@weavecode/weave 0.1.0 → 0.1.2

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 (300) hide show
  1. package/node_modules/@weavecode/cli/dist/cli.js +3 -3
  2. package/node_modules/@weavecode/cli/dist/commands/daemon.d.ts +7 -0
  3. package/node_modules/@weavecode/cli/dist/commands/daemon.js +2 -2
  4. package/node_modules/@weavecode/cli/dist/commands/dashboard.d.ts +0 -2
  5. package/node_modules/@weavecode/cli/dist/commands/dashboard.js +2 -1
  6. package/node_modules/@weavecode/cli/dist/commands/doctor.js +1 -1
  7. package/node_modules/@weavecode/cli/dist/commands/init.js +1 -1
  8. package/node_modules/@weavecode/cli/dist/commands/msg.js +2 -2
  9. package/node_modules/@weavecode/cli/dist/commands/scan.js +1 -1
  10. package/node_modules/@weavecode/cli/dist/commands/status.js +2 -2
  11. package/node_modules/@weavecode/cli/dist/i18n/dict/en.js +6 -12
  12. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.d.ts +44 -2
  13. package/node_modules/@weavecode/cli/dist/i18n/dict/zh.js +6 -12
  14. package/node_modules/@weavecode/cli/dist/init/claudemd-gen.d.ts +2 -3
  15. package/node_modules/@weavecode/cli/dist/init/claudemd-gen.js +4 -4
  16. package/node_modules/@weavecode/cli/dist/init/executor.js +3 -3
  17. package/node_modules/@weavecode/cli/dist/init/git-commit.js +1 -1
  18. package/node_modules/@weavecode/cli/dist/init/harnesses/claude.js +7 -7
  19. package/node_modules/@weavecode/cli/dist/init/harnesses/zcode.d.ts +29 -0
  20. package/node_modules/@weavecode/cli/dist/init/harnesses/zcode.js +1 -0
  21. package/node_modules/@weavecode/cli/dist/init/helpers-gen.d.ts +4 -0
  22. package/node_modules/@weavecode/cli/dist/init/helpers-gen.js +1 -20
  23. package/node_modules/@weavecode/cli/dist/init/mcp-gen.d.ts +3 -20
  24. package/node_modules/@weavecode/cli/dist/init/mcp-gen.js +1 -1
  25. package/node_modules/@weavecode/cli/dist/init/prompt.js +4 -4
  26. package/node_modules/@weavecode/cli/dist/init/settings-gen.d.ts +3 -30
  27. package/node_modules/@weavecode/cli/dist/init/settings-gen.js +1 -1
  28. package/node_modules/@weavecode/cli/package.json +5 -5
  29. package/node_modules/@weavecode/core/dist/harness.d.ts +45 -2
  30. package/node_modules/@weavecode/core/dist/harness.js +1 -1
  31. package/node_modules/@weavecode/core/dist/index.d.ts +2 -2
  32. package/node_modules/@weavecode/core/dist/index.js +1 -1
  33. package/node_modules/@weavecode/core/dist/terminal.d.ts +28 -4
  34. package/node_modules/@weavecode/core/dist/terminal.js +1 -1
  35. package/node_modules/@weavecode/core/dist/types.d.ts +188 -19
  36. package/node_modules/@weavecode/core/dist/types.js +1 -1
  37. package/node_modules/@weavecode/core/package.json +1 -1
  38. package/node_modules/@weavecode/harness/dist/claude/assets.d.ts +10 -0
  39. package/node_modules/@weavecode/harness/dist/claude/assets.js +4 -1
  40. package/node_modules/@weavecode/harness/dist/claude/capture.d.ts +15 -3
  41. package/node_modules/@weavecode/harness/dist/claude/capture.js +15 -9
  42. package/node_modules/@weavecode/harness/dist/claude/event-source.d.ts +1 -1
  43. package/node_modules/@weavecode/harness/dist/claude/event-source.js +1 -1
  44. package/node_modules/@weavecode/harness/dist/claude/helpers-gen.d.ts +5 -0
  45. package/node_modules/@weavecode/harness/dist/claude/helpers-gen.js +20 -0
  46. package/node_modules/@weavecode/harness/dist/claude/index.d.ts +10 -1
  47. package/node_modules/@weavecode/harness/dist/claude/index.js +1 -1
  48. package/node_modules/@weavecode/harness/dist/claude/mcp-gen.d.ts +22 -0
  49. package/node_modules/@weavecode/harness/dist/claude/mcp-gen.js +1 -0
  50. package/node_modules/@weavecode/harness/dist/claude/messaging.d.ts +11 -2
  51. package/node_modules/@weavecode/harness/dist/claude/messaging.js +4 -1
  52. package/node_modules/@weavecode/harness/dist/claude/model-aliases.d.ts +39 -0
  53. package/node_modules/@weavecode/harness/dist/claude/model-aliases.js +1 -0
  54. package/node_modules/@weavecode/harness/dist/claude/plan.d.ts +2 -0
  55. package/node_modules/@weavecode/harness/dist/claude/plan.js +1 -0
  56. package/node_modules/@weavecode/harness/dist/claude/questions.js +2 -1
  57. package/node_modules/@weavecode/harness/dist/claude/settings-gen.d.ts +32 -0
  58. package/node_modules/@weavecode/harness/dist/claude/settings-gen.js +1 -0
  59. package/node_modules/@weavecode/harness/dist/claude/side-question.d.ts +12 -0
  60. package/node_modules/@weavecode/harness/dist/claude/side-question.js +1 -0
  61. package/node_modules/@weavecode/harness/dist/claude/statusline/config.d.ts +200 -0
  62. package/node_modules/@weavecode/harness/dist/claude/statusline/config.js +1 -0
  63. package/node_modules/@weavecode/harness/dist/claude/statusline/generator.d.ts +12 -0
  64. package/node_modules/@weavecode/harness/dist/claude/statusline/generator.js +745 -0
  65. package/node_modules/@weavecode/harness/dist/claude/statusline/git-cache.d.ts +10 -0
  66. package/node_modules/@weavecode/harness/dist/claude/statusline/git-cache.js +1 -0
  67. package/node_modules/@weavecode/harness/dist/claude/statusline/surface.d.ts +20 -0
  68. package/node_modules/@weavecode/harness/dist/claude/statusline/surface.js +2 -0
  69. package/node_modules/@weavecode/harness/dist/claude/transcript.d.ts +16 -0
  70. package/node_modules/@weavecode/harness/dist/claude/transcript.js +4 -2
  71. package/node_modules/@weavecode/harness/dist/codex/assets.js +1 -1
  72. package/node_modules/@weavecode/harness/dist/codex/index.d.ts +1 -0
  73. package/node_modules/@weavecode/harness/dist/codex/index.js +1 -1
  74. package/node_modules/@weavecode/harness/dist/codex/mcp.d.ts +30 -0
  75. package/node_modules/@weavecode/harness/dist/codex/mcp.js +1 -0
  76. package/node_modules/@weavecode/harness/dist/codex/messaging.js +1 -1
  77. package/node_modules/@weavecode/harness/dist/driver.d.ts +168 -3
  78. package/node_modules/@weavecode/harness/dist/index.d.ts +1 -0
  79. package/node_modules/@weavecode/harness/dist/index.js +1 -1
  80. package/node_modules/@weavecode/harness/dist/init/generated.d.ts +37 -0
  81. package/node_modules/@weavecode/harness/dist/init/generated.js +2 -0
  82. package/node_modules/@weavecode/harness/dist/registry-wiring.d.ts +3 -1
  83. package/node_modules/@weavecode/harness/dist/zcode/assets.d.ts +8 -0
  84. package/node_modules/@weavecode/harness/dist/zcode/assets.js +1 -0
  85. package/node_modules/@weavecode/harness/dist/zcode/capture.d.ts +36 -0
  86. package/node_modules/@weavecode/harness/dist/zcode/capture.js +3 -0
  87. package/node_modules/@weavecode/harness/dist/zcode/detect.d.ts +2 -0
  88. package/node_modules/@weavecode/harness/dist/zcode/detect.js +1 -0
  89. package/node_modules/@weavecode/harness/dist/zcode/event-source.d.ts +8 -0
  90. package/node_modules/@weavecode/harness/dist/zcode/event-source.js +1 -0
  91. package/node_modules/@weavecode/harness/dist/zcode/index.d.ts +13 -0
  92. package/node_modules/@weavecode/harness/dist/zcode/index.js +1 -0
  93. package/node_modules/@weavecode/harness/dist/zcode/mcp.d.ts +6 -0
  94. package/node_modules/@weavecode/harness/dist/zcode/mcp.js +2 -0
  95. package/node_modules/@weavecode/harness/dist/zcode/messaging.d.ts +13 -0
  96. package/node_modules/@weavecode/harness/dist/zcode/messaging.js +1 -0
  97. package/node_modules/@weavecode/harness/dist/zcode/resume.d.ts +7 -0
  98. package/node_modules/@weavecode/harness/dist/zcode/resume.js +1 -0
  99. package/node_modules/@weavecode/harness/package.json +2 -2
  100. package/node_modules/@weavecode/server/dist/daemon/ai-config.js +2 -2
  101. package/node_modules/@weavecode/server/dist/daemon/ai-context.js +6 -6
  102. package/node_modules/@weavecode/server/dist/daemon/ai-routes.js +4 -4
  103. package/node_modules/@weavecode/server/dist/daemon/api-log.d.ts +48 -0
  104. package/node_modules/@weavecode/server/dist/daemon/api-log.js +3 -0
  105. package/node_modules/@weavecode/server/dist/daemon/auth-routes.js +1 -1
  106. package/node_modules/@weavecode/server/dist/daemon/auto-start.js +6 -6
  107. package/node_modules/@weavecode/server/dist/daemon/capture-routes.js +1 -1
  108. package/node_modules/@weavecode/server/dist/daemon/claude-liveness.js +1 -1
  109. package/node_modules/@weavecode/server/dist/daemon/dashboard-auth.js +2 -2
  110. package/node_modules/@weavecode/server/dist/daemon/data-bus.js +1 -1
  111. package/node_modules/@weavecode/server/dist/daemon/dev-entry.js +1 -1
  112. package/node_modules/@weavecode/server/dist/daemon/fs-browser.js +1 -1
  113. package/node_modules/@weavecode/server/dist/daemon/hook-pipeline.d.ts +13 -1
  114. package/node_modules/@weavecode/server/dist/daemon/hook-pipeline.js +1 -1
  115. package/node_modules/@weavecode/server/dist/daemon/hooks-routes.js +1 -1
  116. package/node_modules/@weavecode/server/dist/daemon/http.js +1 -1
  117. package/node_modules/@weavecode/server/dist/daemon/opener.d.ts +102 -19
  118. package/node_modules/@weavecode/server/dist/daemon/opener.js +97 -7
  119. package/node_modules/@weavecode/server/dist/daemon/port.js +1 -1
  120. package/node_modules/@weavecode/server/dist/daemon/project-harnesses.js +2 -2
  121. package/node_modules/@weavecode/server/dist/daemon/project-updates-refresher.d.ts +4 -3
  122. package/node_modules/@weavecode/server/dist/daemon/project-updates-refresher.js +1 -1
  123. package/node_modules/@weavecode/server/dist/daemon/server.d.ts +15 -0
  124. package/node_modules/@weavecode/server/dist/daemon/server.js +8 -6
  125. package/node_modules/@weavecode/server/dist/daemon/session-probe.d.ts +72 -2
  126. package/node_modules/@weavecode/server/dist/daemon/session-probe.js +1 -1
  127. package/node_modules/@weavecode/server/dist/daemon/settings.d.ts +10 -0
  128. package/node_modules/@weavecode/server/dist/daemon/settings.js +2 -2
  129. package/node_modules/@weavecode/server/dist/daemon/snapshot-refresher.d.ts +7 -1
  130. package/node_modules/@weavecode/server/dist/daemon/snapshot-refresher.js +1 -1
  131. package/node_modules/@weavecode/server/dist/daemon/sse-hub.d.ts +40 -0
  132. package/node_modules/@weavecode/server/dist/daemon/sse-hub.js +1 -0
  133. package/node_modules/@weavecode/server/dist/daemon/start.js +1 -1
  134. package/node_modules/@weavecode/server/dist/daemon/state.js +2 -2
  135. package/node_modules/@weavecode/server/dist/daemon/static.js +1 -1
  136. package/node_modules/@weavecode/server/dist/daemon/terminal-topology-refresher.d.ts +4 -1
  137. package/node_modules/@weavecode/server/dist/daemon/tls.js +1 -1
  138. package/node_modules/@weavecode/server/dist/daemon/toolkit-routes.js +1 -1
  139. package/node_modules/@weavecode/server/dist/db/db.js +38 -2
  140. package/node_modules/@weavecode/server/dist/db/paths.d.ts +4 -0
  141. package/node_modules/@weavecode/server/dist/db/paths.js +1 -1
  142. package/node_modules/@weavecode/server/dist/hooks/answer-keys.js +1 -1
  143. package/node_modules/@weavecode/server/dist/hooks/bus.d.ts +5 -0
  144. package/node_modules/@weavecode/server/dist/hooks/bus.js +1 -1
  145. package/node_modules/@weavecode/server/dist/hooks/dispatcher.js +6 -6
  146. package/node_modules/@weavecode/server/dist/hooks/handlers/webhook.js +1 -1
  147. package/node_modules/@weavecode/server/dist/hooks/headless-runner.js +2 -2
  148. package/node_modules/@weavecode/server/dist/hooks/inbox-socket.d.ts +17 -4
  149. package/node_modules/@weavecode/server/dist/hooks/inbox-socket.js +2 -1
  150. package/node_modules/@weavecode/server/dist/hooks/inbox-worker.d.ts +27 -6
  151. package/node_modules/@weavecode/server/dist/hooks/inbox-worker.js +3 -3
  152. package/node_modules/@weavecode/server/dist/hooks/match.js +1 -1
  153. package/node_modules/@weavecode/server/dist/hooks/message-deliverer.d.ts +200 -13
  154. package/node_modules/@weavecode/server/dist/hooks/message-deliverer.js +3 -2
  155. package/node_modules/@weavecode/server/dist/hooks/mirror.d.ts +9 -4
  156. package/node_modules/@weavecode/server/dist/hooks/mirror.js +4 -4
  157. package/node_modules/@weavecode/server/dist/hooks/plugin-installer.js +3 -3
  158. package/node_modules/@weavecode/server/dist/hooks/plugin-loader.js +1 -1
  159. package/node_modules/@weavecode/server/dist/hooks/plugin-project-state.js +1 -1
  160. package/node_modules/@weavecode/server/dist/hooks/prompt-flusher.js +1 -1
  161. package/node_modules/@weavecode/server/dist/hooks/promptbox.d.ts +13 -0
  162. package/node_modules/@weavecode/server/dist/hooks/promptbox.js +8 -8
  163. package/node_modules/@weavecode/server/dist/hooks/push-notify.js +2 -2
  164. package/node_modules/@weavecode/server/dist/hooks/question-tracker.d.ts +6 -4
  165. package/node_modules/@weavecode/server/dist/hooks/question-tracker.js +1 -1
  166. package/node_modules/@weavecode/server/dist/hooks/registry.js +1 -1
  167. package/node_modules/@weavecode/server/dist/hooks/resume-runner.js +1 -1
  168. package/node_modules/@weavecode/server/dist/hooks/sequence-engine.js +1 -1
  169. package/node_modules/@weavecode/server/dist/hooks/session-purge.d.ts +7 -0
  170. package/node_modules/@weavecode/server/dist/hooks/session-purge.js +1 -1
  171. package/node_modules/@weavecode/server/dist/hooks/session-sweeper.d.ts +5 -8
  172. package/node_modules/@weavecode/server/dist/hooks/session-sweeper.js +1 -1
  173. package/node_modules/@weavecode/server/dist/hooks/side-questions.d.ts +41 -0
  174. package/node_modules/@weavecode/server/dist/hooks/side-questions.js +1 -0
  175. package/node_modules/@weavecode/server/dist/hooks/toolkit-scan.js +1 -1
  176. package/node_modules/@weavecode/server/dist/hooks/toolkit.d.ts +8 -0
  177. package/node_modules/@weavecode/server/dist/hooks/toolkit.js +5 -5
  178. package/node_modules/@weavecode/server/dist/hooks/watch-engine.d.ts +7 -0
  179. package/node_modules/@weavecode/server/dist/hooks/watch-engine.js +1 -1
  180. package/node_modules/@weavecode/server/dist/index.d.ts +1 -1
  181. package/node_modules/@weavecode/server/dist/install/apply-update.d.ts +1 -1
  182. package/node_modules/@weavecode/server/dist/install/apply-update.js +1 -1
  183. package/node_modules/@weavecode/server/dist/install/capabilities.d.ts +10 -0
  184. package/node_modules/@weavecode/server/dist/install/capabilities.js +1 -1
  185. package/node_modules/@weavecode/server/dist/install/codex-toml.d.ts +8 -26
  186. package/node_modules/@weavecode/server/dist/install/codex-toml.js +1 -1
  187. package/node_modules/@weavecode/server/dist/install/file-assets.js +1 -1
  188. package/node_modules/@weavecode/server/dist/install/fingerprint.d.ts +5 -1
  189. package/node_modules/@weavecode/server/dist/install/fingerprint.js +1 -1
  190. package/node_modules/@weavecode/server/dist/install/git-classify.d.ts +30 -0
  191. package/node_modules/@weavecode/server/dist/install/git-classify.js +1 -0
  192. package/node_modules/@weavecode/server/dist/install/global-config.d.ts +2 -4
  193. package/node_modules/@weavecode/server/dist/install/global-config.js +1 -2
  194. package/node_modules/@weavecode/server/dist/install/global-file-assets.js +1 -1
  195. package/node_modules/@weavecode/server/dist/install/init-files.d.ts +46 -0
  196. package/node_modules/@weavecode/server/dist/install/init-files.js +2 -0
  197. package/node_modules/@weavecode/server/dist/install/install-ledger.js +1 -1
  198. package/node_modules/@weavecode/server/dist/install/installer.d.ts +3 -5
  199. package/node_modules/@weavecode/server/dist/install/installer.js +1 -3
  200. package/node_modules/@weavecode/server/dist/install/library-index.js +1 -1
  201. package/node_modules/@weavecode/server/dist/install/mcp-rows.d.ts +5 -5
  202. package/node_modules/@weavecode/server/dist/install/mcp-rows.js +1 -1
  203. package/node_modules/@weavecode/server/dist/install/plugin-install.js +1 -1
  204. package/node_modules/@weavecode/server/dist/install/plugin-rows.js +1 -1
  205. package/node_modules/@weavecode/server/dist/install/plugin-templates.js +1 -1
  206. package/node_modules/@weavecode/server/dist/install/project-config.d.ts +0 -2
  207. package/node_modules/@weavecode/server/dist/install/project-config.js +2 -2
  208. package/node_modules/@weavecode/server/dist/install/reader.js +1 -1
  209. package/node_modules/@weavecode/server/dist/install/scan-cache.js +1 -1
  210. package/node_modules/@weavecode/server/dist/install/scanner.js +1 -1
  211. package/node_modules/@weavecode/server/dist/install/settings-mcp.js +2 -2
  212. package/node_modules/@weavecode/server/dist/install/updates.d.ts +17 -5
  213. package/node_modules/@weavecode/server/dist/install/updates.js +1 -1
  214. package/node_modules/@weavecode/server/dist/market/builtin.js +1 -1
  215. package/node_modules/@weavecode/server/dist/market/identity.js +1 -1
  216. package/node_modules/@weavecode/server/dist/market/import.js +2 -2
  217. package/node_modules/@weavecode/server/dist/market/refresh.js +1 -1
  218. package/node_modules/@weavecode/server/dist/market/resolve.js +1 -1
  219. package/node_modules/@weavecode/server/dist/market/updates.js +1 -1
  220. package/node_modules/@weavecode/server/dist/registry.js +2 -2
  221. package/node_modules/@weavecode/server/dist/repositories/hook-dispatches.js +5 -5
  222. package/node_modules/@weavecode/server/dist/repositories/hook-events.d.ts +7 -0
  223. package/node_modules/@weavecode/server/dist/repositories/hook-events.js +2 -2
  224. package/node_modules/@weavecode/server/dist/repositories/hook-rules.js +4 -4
  225. package/node_modules/@weavecode/server/dist/repositories/libraries.js +1 -1
  226. package/node_modules/@weavecode/server/dist/repositories/plugin-states.js +1 -1
  227. package/node_modules/@weavecode/server/dist/repositories/projects.d.ts +7 -0
  228. package/node_modules/@weavecode/server/dist/repositories/projects.js +2 -2
  229. package/node_modules/@weavecode/server/dist/repositories/push-subscriptions.js +2 -2
  230. package/node_modules/@weavecode/server/dist/repositories/session-watches.js +4 -4
  231. package/node_modules/@weavecode/server/dist/repositories/sessions.d.ts +32 -8
  232. package/node_modules/@weavecode/server/dist/repositories/sessions.js +2 -2
  233. package/node_modules/@weavecode/server/dist/repositories/side-questions.d.ts +50 -0
  234. package/node_modules/@weavecode/server/dist/repositories/side-questions.js +6 -0
  235. package/node_modules/@weavecode/server/dist/repositories/uploads.d.ts +66 -0
  236. package/node_modules/@weavecode/server/dist/repositories/uploads.js +7 -0
  237. package/node_modules/@weavecode/server/dist/statusline/cache-sweeper.js +1 -1
  238. package/node_modules/@weavecode/server/dist/statusline/config.d.ts +4 -198
  239. package/node_modules/@weavecode/server/dist/statusline/config.js +1 -1
  240. package/node_modules/@weavecode/server/dist/statusline/generator.d.ts +5 -0
  241. package/node_modules/@weavecode/server/dist/statusline/generator.js +1 -676
  242. package/node_modules/@weavecode/server/dist/statusline/manager.d.ts +7 -5
  243. package/node_modules/@weavecode/server/dist/statusline/manager.js +3 -4
  244. package/node_modules/@weavecode/server/dist/surfaces.d.ts +11 -1
  245. package/node_modules/@weavecode/server/dist/surfaces.js +1 -1
  246. package/node_modules/@weavecode/server/dist/watch/cache.js +1 -1
  247. package/node_modules/@weavecode/server/dist/watch/classifier.js +1 -1
  248. package/node_modules/@weavecode/server/dist/watch/plugin-mods.js +1 -1
  249. package/node_modules/@weavecode/server/dist/watch/sync-scheduler.d.ts +8 -4
  250. package/node_modules/@weavecode/server/dist/watch/sync-scheduler.js +1 -1
  251. package/node_modules/@weavecode/server/dist/watch/watch-service.js +1 -1
  252. package/node_modules/@weavecode/server/package.json +4 -4
  253. package/node_modules/@weavecode/server/web/dist/assets/index-CHWbLAje.js +594 -0
  254. package/node_modules/@weavecode/server/web/dist/assets/index-D0s5v8QS.css +11 -0
  255. package/node_modules/@weavecode/server/web/dist/index.html +14 -2
  256. package/node_modules/@weavecode/templates/dist/resources/weave-market/plugins/core-skills/weave-plugin-creator/skills/weave-plugin-creator/SKILL.md +2 -2
  257. package/node_modules/@weavecode/templates/package.json +2 -2
  258. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/README.md +50 -32
  259. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/build/index.d.ts +86 -40
  260. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/build/index.es.js +860 -353
  261. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/build/index.js +860 -353
  262. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-cms/node_modules/asn1js/package.json +20 -17
  263. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/README.md +50 -32
  264. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/build/index.d.ts +86 -40
  265. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/build/index.es.js +860 -353
  266. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/build/index.js +860 -353
  267. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-csr/node_modules/asn1js/package.json +20 -17
  268. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/README.md +50 -32
  269. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/build/index.d.ts +86 -40
  270. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/build/index.es.js +860 -353
  271. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/build/index.js +860 -353
  272. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-ecc/node_modules/asn1js/package.json +20 -17
  273. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/README.md +50 -32
  274. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/build/index.d.ts +86 -40
  275. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/build/index.es.js +860 -353
  276. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/build/index.js +860 -353
  277. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-pkcs9/node_modules/asn1js/package.json +20 -17
  278. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/README.md +50 -32
  279. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/build/index.d.ts +86 -40
  280. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/build/index.es.js +860 -353
  281. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/build/index.js +860 -353
  282. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-rsa/node_modules/asn1js/package.json +20 -17
  283. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/README.md +50 -32
  284. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/build/index.d.ts +86 -40
  285. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/build/index.es.js +860 -353
  286. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/build/index.js +860 -353
  287. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-schema/node_modules/asn1js/package.json +20 -17
  288. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/README.md +50 -32
  289. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/build/index.d.ts +86 -40
  290. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/build/index.es.js +860 -353
  291. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/build/index.js +860 -353
  292. package/node_modules/selfsigned/node_modules/@peculiar/x509/node_modules/@peculiar/asn1-x509/node_modules/asn1js/package.json +20 -17
  293. package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/README.md +50 -32
  294. package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/build/index.d.ts +86 -40
  295. package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/build/index.es.js +860 -353
  296. package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/build/index.js +860 -353
  297. package/node_modules/selfsigned/node_modules/pkijs/node_modules/asn1js/package.json +20 -17
  298. package/package.json +6 -6
  299. package/node_modules/@weavecode/server/web/dist/assets/index-BOzaRlQE.js +0 -560
  300. package/node_modules/@weavecode/server/web/dist/assets/index-ChX8G8cT.css +0 -11
@@ -15,8 +15,18 @@ export interface CategorySurface {
15
15
  export interface CategoryCapability {
16
16
  surfaces: CategorySurface[];
17
17
  }
18
+ /**
19
+ * 某 harness 的 statusline 面:`tui` 答「TUI 里能不能注入」(今天只有 claude
20
+ * 能),`segments` 是它能渲染的块。缺席 = 该 harness 没有 statusline 概念。
21
+ */
22
+ export interface StatuslineCapability {
23
+ harness: Harness;
24
+ tui: 'injectable' | 'none';
25
+ segments: string[];
26
+ }
18
27
  /** `GET /capabilities` 响应体(web 镜像于 api.ts,唯一事实源在这里)。 */
19
28
  export interface InstallCapabilities {
20
29
  categories: Record<InstallCategory, CategoryCapability>;
30
+ statusline: StatuslineCapability[];
21
31
  }
22
32
  export declare function installCapabilities(): InstallCapabilities;
@@ -1 +1 @@
1
- import i from"node:path";import{homedir as l}from"node:os";import{HARNESS_KEYS as f}from"@weavecode/core";import{FILE_ASSET_SPECS as m,FILE_ASSET_CATEGORIES as S}from"./file-assets.js";import{assetSurfaces as a}from"../surfaces.js";function u(t,c){return i.join("~",i.relative(c,t)).split(i.sep).join("/")}export function installCapabilities(){const t=l(),c={};for(const s of S){const r=m[s].dirs,e=[];for(const o of f){const n=r[o];if(!n)continue;const p=[];n.project&&p.push("project"),n.user&&p.push("user"),p.length>0&&e.push({harness:o,scopes:p})}c[s]={surfaces:e}}return c.skill={surfaces:a().map(s=>{const r=[],e={};s.projectSkillsDir()&&(r.push("project"),e.project=s.projectSkillsDir());const o=s.globalSkillsRoots(t)[0];return o&&(r.push("user"),e.user=u(o,t)),{harness:s.harness,scopes:r,dest:e}})},c.mcp={surfaces:a().map(s=>{const r={},e=s.mcpDest("project",t),o=s.mcpDest("user",t);return e&&(r.project=e),o&&(r.user=u(o,t)),{harness:s.harness,scopes:s.mcpScopes(),dest:r}}).filter(s=>s.scopes.length>0)},{categories:c}}
1
+ import p from"node:path";import{homedir as m}from"node:os";import{HARNESS_KEYS as l}from"@weavecode/core";import{FILE_ASSET_SPECS as S,FILE_ASSET_CATEGORIES as h}from"./file-assets.js";import{assetSurfaces as u,statuslineSurfaces as j}from"../surfaces.js";function f(r,c){return p.join("~",p.relative(c,r)).split(p.sep).join("/")}export function installCapabilities(){const r=m(),c={};for(const s of h){const t=S[s].dirs,e=[];for(const o of l){const n=t[o];if(!n)continue;const i=[];n.project&&i.push("project"),n.user&&i.push("user"),i.length>0&&e.push({harness:o,scopes:i})}c[s]={surfaces:e}}c.skill={surfaces:u().map(s=>{const t=[],e={};s.projectSkillsDir()&&(t.push("project"),e.project=s.projectSkillsDir());const o=s.globalSkillsRoots(r)[0];return o&&(t.push("user"),e.user=f(o,r)),{harness:s.harness,scopes:t,dest:e}})},c.mcp={surfaces:u().map(s=>{const t={},e=s.mcpDest("project",r),o=s.mcpDest("user",r);return e&&(t.project=e),o&&(t.user=f(o,r)),{harness:s.harness,scopes:s.mcpScopes(),dest:t}}).filter(s=>s.scopes.length>0)};const a=j().map(({harness:s,surface:t})=>({harness:s,tui:t.tui,segments:[...t.segments]}));return{categories:c,statusline:a}}
@@ -1,38 +1,20 @@
1
1
  import type { McpServerConfig } from './installer.js';
2
2
  /**
3
- * Codex config.toml 的 **fs 侧**(路径解析 + MCP servers 表示法)。
4
- *
5
- * 行级增量编辑器(纯文本层)已下沉 @weavecode/harness 的 `codex/toml.ts`
6
- * (P2 专属格式下沉);本模块原位置 re-export 下沉符号,存量 import 零改动。
7
- * MCP 表示法的下沉留后续批次(其类型 McpServerConfig 仍住 server)。
3
+ * Codex config.toml 的 server 侧入口:路径解析 + 把 harness 里的表示法绑上默认
4
+ * 路径。行级编辑与 `[mcp_servers.<name>]` 这一形都住 @weavecode/harness
5
+ * (`codex/toml.ts` / `codex/mcp.ts`),本模块原位置 re-export,存量 import 零改动。
8
6
  */
9
- export { CodexTomlCorruptError, parseDottedKey, sectionHeaderKey, renderTomlKey, renderTomlHeader, renderTomlString, splitTomlSections, upsertTomlSection, removeTomlSection, parseSectionEntries, upsertCodexPluginEnabledInText, } from '@weavecode/harness';
7
+ export { CodexTomlCorruptError, parseDottedKey, sectionHeaderKey, renderTomlKey, renderTomlHeader, renderTomlString, splitTomlSections, upsertTomlSection, removeTomlSection, parseSectionEntries, upsertCodexPluginEnabledInText, readCodexMcpFromText, upsertCodexMcpInText, removeCodexMcpFromText, } from '@weavecode/harness';
10
8
  export type { TomlSection } from '@weavecode/harness';
11
- /** Absolute path of the Codex user config (`~/.codex/config.toml`),
12
- * respecting the test override. 批 4a:路径本体在 AssetSurface(`userConfigFile`)。 */
9
+ /** Absolute path of the Codex user config (`~/.codex/config.toml`).
10
+ * 批 4a:路径本体在 AssetSurface(`userConfigFile`)。 */
13
11
  export declare function codexConfigFile(home?: string): string;
14
- /** Read the `mcp_servers` map from config.toml text (empty when absent or
15
- * unparseable). stdio servers only — entries without a `command` (e.g. remote
16
- * url servers) are skipped. */
17
- export declare function readCodexMcpFromText(text: string): Record<string, McpServerConfig>;
18
- /** Insert or replace an `[mcp_servers.<name>]` entry in config.toml text,
19
- * preserving everything else. Merge-validated: if preserving user-added keys
20
- * produces invalid TOML, the section is written clean instead. */
21
- export declare function upsertCodexMcpInText(text: string, name: string, config: McpServerConfig): string;
22
- /** Remove an `[mcp_servers.<name>]` entry (with its sub-sections) from
23
- * config.toml text. Returns whether a section was removed. */
24
- export declare function removeCodexMcpFromText(text: string, name: string): {
25
- text: string;
26
- removed: boolean;
27
- };
28
- export declare function setCodexConfigFileOverride(file: string | null): void;
29
12
  /** Read MCP servers from `~/.codex/config.toml` (empty when absent/corrupt). */
30
13
  export declare function readCodexMcpServers(file?: string): Promise<Record<string, McpServerConfig>>;
31
14
  /** Whether an `[mcp_servers.<name>]` section exists (cheap line-level check). */
32
15
  export declare function codexMcpExists(name: string, file?: string): Promise<boolean>;
33
- /** Insert or replace an MCP server in `~/.codex/config.toml`. Refuses to
34
- * write a file that does not parse (protects the user's hand-written config);
35
- * creates the file when absent. */
16
+ /** Insert or replace an MCP server in `~/.codex/config.toml` (refuses a
17
+ * config that does not parse; creates the file when absent). */
36
18
  export declare function writeCodexMcpServer(name: string, config: McpServerConfig, file?: string): Promise<void>;
37
19
  /** Remove an MCP server section from `~/.codex/config.toml`. Returns whether
38
20
  * a section was removed (false = was not configured). */
@@ -1 +1 @@
1
- import{readFile as p,writeFile as x,access as C,mkdir as M}from"node:fs/promises";import{homedir as $}from"node:os";import b from"node:path";import{parse as m}from"smol-toml";import{assetSurfaceFor as E}from"../surfaces.js";import{CodexTomlCorruptError as l,parseSectionEntries as w,removeTomlSection as j,renderTomlHeader as A,renderTomlKey as F,renderTomlString as d,sameKey as y,splitTomlSections as v,upsertTomlSection as h}from"@weavecode/harness";export{CodexTomlCorruptError,parseDottedKey,sectionHeaderKey,renderTomlKey,renderTomlHeader,renderTomlString,splitTomlSections,upsertTomlSection,removeTomlSection,parseSectionEntries,upsertCodexPluginEnabledInText}from"@weavecode/harness";export function codexConfigFile(r=$()){return S??E("codex").userConfigFile(r)}export function readCodexMcpFromText(r){let e;try{e=m(r)}catch{return{}}const n=e.mcp_servers;if(!n||typeof n!="object"||Array.isArray(n))return{};const t={};for(const[s,o]of Object.entries(n)){const c=O(o);c&&(t[s]=c)}return t}function O(r){if(!r||typeof r!="object"||Array.isArray(r))return null;const e=r;if(typeof e.command!="string")return null;const n={command:e.command};if(Array.isArray(e.args)){const t=e.args.filter(s=>typeof s=="string");t.length>0&&(n.args=t)}if(e.env&&typeof e.env=="object"&&!Array.isArray(e.env)){const t={};for(const[s,o]of Object.entries(e.env))typeof o=="string"&&(t[s]=o);Object.keys(t).length>0&&(n.env=t)}return n}function T(r,e,n,t,s){const o=[`command = ${d(e.command)}`];if(e.args&&e.args.length>0&&o.push(`args = [${e.args.map(d).join(", ")}]`),s&&n){const i=new Set(["command","args","env"]);for(const[a,u]of w(n.lines.slice(1)))i.has(a)||o.push(u)}const c=Object.entries(e.env??{}),f=s&&t?w(t.lines.slice(1)).filter(([i])=>!(i in(e.env??{}))):[];if(c.length>0||f.length>0){o.push(""),o.push(A([...r,"env"]));for(const[i,a]of c)o.push(`${F(i)} = ${d(a)}`);for(const[,i]of f)o.push(i)}return o}export function upsertCodexMcpInText(r,e,n){const t=["mcp_servers",e],s=_(r);if(s)throw s;const o=v(r),c=o.find(a=>y(a.key,t)),f=o.find(a=>y(a.key,[...t,"env"])),i=h(r,t,T(t,n,c,f,!0));try{return m(i),i}catch{const a=h(r,t,T(t,n,c,f,!1));try{return m(a),a}catch(u){throw new l(`unable to produce valid TOML for [mcp_servers.${e}]: ${u instanceof Error?u.message:String(u)}`)}}}export function removeCodexMcpFromText(r,e){return j(r,["mcp_servers",e])}function _(r){return v(r)[0].lines.find(e=>/^\s*mcp_servers\s*=/.test(e))?new l('~/.codex/config.toml defines "mcp_servers" as an inline value \u2014 weave only manages the [mcp_servers.<name>] section form'):null}let S=null;export function setCodexConfigFileOverride(r){S=r}async function k(r){try{return await p(r,"utf-8")}catch{return""}}async function g(r){try{return await C(r),!0}catch{return!1}}export async function readCodexMcpServers(r=codexConfigFile()){return await g(r)?readCodexMcpFromText(await p(r,"utf-8")):{}}export async function codexMcpExists(r,e=codexConfigFile()){return await g(e)?K(await p(e,"utf-8"),["mcp_servers",r]):!1}function K(r,e){return v(r).some(n=>y(n.key,e))}export async function writeCodexMcpServer(r,e,n=codexConfigFile()){const t=await k(n);if(t.trim()!=="")try{m(t)}catch(s){throw new l(`${n} is not valid TOML \u2014 refusing to write: ${s instanceof Error?s.message:String(s)}`)}await M(b.dirname(n),{recursive:!0}),await x(n,upsertCodexMcpInText(t,r,e),"utf-8")}export async function removeCodexMcpServer(r,e=codexConfigFile()){if(!await g(e))return!1;const n=await p(e,"utf-8");try{m(n)}catch(o){throw new l(`${e} is not valid TOML \u2014 refusing to write: ${o instanceof Error?o.message:String(o)}`)}const{text:t,removed:s}=removeCodexMcpFromText(n,r);return s&&await x(e,t,"utf-8"),s}
1
+ import{homedir as t}from"node:os";import{assetSurfaceFor as x}from"../surfaces.js";import{codexMcpExists as c,readCodexMcpServers as d,removeCodexMcpServer as n,writeCodexMcpServer as p}from"@weavecode/harness";export{CodexTomlCorruptError,parseDottedKey,sectionHeaderKey,renderTomlKey,renderTomlHeader,renderTomlString,splitTomlSections,upsertTomlSection,removeTomlSection,parseSectionEntries,upsertCodexPluginEnabledInText,readCodexMcpFromText,upsertCodexMcpInText,removeCodexMcpFromText}from"@weavecode/harness";export function codexConfigFile(e=t()){return x("codex").userConfigFile(e)}export function readCodexMcpServers(e=codexConfigFile()){return d(e)}export function codexMcpExists(e,r=codexConfigFile()){return c(e,r)}export function writeCodexMcpServer(e,r,o=codexConfigFile()){return p(e,r,o)}export function removeCodexMcpServer(e,r=codexConfigFile()){return n(e,r)}
@@ -1 +1 @@
1
- import{assetSurfaceFor as s}from"../surfaces.js";export{FILE_ASSET_SPECS,FILE_ASSET_CATEGORIES,isFileAssetCategory}from"@weavecode/harness";export function fileAssetTargetDir(r,e,t,i,o){return s(e).targetDir(r,t,i,o)}
1
+ import{assetSurfaceFor as i}from"../surfaces.js";export{FILE_ASSET_SPECS,FILE_ASSET_CATEGORIES,isFileAssetCategory}from"@weavecode/harness";export function fileAssetTargetDir(r,e,t,o,S){return i(e).targetDir(r,t,o,S)}
@@ -10,7 +10,11 @@ export interface FingerprintCacheEntry {
10
10
  * Empty / missing directories hash to a constant.
11
11
  */
12
12
  export declare function hashSkillDir(dir: string, skipNames?: Set<string>): Promise<string>;
13
- /** Max mtime (ms) across all files in a tree — cache-invalidation signal. */
13
+ /**
14
+ * Max mtime (ms) across all files in a tree — cache-invalidation signal.
15
+ * 逐文件 stat 是这一轮的全部成本(Windows 上每次往返 ~0.1ms、一百来个技能文件
16
+ * 串起来就是 100ms+),故整层并行发起,只保序不排队。
17
+ */
14
18
  export declare function maxMtimeDir(dir: string, skipNames?: Set<string>): Promise<number>;
15
19
  /** Stable hash of an MCP server config (sorted keys → JSON → sha256). */
16
20
  export declare function hashMcpConfig(config: McpServerConfig): string;
@@ -1 +1 @@
1
- import{readdir as h,readFile as m,stat as l}from"node:fs/promises";import{createHash as c}from"node:crypto";import n from"node:path";const f=new Set([".weave",".git","node_modules"]);export async function hashSkillDir(a,e=f){const t=c("sha256"),r=[];await u(a,a,r,e),r.sort((i,s)=>i.rel.localeCompare(s.rel));for(const i of r){t.update(i.rel),t.update("\0");let s;try{s=await m(i.abs)}catch{continue}t.update(s),t.update("\0")}return t.digest("hex")}async function u(a,e,t,r){let i;try{i=await h(e,{withFileTypes:!0})}catch{return}for(const s of i)s.name.startsWith(".")&&r.has(s.name)||(!r.has(s.name)&&s.isDirectory()?await u(a,n.join(e,s.name),t,r):s.isFile()&&t.push({rel:n.relative(a,e).replace(/\\/g,"/")+"/"+s.name,abs:n.join(e,s.name)}))}export async function maxMtimeDir(a,e=f){let t=0,r;try{r=await h(a,{withFileTypes:!0})}catch{return 0}for(const i of r){if(i.name.startsWith(".")&&e.has(i.name))continue;const s=n.join(a,i.name);if(i.isDirectory())t=Math.max(t,await maxMtimeDir(s,e));else if(i.isFile())try{const p=await l(s);t=Math.max(t,p.mtimeMs)}catch{}}return t}export function hashMcpConfig(a){return c("sha256").update(JSON.stringify(o(a))).digest("hex")}export async function hashFile(a){try{const e=await m(a);return c("sha256").update(e).digest("hex")}catch{return"missing"}}function o(a){if(Array.isArray(a))return a.map(o);if(a&&typeof a=="object"){const e={};for(const t of Object.keys(a).sort())e[t]=o(a[t]);return e}return a}export class FingerprintCache{cache=new Map;fileCache=new Map;async get(e){const t=await maxMtimeDir(e),r=this.cache.get(e);if(r&&r.maxMtime===t)return r.hash;const i=await hashSkillDir(e);return this.cache.set(e,{maxMtime:t,hash:i}),i}async getFile(e){let t;try{t=(await l(e)).mtimeMs}catch{return"missing"}const r=this.fileCache.get(e);if(r&&r.maxMtime===t)return r.hash;const i=await hashFile(e);return this.fileCache.set(e,{maxMtime:t,hash:i}),i}invalidate(e){this.cache.delete(e)}clear(){this.cache.clear(),this.fileCache.clear()}}
1
+ import{readdir as m,readFile as u,stat as l}from"node:fs/promises";import{createHash as h}from"node:crypto";import c from"node:path";const f=new Set([".weave",".git","node_modules"]);export async function hashSkillDir(e,t=f){const a=h("sha256"),r=[];await p(e,e,r,t),r.sort((n,i)=>n.rel.localeCompare(i.rel));for(const n of r){a.update(n.rel),a.update("\0");let i;try{i=await u(n.abs)}catch{continue}a.update(i),a.update("\0")}return a.digest("hex")}async function p(e,t,a,r){let n;try{n=await m(t,{withFileTypes:!0})}catch{return}const i=[];for(const s of n)s.name.startsWith(".")&&r.has(s.name)||(!r.has(s.name)&&s.isDirectory()?i.push(p(e,c.join(t,s.name),a,r)):s.isFile()&&a.push({rel:c.relative(e,t).replace(/\\/g,"/")+"/"+s.name,abs:c.join(t,s.name)}));await Promise.all(i)}export async function maxMtimeDir(e,t=f){let a;try{a=await m(e,{withFileTypes:!0})}catch{return 0}return(await Promise.all(a.map(async n=>{if(n.name.startsWith(".")&&t.has(n.name))return 0;const i=c.join(e,n.name);if(n.isDirectory())return maxMtimeDir(i,t);if(!n.isFile())return 0;try{return(await l(i)).mtimeMs}catch{return 0}}))).reduce((n,i)=>Math.max(n,i),0)}export function hashMcpConfig(e){return h("sha256").update(JSON.stringify(o(e))).digest("hex")}export async function hashFile(e){try{const t=await u(e);return h("sha256").update(t).digest("hex")}catch{return"missing"}}function o(e){if(Array.isArray(e))return e.map(o);if(e&&typeof e=="object"){const t={};for(const a of Object.keys(e).sort())t[a]=o(e[a]);return t}return e}export class FingerprintCache{cache=new Map;fileCache=new Map;async get(t){const a=await maxMtimeDir(t),r=this.cache.get(t);if(r&&r.maxMtime===a)return r.hash;const n=await hashSkillDir(t);return this.cache.set(t,{maxMtime:a,hash:n}),n}async getFile(t){let a;try{a=(await l(t)).mtimeMs}catch{return"missing"}const r=this.fileCache.get(t);if(r&&r.maxMtime===a)return r.hash;const n=await hashFile(t);return this.fileCache.set(t,{maxMtime:a,hash:n}),n}invalidate(t){this.cache.delete(t)}clear(){this.cache.clear(),this.fileCache.clear()}}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * 项目内路径「进不进 git」的分类——同步域自动/手动分界的唯一判据。
3
+ *
4
+ * 用户裁决:**不进 git 的自动同步;进 git 的仍走 `weave init` 生成 + commit**,
5
+ * 同步域只检测漂移、dashboard 提醒用户去终端跑 `weave init`(不代写)。
6
+ *
7
+ * 「会进 git」= tracked ∪ untracked-but-not-ignored(后者下次 `git add` 就进)。
8
+ * 所以 `check-ignore` 单独用不够——tracked 文件也可能命中 ignore 规则,判序恒为
9
+ * 先 tracked、后 ignored。非 git 仓库全算「不进 git」。
10
+ *
11
+ * 一轮 sweep 建一次(`gitClassify`),别逐文件起进程。
12
+ */
13
+ /** 一条路径的同步归类。 */
14
+ export type SyncClass = 'auto' | 'manual';
15
+ export type GitPathKind = 'tracked' | 'ignored' | 'untracked' | 'outside';
16
+ export interface GitClassify {
17
+ /** 相对路径 → 实际 git 状态。 */
18
+ kindOf(relPath: string): GitPathKind;
19
+ /** `auto` = 不进 git(代写无害、自愈);`manual` = 会进 git(只报不写)。 */
20
+ classOf(relPath: string): SyncClass;
21
+ }
22
+ /**
23
+ * 对给定的项目相对路径(posix 分隔)做一次批量分类。
24
+ *
25
+ * 两条查询**并行**起:`ls-files` 取 tracked、`check-ignore --stdin` 取 ignored,
26
+ * 都没命中的在仓库里即 untracked。原先串行三轮(ls-files → rev-parse → check-ignore)
27
+ * 在 Windows 上是 `/projects/:id/updates` 的全部耗时(实测 ~450ms,每个 git 子进程
28
+ * 约 150ms);仓库探测改看 `ls-files` 的退出码,省掉 `rev-parse` 那一轮。
29
+ */
30
+ export declare function gitClassify(projectPath: string, relPaths: readonly string[]): Promise<GitClassify>;
@@ -0,0 +1 @@
1
+ import{spawn as l}from"node:child_process";function c(o,s,t){return new Promise(n=>{const e=l("git",["-C",o,...s],{stdio:[t===void 0?"ignore":"pipe","pipe","ignore"],windowsHide:!0});let d="";e.stdout?.setEncoding("utf-8"),e.stdout?.on("data",r=>{d+=r}),e.on("error",()=>n({stdout:"",ran:!1,code:null})),e.on("close",r=>n({stdout:d,ran:!0,code:r})),t!==void 0&&e.stdin?.end(t)})}function a(o){return o.split("\0").filter(s=>s.length>0)}export async function gitClassify(o,s){const t=[...new Set(s)],n=new Map;if(t.length===0)return u(n);const[e,d]=await Promise.all([c(o,["ls-files","-z","--",...t]),c(o,["check-ignore","-z","--stdin"],t.map(i=>`${i}\0`).join(""))]);if(!e.ran||e.code!==0){for(const i of t)n.set(i,"outside");return u(n)}const r=new Set(a(e.stdout)),f=new Set(a(d.stdout));for(const i of t)n.set(i,r.has(i)?"tracked":f.has(i)?"ignored":"untracked");return u(n)}function u(o){const s=t=>o.get(t)??"outside";return{kindOf:s,classOf:t=>{const n=s(t);return n==="ignored"||n==="outside"?"auto":"manual"}}}
@@ -20,10 +20,8 @@ import { type InstallLinkMode } from '../market/install-link.js';
20
20
  * host config: `~/.claude/settings.json` (`enabledPlugins`) for Claude and
21
21
  * `~/.codex/config.toml` (`[plugins."key"] enabled`) for Codex.
22
22
  */
23
- /** `~/.claude.json` could not be parsed; refuse to write to avoid corruption. */
24
- export declare class ClaudeJsonCorruptError extends Error {
25
- constructor(message: string);
26
- }
23
+ /** `~/.claude.json` 解析不了就拒写(实现在 harness 的 claude 资产面)。 */
24
+ export { ClaudeJsonCorruptError } from '@weavecode/harness';
27
25
  /** Where a global skill came from — used as the grouping key in the UI. */
28
26
  export type GlobalSkillSource = `${Harness}-personal` | `${Harness}-plugin`;
29
27
  /** A single resolved skill directory. `dir` is absolute (may be a symlink). */
@@ -1,2 +1 @@
1
- import{readFile as x,writeFile as N,readdir as d,access as K,stat as P,realpath as G}from"node:fs/promises";import{homedir as f}from"node:os";import l from"node:path";import{AssetNotFoundError as b}from"./installer.js";import{FileTooLargeError as B,MAX_BYTES as D}from"./reader.js";import{assetSurfaceFor as h,assetSurfaces as J,pluginStateFor as S,pluginSurfaceFor as O}from"../surfaces.js";import{installForm as R,linkOrCopy as W,removeInstalled as z}from"../market/install-link.js";export class ClaudeJsonCorruptError extends Error{constructor(e){super(e),this.name="ClaudeJsonCorruptError"}}const I=".claude.json",_=".claude/plugins/installed_plugins.json";function j(){return l.join(f(),I)}function k(){return h("claude").globalSkillsRoots(f())[0]}function L(t=f()){return l.join(t,_)}function X(){return h("claude").userConfigFile(f())}function T(){return h("codex").globalSkillsRoots(f())[0]}function Y(){return h("codex").globalSkillsRoots(f())}function A(){const t=h("codex").pluginCacheDir?.(f());if(!t)throw new Error("codex has no plugin cache surface");return t}export function globalPersonalSkillRootsOwned(){return J().flatMap(t=>t.globalSkillsRoots(f()).map(e=>({harness:t.harness,root:e})))}export function globalPersonalSkillRoots(){return globalPersonalSkillRootsOwned().map(t=>t.root)}async function F(t){try{return await K(t),!0}catch{return!1}}async function y(t){try{return(await P(t)).isDirectory()}catch{return!1}}export async function readGlobalClaudeJson(){const t=j();if(!await F(t))return{};let e;try{e=await x(t,"utf-8")}catch{return{}}let n;try{n=JSON.parse(e)}catch(a){throw new ClaudeJsonCorruptError(`~/.claude.json is not valid JSON \u2014 refusing to write: ${a instanceof Error?a.message:String(a)}`)}if(!n||typeof n!="object"||Array.isArray(n))throw new ClaudeJsonCorruptError("~/.claude.json is not a JSON object \u2014 refusing to write");return n}export async function readGlobalMcpServers(){const t=(await readGlobalClaudeJson()).mcpServers;return!t||typeof t!="object"||Array.isArray(t)?{}:t}async function M(t){await N(j(),`${JSON.stringify(t,null,2)}
2
- `,"utf-8")}export async function writeGlobalMcpServer(t,e){const n=await readGlobalClaudeJson(),a=n.mcpServers??{};a[t]=e,n.mcpServers=a,await M(n)}export async function removeGlobalMcpServer(t){const e=await readGlobalClaudeJson(),n=e.mcpServers??{};t in n&&(delete n[t],e.mcpServers=n,await M(e))}export async function readGlobalSkills(){const t=k();try{const e=await d(t,{withFileTypes:!0}),n=[];for(const a of e)!a.isDirectory()&&!a.isSymbolicLink()||await y(l.join(t,a.name))&&n.push(a.name);return n.sort((a,r)=>a.localeCompare(r))}catch{return[]}}export async function installGlobalSkill(t,e,n="claude"){const a=h(n).globalSkillsRoots(f())[0],r=l.join(a,e);if(await F(r))throw new Error(`Global ${n} skill "${e}" already exists`);return await W(t,r),r}export async function uninstallGlobalSkill(t,e="claude"){const n=h(e).globalSkillsRoots(f())[0];await z(l.join(n,t))}async function C(t=f()){const e=L(t);if(!await F(e))return{};try{const n=JSON.parse(await x(e,"utf-8"));return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}catch{return{}}}async function E(t){if(!await y(t))return[];let e;try{e=await d(t,{withFileTypes:!0})}catch{return[]}const n=[];for(const a of e){if(a.name.startsWith(".")||!a.isDirectory()&&!a.isSymbolicLink())continue;const r=l.join(t,a.name);if(!await y(r))continue;const o=await R(r);o!=="absent"&&n.push({name:a.name,dir:r,form:o})}return n.sort((a,r)=>a.name.localeCompare(r.name))}export async function installedPluginNamespaces(t=f()){const e=(await C(t)).plugins;if(!e||typeof e!="object"||Array.isArray(e))return[];const n=[];for(const[a,r]of Object.entries(e)){const{market:o}=O("claude").parsePluginKey(a);for(const i of Array.isArray(r)?r:[])i&&typeof i.installPath=="string"&&n.push({dir:i.installPath,namespace:o})}return n}async function q(){const t=(await C()).plugins;if(!t||typeof t!="object"||Array.isArray(t))return[];const e=[];for(const[n,a]of Object.entries(t)){const r=Array.isArray(a)?a:[];if(r.length===0)continue;const o=[...r].filter(p=>p&&typeof p.installPath=="string").pop();if(!o?.installPath)continue;const i=await E(l.join(o.installPath,"skills")),{name:s,market:u}=O("claude").parsePluginKey(n);e.push({source:"claude-plugin",label:s,namespace:u,skills:i,pluginKey:n})}return e.sort((n,a)=>n.label.localeCompare(a.label))}async function H(){const t=new Map;for(const e of Y())for(const n of await E(e))t.has(n.name)||t.set(n.name,n);return{source:"codex-personal",label:"Codex \xB7 \u4E2A\u4EBA",skills:[...t.values()].sort((e,n)=>e.name.localeCompare(n.name))}}async function Q(){const t=A();if(!await y(t))return[];const e=[];let n;try{n=await d(t,{withFileTypes:!0})}catch{return[]}for(const a of n){if(!a.isDirectory()&&!a.isSymbolicLink())continue;const r=l.join(t,a.name);let o;try{o=await d(r,{withFileTypes:!0})}catch{continue}for(const i of o){if(!i.isDirectory()&&!i.isSymbolicLink())continue;const s=l.join(r,i.name);let u;try{u=await d(s,{withFileTypes:!0})}catch{continue}const p=u.filter(w=>w.isDirectory()||w.isSymbolicLink());if(p.length===0)continue;const m=p.map(w=>w.name).sort().pop(),c=await E(l.join(s,m,"skills")),g=`${i.name}@${a.name}`;e.push({source:"codex-plugin",label:i.name,namespace:a.name,skills:c,pluginKey:g})}}return e.sort((a,r)=>a.label.localeCompare(r.label))}async function U(){const t=k(),e=await readGlobalSkills(),n=[];for(const a of e){const r=l.join(t,a),o=await R(r);o!=="absent"&&n.push({name:a,dir:r,form:o})}return{source:"claude-personal",label:"Claude Code \xB7 \u4E2A\u4EBA",skills:n}}export async function readGlobalSkillGroups(){const[t,e,n,a,r,o]=await Promise.all([U(),q(),H(),Q(),readClaudePluginEnabled(),readCodexPluginEnabled()]),i=(s,u)=>({...s,enabled:s.pluginKey?u[s.pluginKey]??!1:void 0});return[t,...e.map(s=>i(s,r)),n,...a.map(s=>i(s,o))]}export async function resolveGlobalSkillDir(t,e,n){if(t==="claude-personal"){const c=l.join(k(),e);return await y(c)?c:null}if(t==="codex-personal"){const c=l.join(T(),e);return await y(c)?c:null}if(t==="claude-plugin"){if(!n)return null;const c=(await C()).plugins;if(!c||typeof c!="object"||Array.isArray(c))return null;const g=c[n],w=[...Array.isArray(g)?g:[]].filter($=>$&&typeof $.installPath=="string").pop();if(!w?.installPath)return null;const v=l.join(w.installPath,"skills",e);return await y(v)?v:null}if(!n)return null;const a=n.lastIndexOf("@");if(a<=0)return null;const r=n.slice(0,a),o=n.slice(a+1),i=l.join(A(),o,r);if(!await y(i))return null;let s;try{s=await d(i,{withFileTypes:!0})}catch{return null}const u=s.filter(c=>c.isDirectory()||c.isSymbolicLink());if(u.length===0)return null;const p=u.map(c=>c.name).sort().pop(),m=l.join(i,p,"skills",e);return await y(m)?m:null}function V(t){const e=l.resolve(t),n=f();return J().find(a=>{const r=[...a.globalSkillsRoots(n)],o=a.pluginCacheDir?.(n);return o&&r.push(o),r.some(i=>e===l.resolve(i)||e.startsWith(l.resolve(i)+l.sep))})?.harness??"claude"}export async function listGlobalSkillFiles(t){const e=V(t),n=[],a=async(r,o)=>{let i;try{i=await d(r,{withFileTypes:!0})}catch{return}for(const s of i){if(s.name.startsWith("."))continue;const u=l.join(r,s.name),p=o?`${o}/${s.name}`:s.name;if((s.isDirectory()||s.isSymbolicLink())&&await y(u))await a(u,p);else if(s.isFile()||s.isSymbolicLink())try{const m=await P(u);m.isFile()&&n.push({absPath:u,relPath:p,category:"skill",agent:e,mtimeMs:m.mtimeMs})}catch{}}};return await a(t,""),n.sort((r,o)=>r.relPath.localeCompare(o.relPath))}export async function readGlobalSkillFile(t,e){const n=l.normalize(e).replace(/\\/g,"/");if(l.isAbsolute(e))throw new b(`Absolute paths are not allowed: "${e}"`);if(n.split("/").some(u=>u===".."))throw new b(`Path traversal is not allowed: "${e}"`);const a=l.join(t,n);let r;try{r=await P(a)}catch{throw new b(`File not found: "${e}"`)}if(!r.isFile())throw new b(`Not a file: "${e}"`);if(r.size>D)throw new B(`File exceeds ${D} bytes: "${e}"`);let o=t,i=a;try{[o,i]=await Promise.all([G(t),G(a)])}catch{throw new b(`File not found: "${e}"`)}const s=o.endsWith(l.sep)?o:o+l.sep;if(i!==o&&!i.startsWith(s))throw new b(`Resolved path escapes the skill directory: "${e}"`);return{content:await x(a,"utf-8"),size:r.size}}export async function readClaudePluginEnabled(){return S("claude").readGlobalEnabled()}export async function writeClaudePluginEnabled(t,e){return S("claude").writeGlobalEnabled(t,e)}export async function readCodexPluginEnabled(){return S("codex").readGlobalEnabled()}export async function writeCodexPluginEnabled(t,e){return S("codex").writeGlobalEnabled(t,e)}export{k as globalSkillsPath,j as claudeJsonPath,L as claudePluginsJsonPath,X as claudeSettingsPath,T as codexSkillsPath,A as codexPluginsCachePath};
1
+ import{readFile as E,readdir as h,access as J,stat as x,realpath as G}from"node:fs/promises";import{homedir as c}from"node:os";import l from"node:path";import{AssetNotFoundError as g}from"./installer.js";import{readClaudeJson as N}from"@weavecode/harness";import{FileTooLargeError as W,MAX_BYTES as v}from"./reader.js";import{assetSurfaceFor as y,assetSurfaces as R,pluginStateFor as k,pluginSurfaceFor as $}from"../surfaces.js";import{installForm as L,linkOrCopy as _,removeInstalled as z}from"../market/install-link.js";export{ClaudeJsonCorruptError}from"@weavecode/harness";const I=".claude.json",U=".claude/plugins/installed_plugins.json";function B(){return l.join(c(),I)}function S(){return y("claude").globalSkillsRoots(c())[0]}function M(t=c()){return l.join(t,U)}function K(){return y("claude").userConfigFile(c())}function O(){return y("codex").globalSkillsRoots(c())[0]}function X(){return y("codex").globalSkillsRoots(c())}function P(){const t=y("codex").pluginCacheDir?.(c());if(!t)throw new Error("codex has no plugin cache surface");return t}export function globalPersonalSkillRootsOwned(){return R().flatMap(t=>t.globalSkillsRoots(c()).map(n=>({harness:t.harness,root:n})))}export function globalPersonalSkillRoots(){return globalPersonalSkillRootsOwned().map(t=>t.root)}async function T(t){try{return await J(t),!0}catch{return!1}}async function m(t){try{return(await x(t)).isDirectory()}catch{return!1}}export function readGlobalClaudeJson(){return N(c())}export async function readGlobalMcpServers(){const t=(await readGlobalClaudeJson()).mcpServers;return!t||typeof t!="object"||Array.isArray(t)?{}:t}export async function writeGlobalMcpServer(t,n){await y("claude").mcpWrite("user","",c(),t,n)}export async function removeGlobalMcpServer(t){await y("claude").mcpRemove("user","",c(),t)}export async function readGlobalSkills(){const t=S();try{const n=await h(t,{withFileTypes:!0}),o=[];for(const e of n)!e.isDirectory()&&!e.isSymbolicLink()||await m(l.join(t,e.name))&&o.push(e.name);return o.sort((e,r)=>e.localeCompare(r))}catch{return[]}}export async function installGlobalSkill(t,n,o="claude"){const e=y(o).globalSkillsRoots(c())[0],r=l.join(e,n);if(await T(r))throw new Error(`Global ${o} skill "${n}" already exists`);return await _(t,r),r}export async function uninstallGlobalSkill(t,n="claude"){const o=y(n).globalSkillsRoots(c())[0];await z(l.join(o,t))}async function C(t=c()){const n=M(t);if(!await T(n))return{};try{const o=JSON.parse(await E(n,"utf-8"));return o&&typeof o=="object"&&!Array.isArray(o)?o:{}}catch{return{}}}async function j(t){if(!await m(t))return[];let n;try{n=await h(t,{withFileTypes:!0})}catch{return[]}const o=[];for(const e of n){if(e.name.startsWith(".")||!e.isDirectory()&&!e.isSymbolicLink())continue;const r=l.join(t,e.name);if(!await m(r))continue;const i=await L(r);i!=="absent"&&o.push({name:e.name,dir:r,form:i})}return o.sort((e,r)=>e.name.localeCompare(r.name))}export async function installedPluginNamespaces(t=c()){const o=(await C(t)).plugins;if(!o||typeof o!="object"||Array.isArray(o))return[];const e=[];for(const[r,i]of Object.entries(o)){const{market:s}=$("claude").parsePluginKey(r);for(const a of Array.isArray(i)?i:[])a&&typeof a.installPath=="string"&&e.push({dir:a.installPath,namespace:s})}return e}async function Y(){const n=(await C()).plugins;if(!n||typeof n!="object"||Array.isArray(n))return[];const o=[];for(const[e,r]of Object.entries(n)){const i=Array.isArray(r)?r:[];if(i.length===0)continue;const s=[...i].filter(d=>d&&typeof d.installPath=="string").pop();if(!s?.installPath)continue;const a=await j(l.join(s.installPath,"skills")),{name:u,market:p}=$("claude").parsePluginKey(e);o.push({source:"claude-plugin",label:u,namespace:p,skills:a,pluginKey:e})}return o.sort((e,r)=>e.label.localeCompare(r.label))}async function q(){const t=new Map;for(const o of X())for(const e of await j(o))t.has(e.name)||t.set(e.name,e);return{source:"codex-personal",label:"Codex \xB7 \u4E2A\u4EBA",skills:[...t.values()].sort((o,e)=>o.name.localeCompare(e.name))}}async function H(){const t=P();if(!await m(t))return[];const n=[];let o;try{o=await h(t,{withFileTypes:!0})}catch{return[]}for(const e of o){if(!e.isDirectory()&&!e.isSymbolicLink())continue;const r=l.join(t,e.name);let i;try{i=await h(r,{withFileTypes:!0})}catch{continue}for(const s of i){if(!s.isDirectory()&&!s.isSymbolicLink())continue;const a=l.join(r,s.name);let u;try{u=await h(a,{withFileTypes:!0})}catch{continue}const p=u.filter(w=>w.isDirectory()||w.isSymbolicLink());if(p.length===0)continue;const d=p.map(w=>w.name).sort().pop(),f=await j(l.join(a,d,"skills")),b=`${s.name}@${e.name}`;n.push({source:"codex-plugin",label:s.name,namespace:e.name,skills:f,pluginKey:b})}}return n.sort((e,r)=>e.label.localeCompare(r.label))}async function Q(){const t=S(),n=await readGlobalSkills(),o=[];for(const e of n){const r=l.join(t,e),i=await L(r);i!=="absent"&&o.push({name:e,dir:r,form:i})}return{source:"claude-personal",label:"Claude Code \xB7 \u4E2A\u4EBA",skills:o}}export async function readGlobalSkillGroups(){const[t,n,o,e,r,i]=await Promise.all([Q(),Y(),q(),H(),readClaudePluginEnabled(),readCodexPluginEnabled()]),s=(a,u)=>({...a,enabled:a.pluginKey?u[a.pluginKey]??!1:void 0});return[t,...n.map(a=>s(a,r)),o,...e.map(a=>s(a,i))]}export async function resolveGlobalSkillDir(t,n,o){if(t==="claude-personal"){const f=l.join(S(),n);return await m(f)?f:null}if(t==="codex-personal"){const f=l.join(O(),n);return await m(f)?f:null}if(t==="claude-plugin"){if(!o)return null;const b=(await C()).plugins;if(!b||typeof b!="object"||Array.isArray(b))return null;const w=b[o],F=[...Array.isArray(w)?w:[]].filter(D=>D&&typeof D.installPath=="string").pop();if(!F?.installPath)return null;const A=l.join(F.installPath,"skills",n);return await m(A)?A:null}if(!o)return null;const e=o.lastIndexOf("@");if(e<=0)return null;const r=o.slice(0,e),i=o.slice(e+1),s=l.join(P(),i,r);if(!await m(s))return null;let a;try{a=await h(s,{withFileTypes:!0})}catch{return null}const u=a.filter(f=>f.isDirectory()||f.isSymbolicLink());if(u.length===0)return null;const p=u.map(f=>f.name).sort().pop(),d=l.join(s,p,"skills",n);return await m(d)?d:null}function V(t){const n=l.resolve(t),o=c();return R().find(r=>{const i=[...r.globalSkillsRoots(o)],s=r.pluginCacheDir?.(o);return s&&i.push(s),i.some(a=>n===l.resolve(a)||n.startsWith(l.resolve(a)+l.sep))})?.harness??"claude"}export async function listGlobalSkillFiles(t){const n=V(t),o=[],e=async(r,i)=>{let s;try{s=await h(r,{withFileTypes:!0})}catch{return}for(const a of s){if(a.name.startsWith("."))continue;const u=l.join(r,a.name),p=i?`${i}/${a.name}`:a.name;if((a.isDirectory()||a.isSymbolicLink())&&await m(u))await e(u,p);else if(a.isFile()||a.isSymbolicLink())try{const d=await x(u);d.isFile()&&o.push({absPath:u,relPath:p,category:"skill",agent:n,mtimeMs:d.mtimeMs})}catch{}}};return await e(t,""),o.sort((r,i)=>r.relPath.localeCompare(i.relPath))}export async function readGlobalSkillFile(t,n){const o=l.normalize(n).replace(/\\/g,"/");if(l.isAbsolute(n))throw new g(`Absolute paths are not allowed: "${n}"`);if(o.split("/").some(p=>p===".."))throw new g(`Path traversal is not allowed: "${n}"`);const e=l.join(t,o);let r;try{r=await x(e)}catch{throw new g(`File not found: "${n}"`)}if(!r.isFile())throw new g(`Not a file: "${n}"`);if(r.size>v)throw new W(`File exceeds ${v} bytes: "${n}"`);let i=t,s=e;try{[i,s]=await Promise.all([G(t),G(e)])}catch{throw new g(`File not found: "${n}"`)}const a=i.endsWith(l.sep)?i:i+l.sep;if(s!==i&&!s.startsWith(a))throw new g(`Resolved path escapes the skill directory: "${n}"`);return{content:await E(e,"utf-8"),size:r.size}}export async function readClaudePluginEnabled(){return k("claude").readGlobalEnabled()}export async function writeClaudePluginEnabled(t,n){return k("claude").writeGlobalEnabled(t,n)}export async function readCodexPluginEnabled(){return k("codex").readGlobalEnabled()}export async function writeCodexPluginEnabled(t,n){return k("codex").writeGlobalEnabled(t,n)}export{S as globalSkillsPath,B as claudeJsonPath,M as claudePluginsJsonPath,K as claudeSettingsPath,O as codexSkillsPath,P as codexPluginsCachePath};
@@ -1 +1 @@
1
- import{lstat as y,readdir as k,stat as p}from"node:fs/promises";import{homedir as P}from"node:os";import l from"node:path";import{classifyAgent as S,classifyAsset as $}from"../watch/classifier.js";import{PluginModsSniffer as j}from"../watch/plugin-mods.js";import{installedPluginNamespaces as x}from"./global-config.js";const A=["commands","agents","workflows","rules","output-styles","hooks","themes","routines","plugins"],b=["CLAUDE.md","settings.json","settings.local.json"],v=["prompts"],D=["config.toml","AGENTS.md"],F=new Set(["skills","node_modules",".git"]),L=new Set(["marketplaces","data",".in_use"]),h=".claude/plugins",E=`${h}/`,M=6,N=10,d=5e3,T=[{prefix:".claude",dirs:A,files:b},{prefix:".codex",dirs:v,files:D}];async function g(e,i,s){try{const n=await y(e),t=n.isSymbolicLink(),o=t?await p(e):n;if(!o.isFile())return null;let a=$(i);return a==="plugin"&&(a=s.refine(a,i,e)),{absPath:e,relPath:i,category:a,agent:S(i),mtimeMs:o.mtimeMs,...t?{isSymlink:!0}:{}}}catch{return null}}async function m(e,i,s,n,t,o){if(s>t||n.length>=d)return;let a;try{a=await k(e,{withFileTypes:!0})}catch{return}for(const r of a){if(n.length>=d)return;const c=l.join(e,r.name),f=`${i}/${r.name}`;if(r.isDirectory()){if(w(f,r.name))continue;await m(c,f,s+1,n,t,o);continue}if(r.isSymbolicLink())try{if((await p(c)).isDirectory()){w(f,r.name)||await m(c,f,s+1,n,t,o);continue}}catch{continue}const u=await g(c,f,o);u&&n.push(u)}}function w(e,i){return F.has(i)?!0:e.startsWith(E)&&L.has(i)}export async function listGlobalFileAssets(e=P()){const i=new j({revalidate:!1}),s=[];for(const t of T){const o=l.join(e,...t.prefix.split("/"));for(const a of t.files){const r=await g(l.join(o,a),`${t.prefix}/${a}`,i);r&&s.push(r)}for(const a of t.dirs){const r=`${t.prefix}/${a}`,c=r===h?N:M;await m(l.join(o,a),r,1,s,c,i)}}const n=await x(e);return s.sort((t,o)=>t.relPath.localeCompare(o.relPath)),s.map(t=>{const o=_(t.absPath,n);return o?{...t,namespace:o}:t})}function _(e,i){let s;for(const n of i){const t=l.relative(l.resolve(n.dir),l.resolve(e));t===""||t.startsWith("..")||l.isAbsolute(t)||(!s||n.dir.length>s.dir.length)&&(s=n)}return s?.namespace}
1
+ import{lstat as S,readdir as _,stat as P}from"node:fs/promises";import{homedir as g}from"node:os";import c from"node:path";import{classifyAgent as w,classifyAsset as h}from"../watch/classifier.js";import{PluginModsSniffer as I}from"../watch/plugin-mods.js";import{installedPluginNamespaces as D}from"./global-config.js";const L=["commands","agents","workflows","rules","output-styles","hooks","themes","routines","plugins"],A=["CLAUDE.md","settings.json","settings.local.json"],k=["prompts"],R=["config.toml","AGENTS.md"],T=new Set(["skills","node_modules",".git"]),U=new Set(["marketplaces","data",".in_use"]),y=".claude/plugins",F=`${y}/`,N=6,O=10,$=5e3,j=[{prefix:".claude",dirs:L,files:A},{prefix:".codex",dirs:k,files:R}];async function d(s,n,o){try{const e=await S(s),a=e.isSymbolicLink(),t=a?await P(s):e;if(!t.isFile())return null;let i=h(n);return i==="plugin"&&(i=o.refine(i,n,s)),{absPath:s,relPath:n,category:i,agent:w(n),mtimeMs:t.mtimeMs,...a?{isSymlink:!0}:{}}}catch{return null}}async function f(s,n,o,e,a){if(o>e)return[];let t;try{t=await _(s,{withFileTypes:!0})}catch{return[]}return(await Promise.all(t.map(async l=>{const u=c.join(s,l.name),r=`${n}/${l.name}`;if(l.isDirectory())return E(r,l.name)?[]:f(u,r,o+1,e,a);if(l.isSymbolicLink())try{if((await P(u)).isDirectory())return E(r,l.name)?[]:f(u,r,o+1,e,a)}catch{return[]}const m=await d(u,r,a);return m?[m]:[]}))).flat()}function E(s,n){return T.has(n)?!0:s.startsWith(F)&&U.has(n)}export async function listGlobalFileAssets(s=g()){const n=new I({revalidate:!1}),e=(await Promise.all(j.map(async t=>{const i=c.join(s,...t.prefix.split("/")),[l,u]=await Promise.all([Promise.all(t.files.map(r=>d(c.join(i,r),`${t.prefix}/${r}`,n))),Promise.all(t.dirs.map(r=>{const m=`${t.prefix}/${r}`,p=m===y?O:N;return f(c.join(i,r),m,1,p,n)}))]);return[...l.filter(r=>r!==null),...u.flat()]}))).flat(),a=await D(s);return e.sort((t,i)=>t.relPath.localeCompare(i.relPath)),e.slice(0,$).map(t=>{const i=x(t.absPath,a);return i?{...t,namespace:i}:t})}function x(s,n){let o;for(const e of n){const a=c.relative(c.resolve(e.dir),c.resolve(s));a===""||a.startsWith("..")||c.isAbsolute(a)||(!o||e.dir.length>o.dir.length)&&(o=e)}return o?.namespace}
@@ -0,0 +1,46 @@
1
+ import { type Harness, type HooksConfig, type InitComponents, type MCPConfig, type Preset } from '@weavecode/core';
2
+ import { type SyncClass } from './git-classify.js';
3
+ /**
4
+ * init 生成物的漂移检测与自动落盘——`weave init` 写过的文件里,**不进 git 的**
5
+ * 由同步域自动刷新(自愈),**会进 git 的**只报不写、dashboard 提醒用户去终端
6
+ * 跑 `weave init`(保留「生成 + commit」流程)。
7
+ *
8
+ * 期望态不在此处拼:落点与内容全经 harness 的 `generateInitFiles`(与 init 落盘
9
+ * 同一套生成器),statusline 那条走 statusline 模块自己的生成器与落点。本模块只
10
+ * 做「盘上 vs 期望」的比对与按 git 归类分流。
11
+ */
12
+ export interface InitFileUpdate {
13
+ /** 项目根相对路径(posix)。 */
14
+ relPath: string;
15
+ targetPath: string;
16
+ /** 盘上缺失或内容与期望不同。 */
17
+ outdated: boolean;
18
+ /** `auto` = 可代写自愈;`manual` = 会进 git,只报不写;null = 没漂移,未归类。 */
19
+ syncClass: SyncClass | null;
20
+ /** 期望全文;null = 判不出来(盘上不可合并等)→ 不写。 */
21
+ expectedContent: string | null;
22
+ }
23
+ /** `.weave/config.yaml` 的解析结果(手写 k:v 行,对象值是 JSON 一行)。 */
24
+ interface InitRuntime {
25
+ initVersion: string | null;
26
+ preset: Preset;
27
+ harnesses: Harness[];
28
+ components: InitComponents;
29
+ hooks: HooksConfig;
30
+ mcp: MCPConfig;
31
+ }
32
+ /**
33
+ * 读 init 落档的运行时配置。旧项目没有 `hooks`/`mcp`/`components` 字段——
34
+ * 回落 DEFAULT_*(正是未加 `--hooks`/`--mcp` 时 init 的取值)。
35
+ */
36
+ export declare function readInitRuntime(projectPath: string): Promise<InitRuntime>;
37
+ /** 一个项目的 init 生成物漂移清单(含全部条目,`outdated` 标注是否需同步)。 */
38
+ export declare function detectInitFileUpdates(projectPath: string): Promise<InitFileUpdate[]>;
39
+ /**
40
+ * 落一条生成物——**只写 `auto` 归类的**(不进 git);会进 git 的写下去会改掉用户
41
+ * 正要 commit 的文件,一律拒绝。返回是否真的写了。
42
+ */
43
+ export declare function applyInitFile(update: InitFileUpdate): Promise<boolean>;
44
+ /** 会进 git、因此只能提醒用户跑 `weave init` 的漂移条目。 */
45
+ export declare function needsInit(updates: readonly InitFileUpdate[]): boolean;
46
+ export {};
@@ -0,0 +1,2 @@
1
+ import{mkdir as y,readFile as m,writeFile as g}from"node:fs/promises";import l from"node:path";import{DEFAULT_HOOKS as f,DEFAULT_MCP as w,HARNESS_KEYS as C,detectPlatform as E,isHarness as x,resolveComponents as O}from"@weavecode/core";import{WEAVE_CONTENT_MARKER as h,generateInitFiles as S}from"@weavecode/harness";import{gitClassify as k}from"./git-classify.js";import{generateStatuslineScript as F}from"../statusline/generator.js";import{readStatuslineConfig as v,statuslineScriptRelPath as A}from"../statusline/manager.js";import{WEAVE_VERSION as P}from"../version.js";function b(t){const e={};for(const o of t.split(`
2
+ `)){const n=o.indexOf(":");if(n<=0)continue;const s=o.slice(0,n).trim(),i=o.slice(n+1).trim();if(s)try{e[s]=JSON.parse(i)}catch{e[s]=i}}return e}function I(t){if(typeof t!="object"||t===null)return f;const e=t,o=Object.fromEntries(Object.keys(f).filter(n=>typeof f[n]=="boolean"&&!(n in e)).map(n=>[n,!1]));return{...f,...o,...e}}export async function readInitRuntime(t){let e;try{e=await m(l.join(t,".weave","config.yaml"),"utf-8")}catch{e=""}const o=b(e),n=o.preset,s=o.components,i=o.hooks,a=o.mcp,c=o.harnesses;return{initVersion:typeof o.initVersion=="string"?o.initVersion:null,preset:n==="minimal"||n==="full"||n==="default"?n:"default",harnesses:Array.isArray(c)?c.filter(x):[],components:O(n==="minimal"||n==="full"||n==="default"?n:"default",typeof s=="object"&&s!==null?s:void 0),hooks:I(i),mcp:{...w,...typeof a=="object"&&a!==null?a:{}}}}function R(){return E()}function V(t,e){return{projectPath:t,version:P,platform:R(),components:e.components,hooks:e.hooks,mcp:e.mcp}}async function _(t,e){if(!e.components.helpers)return[];const o=await v(t);return[{relPath:A(),weaveMarker:h,content:F(o)}]}async function N(t){try{return await m(t,"utf-8")}catch{return null}}function H(t,e){return t.merge?e===null?t.content:t.merge(e,t.content):e!==null&&!e.includes(t.weaveMarker??h)?null:t.content}async function M(t){try{return await m(l.join(t,".weave","config.yaml"),"utf-8"),!0}catch{return!1}}export async function detectInitFileUpdates(t){if(!await M(t))return[];const e=await readInitRuntime(t),o=V(t,e),n=e.harnesses.length>0?e.harnesses:[C[0]],s=[...await _(t,e)];for(const r of n)s.push(...await S(r,o));const i=[];for(const r of s){const p=l.join(t,...r.relPath.split("/")),d=await N(p),u=H(r,d);i.push({relPath:r.relPath,targetPath:p,outdated:u!==null&&u!==d,syncClass:null,expectedContent:u})}const a=i.filter(r=>r.outdated),c=await k(t,a.map(r=>r.relPath));for(const r of a)r.syncClass=c.classOf(r.relPath);return i}export async function applyInitFile(t){return t.syncClass!=="auto"||!t.outdated||t.expectedContent===null?!1:(await y(l.dirname(t.targetPath),{recursive:!0}),await g(t.targetPath,t.expectedContent,"utf-8"),!0)}export function needsInit(t){return t.some(e=>e.syncClass==="manual"&&e.outdated)}
@@ -1,2 +1,2 @@
1
- import{mkdir as l,readFile as f,writeFile as y}from"node:fs/promises";import r from"node:path";const i=r.join(".weave","installed.json"),s=e=>[e.category,e.name,e.agent,e.assetCategory??""].join("\0");function g(e){if(!e||typeof e!="object")return!1;const t=e;return(t.category==="skill"||t.category==="mcp"||t.category==="file")&&typeof t.name=="string"&&t.name!==""&&typeof t.agent=="string"}export async function readInstalledLedger(e){try{const t=JSON.parse(await f(r.join(e,i),"utf-8"));return Array.isArray(t.assets)?t.assets.filter(g):[]}catch{return[]}}export async function recordInstalled(e,t){const n=await readInstalledLedger(e);n.some(a=>s(a)===s(t))||await o(e,[...n,t])}export async function forgetInstalled(e,t){const n=await readInstalledLedger(e),a=n.filter(c=>s(c)!==s(t));a.length!==n.length&&await o(e,a)}async function o(e,t){const n=r.join(e,i);await l(r.dirname(n),{recursive:!0}),await y(n,`${JSON.stringify({version:1,assets:t},null,2)}
1
+ import{mkdir as c,readFile as l,writeFile as y}from"node:fs/promises";import r from"node:path";const i=r.join(".weave","installed.json"),s=t=>[t.category,t.name,t.agent,t.assetCategory??""].join("\0");function g(t){if(!t||typeof t!="object")return!1;const e=t;return(e.category==="skill"||e.category==="mcp"||e.category==="file")&&typeof e.name=="string"&&e.name!==""&&typeof e.agent=="string"}export async function readInstalledLedger(t){try{const e=JSON.parse(await l(r.join(t,i),"utf-8"));return Array.isArray(e.assets)?e.assets.filter(g):[]}catch{return[]}}export async function recordInstalled(t,e){const n=await readInstalledLedger(t);n.some(a=>s(a)===s(e))||await o(t,[...n,e])}export async function forgetInstalled(t,e){const n=await readInstalledLedger(t),a=n.filter(f=>s(f)!==s(e));a.length!==n.length&&await o(t,a)}async function o(t,e){const n=r.join(t,i);await c(r.dirname(n),{recursive:!0}),await y(n,`${JSON.stringify({version:1,assets:e},null,2)}
2
2
  `,"utf-8")}
@@ -1,4 +1,5 @@
1
1
  import type { Harness } from '@weavecode/core';
2
+ import type { McpServerConfig } from '@weavecode/harness';
2
3
  import { type FileAssetCategory } from './file-assets.js';
3
4
  /**
4
5
  * Asset install/uninstall — pure filesystem operations, no sqlite writes.
@@ -14,11 +15,8 @@ export declare class InstallConflictError extends Error {
14
15
  export declare class AssetNotFoundError extends Error {
15
16
  constructor(message: string);
16
17
  }
17
- export interface McpServerConfig {
18
- command: string;
19
- args?: string[];
20
- env?: Record<string, string>;
21
- }
18
+ /** MCP 配置的通用形(定义随 `AssetSurface` 的方法签名住在 harness 包)。 */
19
+ export type { McpServerConfig };
22
20
  /** Which coding agent an install targets — Claude Code or Codex surfaces. */
23
21
  export type InstallAgent = Harness;
24
22
  /** Copy an entire skill directory into the agent's `<skills>/<name>/`. */
@@ -1,3 +1 @@
1
- import{cp as w,rm as m,readFile as j,writeFile as y,access as v,mkdir as h}from"node:fs/promises";import{homedir as g}from"node:os";import s from"node:path";import{FILE_ASSET_SPECS as S,fileAssetTargetDir as x}from"./file-assets.js";import{assetSurfaceFor as E}from"../surfaces.js";import{forgetInstalled as f,recordInstalled as p}from"./install-ledger.js";export class InstallConflictError extends Error{constructor(a){super(a),this.name="InstallConflictError"}}export class AssetNotFoundError extends Error{constructor(a){super(a),this.name="AssetNotFoundError"}}const d=".mcp.json";function i(e){if(!e||e.includes("/")||e.includes("\\")||e.includes("..")||e.includes(s.sep))throw new Error(`Invalid asset name: "${e}"`)}async function l(e){try{return await v(e),!0}catch{return!1}}function $(e){return E(e).projectSkillsDir()}export async function installSkill(e,a,t,r="claude"){i(t);const n=s.join(e,$(r),t);if(await l(n))throw new InstallConflictError(`Skill "${t}" is already installed${r==="codex"?" (Codex)":""}`);return await w(a,n,{recursive:!0}),await p(e,{category:"skill",name:t,agent:r}),n}export async function uninstallSkill(e,a,t="claude"){i(a);const r=s.join(e,$(t),a);if(!await l(r))throw new AssetNotFoundError(`Skill "${a}" is not installed${t==="codex"?" (Codex)":""}`);await m(r,{recursive:!0,force:!0}),await f(e,{category:"skill",name:a,agent:t})}export async function installFileAsset(e,a,t,r,n="claude",o="project"){i(t);const c=x(a,n,o,e,g()),u=s.join(c,`${t}${S[a].ext}`);if(await l(u))throw new InstallConflictError(`${a} "${t}" is already installed`);return await h(c,{recursive:!0}),await w(r,u),o==="project"&&await p(e,{category:"file",name:t,agent:n,assetCategory:a}),u}export async function uninstallFileAsset(e,a,t,r="claude",n="project"){i(t);const o=x(a,r,n,e,g()),c=s.join(o,`${t}${S[a].ext}`);if(!await l(c))throw new AssetNotFoundError(`${a} "${t}" is not installed`);await m(c,{force:!0}),n==="project"&&await f(e,{category:"file",name:t,agent:r,assetCategory:a})}export async function installMcp(e,a,t){i(a);const r=s.join(e,d),n=await readMcpJson(r),o=n.mcpServers??{};if(a in o)throw new InstallConflictError(`MCP server "${a}" is already configured`);o[a]=t,n.mcpServers=o,await y(r,`${JSON.stringify(n,null,2)}
2
- `,"utf-8"),await p(e,{category:"mcp",name:a,agent:"claude"})}export async function uninstallMcp(e,a){i(a);const t=s.join(e,d),r=await readMcpJson(t),n=r.mcpServers??{};if(!(a in n))throw new AssetNotFoundError(`MCP server "${a}" is not configured`);delete n[a],r.mcpServers=n,await y(t,`${JSON.stringify(r,null,2)}
3
- `,"utf-8"),await f(e,{category:"mcp",name:a,agent:"claude"})}export async function readMcpJson(e){try{const a=await j(e,"utf-8"),t=JSON.parse(a);return t&&typeof t=="object"?t:{}}catch{return{}}}export async function readMcpServers(e){return(await readMcpJson(s.join(e,d))).mcpServers??{}}
1
+ import{cp as x,rm as y,readFile as k,access as C,mkdir as g}from"node:fs/promises";import{homedir as a}from"node:os";import c from"node:path";import{FILE_ASSET_SPECS as $,fileAssetTargetDir as S}from"./file-assets.js";import{assetSurfaceFor as n}from"../surfaces.js";import{forgetInstalled as w,recordInstalled as p}from"./install-ledger.js";export class InstallConflictError extends Error{constructor(r){super(r),this.name="InstallConflictError"}}export class AssetNotFoundError extends Error{constructor(r){super(r),this.name="AssetNotFoundError"}}function u(t){if(!t||t.includes("/")||t.includes("\\")||t.includes("..")||t.includes(c.sep))throw new Error(`Invalid asset name: "${t}"`)}async function d(t){try{return await C(t),!0}catch{return!1}}function E(t){return n(t).projectSkillsDir()}export async function installSkill(t,r,i,e="claude"){u(i);const s=c.join(t,E(e),i);if(await d(s))throw new InstallConflictError(`Skill "${i}" is already installed${e==="codex"?" (Codex)":""}`);return await x(r,s,{recursive:!0}),await p(t,{category:"skill",name:i,agent:e}),s}export async function uninstallSkill(t,r,i="claude"){u(r);const e=c.join(t,E(i),r);if(!await d(e))throw new AssetNotFoundError(`Skill "${r}" is not installed${i==="codex"?" (Codex)":""}`);await y(e,{recursive:!0,force:!0}),await w(t,{category:"skill",name:r,agent:i})}export async function installFileAsset(t,r,i,e,s="claude",l="project"){u(i);const o=S(r,s,l,t,a()),f=c.join(o,`${i}${$[r].ext}`);if(await d(f))throw new InstallConflictError(`${r} "${i}" is already installed`);return await g(o,{recursive:!0}),await x(e,f),l==="project"&&await p(t,{category:"file",name:i,agent:s,assetCategory:r}),f}export async function uninstallFileAsset(t,r,i,e="claude",s="project"){u(i);const l=S(r,e,s,t,a()),o=c.join(l,`${i}${$[r].ext}`);if(!await d(o))throw new AssetNotFoundError(`${r} "${i}" is not installed`);await y(o,{force:!0}),s==="project"&&await w(t,{category:"file",name:i,agent:e,assetCategory:r})}export async function installMcp(t,r,i){if(r in await readMcpServers(t))throw new InstallConflictError(`MCP server "${r}" is already configured`);await n("claude").mcpWrite("project",t,a(),r,i),await p(t,{category:"mcp",name:r,agent:"claude"})}export async function uninstallMcp(t,r){if(!await n("claude").mcpRemove("project",t,a(),r))throw new AssetNotFoundError(`MCP server "${r}" is not configured`);await w(t,{category:"mcp",name:r,agent:"claude"})}export async function readMcpJson(t){try{const r=await k(t,"utf-8"),i=JSON.parse(r);return i&&typeof i=="object"?i:{}}catch{return{}}}export async function readMcpServers(t){return n("claude").mcpRead("project",t,a())}
@@ -1 +1 @@
1
- import{getLibraryScan as u}from"./scan-cache.js";export async function buildLibraryIndex(e){const a=new Map,i=new Map,s=new Map;for(const n of e){const m=n.kind==="skill"||n.kind==="both",d=n.kind==="mcp"||n.kind==="both";let o;try{o=await u(n.path)}catch{continue}if(m){for(const t of o.skills)a.has(t.name)||a.set(t.name,{name:t.name,libraryId:n.id,libraryPath:n.path,dirPath:t.dirPath});for(const t of Object.values(o.files))for(const r of t){const c=`${r.category}/${r.name}`;s.has(c)||s.set(c,{name:r.name,category:r.category,libraryId:n.id,libraryPath:n.path,filePath:r.filePath})}}if(d){for(const t of o.mcp)if(!i.has(t.name)){const{name:r,command:c,args:f,env:l,sourcePath:h}=t,p={command:c,...f&&{args:f},...l&&{env:l}};i.set(t.name,{name:r,libraryId:n.id,libraryPath:n.path,config:p,sourcePath:h})}}}return{skills:a,mcp:i,files:s}}export function findSkillSource(e,a){return e.skills.get(a)}export function findMcpSource(e,a){return e.mcp.get(a)}export function findFileAssetSource(e,a,i){return e.files.get(`${a}/${i}`)}
1
+ import{getLibraryScan as u}from"./scan-cache.js";export async function buildLibraryIndex(e){const a=new Map,r=new Map,s=new Map;for(const t of e){const m=t.kind==="skill"||t.kind==="both",p=t.kind==="mcp"||t.kind==="both";let o;try{o=await u(t.path)}catch{continue}if(m){for(const n of o.skills)a.has(n.name)||a.set(n.name,{name:n.name,libraryId:t.id,libraryPath:t.path,dirPath:n.dirPath});for(const n of Object.values(o.files))for(const i of n){const c=`${i.category}/${i.name}`;s.has(c)||s.set(c,{name:i.name,category:i.category,libraryId:t.id,libraryPath:t.path,filePath:i.filePath})}}if(p){for(const n of o.mcp)if(!r.has(n.name)){const{name:i,command:c,args:f,env:l,sourcePath:d}=n,h={command:c,...f&&{args:f},...l&&{env:l}};r.set(n.name,{name:i,libraryId:t.id,libraryPath:t.path,config:h,sourcePath:d})}}}return{skills:a,mcp:r,files:s}}export function findSkillSource(e,a){return e.skills.get(a)}export function findMcpSource(e,a){return e.mcp.get(a)}export function findFileAssetSource(e,a,r){return e.files.get(`${a}/${r}`)}
@@ -1,11 +1,11 @@
1
1
  import type { ToolStateRow } from '@weavecode/core';
2
- import { type McpServerConfig } from './installer.js';
2
+ import type { McpServerConfig } from './installer.js';
3
3
  export type McpToolRow = ToolStateRow<McpServerConfig>;
4
4
  /**
5
- * MCP 工具行装配(工具对象模型首个产消方):三处表示法(项目 `.mcp.json` /
6
- * `~/.claude.json` / `~/.codex/config.toml`)读出的服务器映射展平成
7
- * harness × scope 状态行。范围来自 `AssetSurface.mcpScopes`;启停覆写与
8
- * 生效态由服务端解析(词表桥在 settings-mcp,文件表示法不出 server)。
5
+ * MCP 工具行装配(工具对象模型首个产消方):每个 surface 按自己的 `mcpScopes()`
6
+ * 读出服务器映射、展平成 harness × scope 状态行——表示法(项目 `.mcp.json` /
7
+ * `~/.claude.json` / `~/.codex/config.toml`)只活在各自的 `AssetSurface.mcpRead`
8
+ * 里,本函数不认识任何一种。启停覆写与生效态由服务端解析(词表桥在 settings-mcp)。
9
9
  * 行行携带 installScopes——web 的视图选择与安装控制不依赖能力表二次拉取。
10
10
  */
11
11
  export declare function readMcpRows(projectPath: string): Promise<McpToolRow[]>;
@@ -1 +1 @@
1
- import{readMcpServers as u}from"./installer.js";import{readGlobalMcpServers as M}from"./global-config.js";import{readCodexMcpServers as v}from"./codex-toml.js";import{readMcpEnableMap as h,mcpOverrideOf as S,resolveMcpEffective as b}from"./settings-mcp.js";import{assetSurfaces as w}from"../surfaces.js";export async function readMcpRows(s){const[t,p,l,n]=await Promise.all([u(s).catch(()=>({})),M().catch(()=>({})),v().catch(()=>({})),h(s)]),f=new Map(w().map(e=>[e.harness,e.mcpScopes()])),o=[],r=(e,m,i,a)=>{for(const[c,d]of Object.entries(i))o.push({key:c,category:"mcp",harness:e,scope:m,installScopes:f.get(e)??[],enable:a?S(a,c):null,effective:a?b(a,c):!0,detail:d})};return r("claude","project",t,n),r("claude","user",p,null),r("codex","user",l,null),o}
1
+ import{homedir as i}from"node:os";import{readMcpEnableMap as l,mcpOverrideOf as m,resolveMcpEffective as u}from"./settings-mcp.js";import{assetSurfaces as d}from"../surfaces.js";export async function readMcpRows(r){const t=await l(r),a=[];for(const e of d()){const n=e.mcpScopes();for(const s of n){const o=e.harness==="claude"&&s==="project"?t:null,f=await e.mcpRead(s,r,i()).catch(()=>({}));for(const[c,p]of Object.entries(f))a.push({key:c,category:"mcp",harness:e.harness,scope:s,installScopes:n,enable:o?m(o,c):null,effective:o?u(o,c):!0,detail:p})}}return a}
@@ -1 +1 @@
1
- import r from"node:path";import{marketIdOf as t}from"../market/identity.js";import{marketDir as a}from"../market/manifest.js";export async function installPluginPack(o,i){const n=t(i.dir);return o.globalInstall(i.dir,{name:i.name,version:i.version,description:i.description,...n?{marketplace:{name:n,dir:r.join(a(),n)}}:{}})}
1
+ import t from"node:path";import{marketIdOf as o}from"../market/identity.js";import{marketDir as e}from"../market/manifest.js";export async function installPluginPack(n,r){const i=o(r.dir);return n.globalInstall(r.dir,{name:r.name,version:r.version,description:r.description,...i?{marketplace:{name:i,dir:t.join(e(),i)}}:{}})}
@@ -1 +1 @@
1
- import{pluginSurfaces as b,pluginStateSurfaces as g}from"../surfaces.js";const u=["user","project","local"],y=(s,e)=>e in s?s[e]?"on":"off":"inherit";function S(s,e){for(let n=u.length-1;n>=0;n--){const o=s[u[n]][e];if(o!==void 0)return o}return!1}export async function readPluginRows(s){const e=[],n=b();for(const{harness:o,surface:a}of n){const f=a.pluginScopes(),[t,c]=await Promise.all([a.readInstalled().catch(()=>({})),a.readEnabledOverrides(s).catch(()=>({user:{},project:{},local:{}}))]),p=new Set(Object.keys(t));for(const r of u)for(const l of Object.keys(c[r]))p.add(l);for(const r of p){const l=t[r],d=S(c,r);for(const i of f)e.push({key:r,category:"plugin",harness:o,scope:i,installScopes:f,install:l?.some(h=>(h.scope??"user")===i)?"installed":"absent",enable:y(c[i],r),effective:d})}}for(const{harness:o,state:a}of g()){if(n.some(t=>t.harness===o))continue;const f=await a.readGlobalEnabled().catch(()=>({}));for(const[t,c]of Object.entries(f))e.push({key:t,category:"plugin",harness:o,scope:"user",installScopes:[],enable:c?"on":"off",effective:c})}return e}
1
+ import{pluginSurfaces as b,pluginStateSurfaces as g}from"../surfaces.js";const u=["user","project","local"],v=(s,e)=>e in s?s[e]?"on":"off":"inherit";function y(s,e){for(let n=u.length-1;n>=0;n--){const o=s[u[n]][e];if(o!==void 0)return o}return!1}export async function readPluginRows(s){const e=[],n=b();for(const{harness:o,surface:a}of n){const l=a.pluginScopes(),[t,c]=await Promise.all([a.readInstalled().catch(()=>({})),a.readEnabledOverrides(s).catch(()=>({user:{},project:{},local:{}}))]),p=new Set(Object.keys(t));for(const r of u)for(const f of Object.keys(c[r]))p.add(f);for(const r of p){const f=t[r],d=y(c,r);for(const i of l)e.push({key:r,category:"plugin",harness:o,scope:i,installScopes:l,install:f?.some(h=>(h.scope??"user")===i)?"installed":"absent",enable:v(c[i],r),effective:d})}}for(const{harness:o,state:a}of g()){if(n.some(t=>t.harness===o))continue;const l=await a.readGlobalEnabled().catch(()=>({}));for(const[t,c]of Object.entries(l))e.push({key:t,category:"plugin",harness:o,scope:"user",installScopes:[],enable:c?"on":"off",effective:c})}return e}
@@ -1 +1 @@
1
- import{cp as f,mkdir as h,readdir as d,readFile as P,rm as w}from"node:fs/promises";import{homedir as j}from"node:os";import r from"node:path";import{WEAVE_PLUGIN_MANIFEST as y,WeavePluginManifestSchema as k}from"@weavecode/core";import{assetSurfaceFor as v}from"../surfaces.js";const S={skills:"skill",commands:"command",agents:"agent"};async function F(t){const a=[];let s;try{s=await d(t)}catch{return a}for(const o of s){const i=r.join(t,o);try{const c=JSON.parse(await P(r.join(i,y),"utf8")),e=k.safeParse(c);e.success&&a.push({dir:i,manifest:e.data})}catch{}}return a}function E(t,a,s){const o=[];if(!s.templates)return o;const i=v("claude"),c=r.join(t,...i.projectSkillsDir().split("/"));for(const[e,l]of Object.entries(s.templates)){const n=S[e];if(n)for(const p of l??[]){const u=r.resolve(a,p);if(!u.startsWith(r.resolve(a)+r.sep))continue;const m=r.basename(u),g=n==="skill"?c:i.targetDir(n,"project",t,j());o.push({pluginId:s.id,category:n,name:m.replace(/\.md$/,""),sourcePath:u,targetPath:r.join(g,m)})}}return o}export async function detectPluginTemplateUpdates(t,a){const s=[],o=r.join(t,".weave","plugins");for(const{dir:i,manifest:c}of await F(o))for(const e of E(t,i,c)){const[l,n]=e.category==="skill"?await Promise.all([a.get(e.sourcePath),a.get(e.targetPath)]):await Promise.all([a.getFile(e.sourcePath),a.getFile(e.targetPath)]);s.push({...e,outdated:l!==n})}return s}export async function materializePluginTemplate(t){if(t.category==="skill"){await w(t.targetPath,{recursive:!0,force:!0}),await f(t.sourcePath,t.targetPath,{recursive:!0});return}await h(r.dirname(t.targetPath),{recursive:!0}),await f(t.sourcePath,t.targetPath)}
1
+ import{cp as f,mkdir as d,readdir as P,readFile as h,rm as w}from"node:fs/promises";import{homedir as y}from"node:os";import a from"node:path";import{WEAVE_PLUGIN_MANIFEST as k,WeavePluginManifestSchema as v}from"@weavecode/core";import{assetSurfaceFor as E}from"../surfaces.js";const T={skills:"skill",commands:"command",agents:"agent"};async function j(t){const e=[];let s;try{s=await P(t)}catch{return e}for(const o of s){const i=a.join(t,o);try{const c=JSON.parse(await h(a.join(i,k),"utf8")),r=v.safeParse(c);r.success&&e.push({dir:i,manifest:r.data})}catch{}}return e}function S(t,e,s){const o=[];if(!s.templates)return o;const i=E("claude"),c=a.join(t,...i.projectSkillsDir().split("/"));for(const[r,l]of Object.entries(s.templates)){const n=T[r];if(n)for(const p of l??[]){const u=a.resolve(e,p);if(!u.startsWith(a.resolve(e)+a.sep))continue;const m=a.basename(u),g=n==="skill"?c:i.targetDir(n,"project",t,y());o.push({pluginId:s.id,category:n,name:m.replace(/\.md$/,""),sourcePath:u,targetPath:a.join(g,m)})}}return o}export async function detectPluginTemplateUpdates(t,e){const s=[],o=a.join(t,".weave","plugins");for(const{dir:i,manifest:c}of await j(o))for(const r of S(t,i,c)){const[l,n]=r.category==="skill"?await Promise.all([e.get(r.sourcePath),e.get(r.targetPath)]):await Promise.all([e.getFile(r.sourcePath),e.getFile(r.targetPath)]);s.push({...r,outdated:l!==n})}return s}export async function materializePluginTemplate(t){if(t.category==="skill"){await w(t.targetPath,{recursive:!0,force:!0}),await f(t.sourcePath,t.targetPath,{recursive:!0});return}await d(a.dirname(t.targetPath),{recursive:!0}),await f(t.sourcePath,t.targetPath)}
@@ -1,6 +1,4 @@
1
1
  export interface ProjectConfig {
2
- /** When true, the SyncScheduler auto-applies outdated updates on its tick. */
3
- autoSync: boolean;
4
2
  /** ISO timestamp of the last successful sync (null if never). */
5
3
  lastSyncAt: string | null;
6
4
  }
@@ -1,2 +1,2 @@
1
- import{readFile as i,writeFile as e,mkdir as s}from"node:fs/promises";import c from"node:path";const o=".weave",u="config.json";export const DEFAULT_PROJECT_CONFIG={autoSync:!1,lastSyncAt:null};function r(t){return c.join(t,o,u)}function y(t){return{autoSync:t.autoSync??DEFAULT_PROJECT_CONFIG.autoSync,lastSyncAt:t.lastSyncAt??DEFAULT_PROJECT_CONFIG.lastSyncAt}}export async function readProjectConfig(t){try{const n=await i(r(t),"utf-8");return y(JSON.parse(n))}catch{return DEFAULT_PROJECT_CONFIG}}export async function writeProjectConfig(t,n){const a=c.join(t,o);await s(a,{recursive:!0}),await e(r(t),`${JSON.stringify(n,null,2)}
2
- `,"utf-8")}export async function markSynced(t,n){const a=await readProjectConfig(t);await writeProjectConfig(t,{...a,lastSyncAt:n})}
1
+ import{readFile as a,writeFile as e,mkdir as s}from"node:fs/promises";import i from"node:path";const c=".weave",f="config.json";export const DEFAULT_PROJECT_CONFIG={lastSyncAt:null};function o(t){return i.join(t,c,f)}function u(t){return{lastSyncAt:t.lastSyncAt??DEFAULT_PROJECT_CONFIG.lastSyncAt}}export async function readProjectConfig(t){try{const n=await a(o(t),"utf-8");return u(JSON.parse(n))}catch{return DEFAULT_PROJECT_CONFIG}}export async function writeProjectConfig(t,n){const r=i.join(t,c);await s(r,{recursive:!0}),await e(o(t),`${JSON.stringify(n,null,2)}
2
+ `,"utf-8")}export async function markSynced(t,n){const r=await readProjectConfig(t);await writeProjectConfig(t,{...r,lastSyncAt:n})}
@@ -1 +1 @@
1
- import{readFile as l,stat as c}from"node:fs/promises";import{homedir as h}from"node:os";import s from"node:path";import{AssetNotFoundError as a}from"./installer.js";export class PathEscapeError extends Error{constructor(e){super(e),this.name="PathEscapeError"}}export class FileTooLargeError extends Error{constructor(e){super(e),this.name="FileTooLargeError"}}export const MAX_BYTES=512*1024;export function resolveProjectFile(r,e){const t=s.normalize(e).replace(/\\/g,"/");if(s.isAbsolute(e))throw new PathEscapeError(`Absolute paths are not allowed: "${e}"`);if(t.split("/").some(n=>n===".."))throw new PathEscapeError(`Path traversal is not allowed: "${e}"`);if(!(t===".mcp.json"||t==="CLAUDE.md"||t==="AGENTS.md"||t===".claude"||t.startsWith(".claude/")||t===".codex"||t.startsWith(".codex/")||t===".weave"||t.startsWith(".weave/")))throw new PathEscapeError(`Path is outside the allowed roots: "${e}"`);const o=s.join(r,t),i=r.endsWith(s.sep)?r:r+s.sep;if(o!==r&&!o.startsWith(i))throw new PathEscapeError(`Resolved path escapes the project: "${e}"`);return o}export async function readProjectFile(r,e){const t=resolveProjectFile(r,e);let o;try{o=await c(t)}catch{throw new a(`File not found: "${e}"`)}if(!o.isFile())throw new a(`Not a file: "${e}"`);if(o.size>MAX_BYTES)throw new FileTooLargeError(`File exceeds ${MAX_BYTES} bytes: "${e}"`);return{content:await l(t,"utf-8"),size:o.size}}export async function readGlobalFile(r){return readProjectFile(h(),r)}
1
+ import{readFile as l,stat as d}from"node:fs/promises";import{homedir as w}from"node:os";import s from"node:path";import{AssetNotFoundError as n}from"./installer.js";export class PathEscapeError extends Error{constructor(e){super(e),this.name="PathEscapeError"}}export class FileTooLargeError extends Error{constructor(e){super(e),this.name="FileTooLargeError"}}export const MAX_BYTES=512*1024;export function resolveProjectFile(t,e){const o=s.normalize(e).replace(/\\/g,"/");if(s.isAbsolute(e))throw new PathEscapeError(`Absolute paths are not allowed: "${e}"`);if(o.split("/").some(c=>c===".."))throw new PathEscapeError(`Path traversal is not allowed: "${e}"`);if(!(o===".mcp.json"||o==="CLAUDE.md"||o==="AGENTS.md"||o===".claude"||o.startsWith(".claude/")||o===".codex"||o.startsWith(".codex/")||o===".weave"||o.startsWith(".weave/")))throw new PathEscapeError(`Path is outside the allowed roots: "${e}"`);const i=s.join(t,o),a=t.endsWith(s.sep)?t:t+s.sep;if(i!==t&&!i.startsWith(a))throw new PathEscapeError(`Resolved path escapes the project: "${e}"`);return i}export async function readProjectFile(t,e){const o=resolveProjectFile(t,e);let r;try{r=await d(o)}catch{throw new n(`File not found: "${e}"`)}if(!r.isFile())throw new n(`Not a file: "${e}"`);if(r.size>MAX_BYTES)throw new FileTooLargeError(`File exceeds ${MAX_BYTES} bytes: "${e}"`);return{content:await l(o,"utf-8"),size:r.size}}export async function readGlobalFile(t){return readProjectFile(w(),t)}
@@ -1 +1 @@
1
- import{mkdir as f,readFile as p,rm as w,writeFile as m}from"node:fs/promises";import s from"node:path";import{scanLibraryFileAssets as g,scanLibraryMcp as v,scanLibraryPlugins as A,scanLibrarySkills as b}from"./scanner.js";const l="scans.json",u=1;function c(a){const r=s.resolve(a);return s.join(s.dirname(r),".weave-scans",s.basename(r))}const e=new Map,o=new Map;export async function scanLibrary(a){const{plugins:r,packRoots:t}=await A(a),[i,n,y]=await Promise.all([b(a,t),v(a,t),g(a,t)]);return{plugins:r,packRoots:t,skills:i,mcp:n,files:y}}export async function getLibraryScan(a){const r=s.resolve(a),t=e.get(r);if(t)return t;const i=o.get(r);if(i)return i;const n=d(r);o.set(r,n);try{return await n}finally{o.delete(r)}}async function d(a){const r=await k(a);if(r)return e.set(a,r),r;const t=await scanLibrary(a);return await L(a,t),e.set(a,t),t}async function k(a){try{const r=JSON.parse(await p(s.join(c(a),l),"utf8"));return!r||r.version!==u||!Array.isArray(r.plugins)||!Array.isArray(r.packRoots)||!Array.isArray(r.skills)||!Array.isArray(r.mcp)||!r.files||typeof r.files!="object"?null:r}catch{return null}}async function L(a,r){try{await f(c(a),{recursive:!0}),await m(s.join(c(a),l),JSON.stringify({version:u,...r}),"utf8")}catch{}}export async function invalidateScan(a){const r=s.resolve(a);e.delete(r);const t=o.get(r);t&&await t.catch(()=>{}),await w(c(r),{recursive:!0,force:!0}),e.delete(r)}export function clearScanCache(){e.clear()}
1
+ import{mkdir as f,readFile as p,rm as w,writeFile as m}from"node:fs/promises";import t from"node:path";import{scanLibraryFileAssets as d,scanLibraryMcp as g,scanLibraryPlugins as A,scanLibrarySkills as v}from"./scanner.js";const u="scans.json",y=1;function c(n){const r=t.resolve(n);return t.join(t.dirname(r),".weave-scans",t.basename(r))}const a=new Map,o=new Map;export async function scanLibrary(n){const{plugins:r,packRoots:e}=await A(n),[s,i,l]=await Promise.all([v(n,e),g(n,e),d(n,e)]);return{plugins:r,packRoots:e,skills:s,mcp:i,files:l}}export async function getLibraryScan(n){const r=t.resolve(n),e=a.get(r);if(e)return e;const s=o.get(r);if(s)return s;const i=S(r);o.set(r,i);try{return await i}finally{o.delete(r)}}async function S(n){const r=await k(n);if(r)return a.set(n,r),r;const e=await scanLibrary(n);return await L(n,e),a.set(n,e),e}async function k(n){try{const r=JSON.parse(await p(t.join(c(n),u),"utf8"));return!r||r.version!==y||!Array.isArray(r.plugins)||!Array.isArray(r.packRoots)||!Array.isArray(r.skills)||!Array.isArray(r.mcp)||!r.files||typeof r.files!="object"?null:r}catch{return null}}async function L(n,r){try{await f(c(n),{recursive:!0}),await m(t.join(c(n),u),JSON.stringify({version:y,...r}),"utf8")}catch{}}export async function invalidateScan(n){const r=t.resolve(n);a.delete(r);const e=o.get(r);e&&await e.catch(()=>{}),await w(c(r),{recursive:!0,force:!0}),a.delete(r)}export function clearScanCache(){a.clear()}
@@ -1 +1 @@
1
- import{readdir as p,readFile as k,stat as F}from"node:fs/promises";import{join as c,basename as u,relative as l,dirname as j}from"node:path";import{FILE_ASSET_SPECS as P,FILE_ASSET_CATEGORIES as h}from"./file-assets.js";import{hasNonEmptyModules as L}from"../watch/plugin-mods.js";import{parseToolkitPack as E}from"../hooks/toolkit-scan.js";import{marketIdOf as O}from"../market/identity.js";import{pluginSurfaceFor as T}from"../surfaces.js";function C(e){if(!(!(e.ccPack||e.kind==="mod")||!e.targets.includes("claude")))return T("claude").pluginKey(e.name,O(e.dir))}const y=new Set(["node_modules",".git","dist","build",".next","coverage",".cache"]);async function d(e){try{return(await F(e)).isFile()}catch{return!1}}async function I(e){if(await d(c(e,".claude-plugin","plugin.json"))||await d(c(e,"weave-plugin.json")))return!0;try{const a=JSON.parse(await k(c(e,"hooks","hooks.json"),"utf8"));return L(a)}catch{return!1}}const x=10;export async function scanLibraryPlugins(e){const a=[],n=[],o=async(t,r)=>{if(await I(t)){n.push(l(e,t).replace(/\\/g,"/"));const s=await E(t,{root:e,provenance:"market"},"");if(s){const m=[];for(const w of s.skills)await d(c(t,"skills",w,"SKILL.md"))&&m.push(w);const f=C(s);a.push({name:s.name,version:s.version,...s.description?{description:s.description}:{},...f?{key:f}:{},dirPath:s.dir,relPath:l(e,t).replace(/\\/g,"/"),ccPack:s.ccPack,weavePack:s.weavePack,kind:s.kind,components:s.components,targets:s.targets,skills:m})}return}if(r>=x)return;let i;try{i=await p(t,{withFileTypes:!0})}catch{return}for(const s of i)s.isDirectory()&&(s.name.startsWith(".")||y.has(s.name)||await o(c(t,s.name),r+1))};return await o(e,0),{plugins:a.sort((t,r)=>t.relPath.localeCompare(r.relPath)),packRoots:n.sort((t,r)=>t.localeCompare(r))}}function g(e,a){return!a||a.length===0?!1:a.some(n=>n===""||e===n||e.startsWith(`${n}/`))}export async function scanLibrarySkills(e,a){const n=[];return await b(e,e,n,a),n.sort((o,t)=>o.name.localeCompare(t.name))}async function b(e,a,n,o){if(g(l(e,a).replace(/\\/g,"/"),o))return;let t;try{t=await p(a,{withFileTypes:!0})}catch{return}if(t.some(r=>r.isFile()&&r.name==="SKILL.md")){n.push({name:u(a),dirPath:a,relPath:l(e,a).replace(/\\/g,"/"),group:l(e,j(a)).replace(/\\/g,"/")});return}for(const r of t)r.isDirectory()&&(r.name.startsWith(".")||y.has(r.name)||await b(e,c(a,r.name),n,o))}export async function scanLibraryMcp(e,a){const n=[];await v(e,e,n,a);const o=[];for(const t of n)try{const r=JSON.parse(await k(t.abs,"utf-8"));$(r,t,o)}catch{}return o.sort((t,r)=>t.name.localeCompare(r.name))}async function v(e,a,n,o){if(g(l(e,a).replace(/\\/g,"/"),o))return;let t;try{t=await p(a,{withFileTypes:!0})}catch{return}for(const r of t)if(r.isDirectory()){if(r.name.startsWith(".")||y.has(r.name))continue;await v(e,c(a,r.name),n,o)}else if(r.isFile()){const i=r.name.replace(/\.mcp\.json$/i,"").replace(/\.json$/i,""),s=/\.mcp\.json$/i.test(r.name),m=u(a)==="mcp"&&/\.json$/i.test(r.name);(s||m)&&i&&n.push({abs:c(a,r.name),rel:l(e,c(a,r.name)).replace(/\\/g,"/")})}}function $(e,a,n){const o=a.rel.replace(/\.mcp\.json$/i,"").replace(/\.json$/i,"").replace(/^.*\//,"");if(e&&typeof e=="object"&&!Array.isArray(e)){const t=e,r=t.mcpServers;if(r&&typeof r=="object"&&!Array.isArray(r)){for(const[s,m]of Object.entries(r)){const f=S(s,m);f&&n.push({...f,sourcePath:a.abs,relPath:a.rel})}return}const i=S(o,t);i&&n.push({...i,sourcePath:a.abs,relPath:a.rel})}}function S(e,a){if(!a||typeof a!="object"||Array.isArray(a))return null;const n=a;if(typeof n.command!="string"||!n.command)return null;const o={name:e,command:n.command};if(Array.isArray(n.args)&&(o.args=n.args.filter(t=>typeof t=="string")),n.env&&typeof n.env=="object"&&!Array.isArray(n.env)){const t={};for(const[r,i]of Object.entries(n.env))typeof i=="string"&&(t[r]=i);Object.keys(t).length&&(o.env=t)}return o}const W=Object.fromEntries(h.flatMap(e=>Object.values(P[e].dirs).map(a=>a?.project).filter(a=>a!==void 0).map(a=>[u(a),e])));export async function scanLibraryFileAssets(e,a){const n={};for(const o of h)n[o]=[];await A(e,e,n,a);for(const o of h)n[o].sort((t,r)=>t.name.localeCompare(r.name));return n}async function A(e,a,n,o){if(g(l(e,a).replace(/\\/g,"/"),o))return;let t;try{t=await p(a,{withFileTypes:!0})}catch{return}if(t.some(i=>i.isFile()&&i.name==="SKILL.md"))return;const r=W[u(a)];if(r){const i=P[r];for(const s of t){if(!s.isFile()||!s.name.endsWith(i.ext))continue;const m=s.name.slice(0,-i.ext.length);if(!m)continue;const f=c(a,s.name);n[r].push({name:m,filePath:f,relPath:l(e,f).replace(/\\/g,"/"),group:l(e,j(a)).replace(/\\/g,"/"),category:r})}return}for(const i of t)i.isDirectory()&&(i.name.startsWith(".")||y.has(i.name)||await A(e,c(a,i.name),n,o))}
1
+ import{readdir as l,readFile as j,stat as E}from"node:fs/promises";import{join as o,basename as p,relative as f,dirname as S}from"node:path";import{FILE_ASSET_SPECS as A,FILE_ASSET_CATEGORIES as h}from"./file-assets.js";import{hasNonEmptyModules as L}from"../watch/plugin-mods.js";import{parseToolkitPack as I}from"../hooks/toolkit-scan.js";import{marketIdOf as T}from"../market/identity.js";import{pluginSurfaceFor as d}from"../surfaces.js";function _(t){if(!(!(t.ccPack||t.kind==="mod")||!t.targets.includes("claude")))return d("claude").pluginKey(t.name,T(t.dir))}const y=new Set(["node_modules",".git","dist","build",".next","coverage",".cache"]);async function g(t){try{return(await E(t)).isFile()}catch{return!1}}async function D(t){if(await g(o(t,".claude-plugin","plugin.json"))||await g(o(t,"weave-plugin.json")))return!0;try{const e=JSON.parse(await j(o(t,"hooks","hooks.json"),"utf8"));return L(e)}catch{return!1}}const M=10;export async function scanLibraryPlugins(t){const e=[],r=[],c=async(a,n)=>{if(await D(a)){r.push(f(t,a).replace(/\\/g,"/"));const s=await I(a,{root:t,provenance:"market"},"");if(s){const u=[];for(const k of s.skills)await g(o(a,"skills",k,"SKILL.md"))&&u.push(k);const m=_(s);e.push({name:s.name,version:s.version,...s.description?{description:s.description}:{},...m?{key:m}:{},dirPath:s.dir,relPath:f(t,a).replace(/\\/g,"/"),ccPack:s.ccPack,weavePack:s.weavePack,kind:s.kind,components:s.components,targets:s.targets,skills:u})}return}if(n>=M)return;let i;try{i=await l(a,{withFileTypes:!0})}catch{return}for(const s of i)s.isDirectory()&&(s.name.startsWith(".")||y.has(s.name)||await c(o(a,s.name),n+1))};return await c(t,0),{plugins:e.sort((a,n)=>a.relPath.localeCompare(n.relPath)),packRoots:r.sort((a,n)=>a.localeCompare(n))}}function w(t,e){return!e||e.length===0?!1:e.some(r=>r===""||t===r||t.startsWith(`${r}/`))}export async function scanLibrarySkills(t,e){const r=[];return await P(t,t,r,e),r.sort((c,a)=>c.name.localeCompare(a.name))}async function P(t,e,r,c){if(w(f(t,e).replace(/\\/g,"/"),c))return;let a;try{a=await l(e,{withFileTypes:!0})}catch{return}if(a.some(n=>n.isFile()&&n.name==="SKILL.md")){r.push({name:p(e),dirPath:e,relPath:f(t,e).replace(/\\/g,"/"),group:f(t,S(e)).replace(/\\/g,"/")});return}for(const n of a)n.isDirectory()&&(n.name.startsWith(".")||y.has(n.name)||await P(t,o(e,n.name),r,c))}export async function scanLibraryMcp(t,e){const r=[];await v(t,t,r,e);const c=[];for(const a of r)try{const n=JSON.parse(await j(a.abs,"utf-8"));O(n,a,c)}catch{}return c.sort((a,n)=>a.name.localeCompare(n.name))}async function v(t,e,r,c){if(w(f(t,e).replace(/\\/g,"/"),c))return;let a;try{a=await l(e,{withFileTypes:!0})}catch{return}for(const n of a)if(n.isDirectory()){if(n.name.startsWith(".")||y.has(n.name))continue;await v(t,o(e,n.name),r,c)}else if(n.isFile()){const i=n.name.replace(/\.mcp\.json$/i,"").replace(/\.json$/i,""),s=/\.mcp\.json$/i.test(n.name),u=p(e)==="mcp"&&/\.json$/i.test(n.name);(s||u)&&i&&r.push({abs:o(e,n.name),rel:f(t,o(e,n.name)).replace(/\\/g,"/")})}}function O(t,e,r){const c=e.rel.replace(/\.mcp\.json$/i,"").replace(/\.json$/i,"").replace(/^.*\//,"");if(t&&typeof t=="object"&&!Array.isArray(t)){const a=t,n=a.mcpServers;if(n&&typeof n=="object"&&!Array.isArray(n)){for(const[s,u]of Object.entries(n)){const m=F(s,u);m&&r.push({...m,sourcePath:e.abs,relPath:e.rel})}return}const i=F(c,a);i&&r.push({...i,sourcePath:e.abs,relPath:e.rel})}}function F(t,e){if(!e||typeof e!="object"||Array.isArray(e))return null;const r=e;if(typeof r.command!="string"||!r.command)return null;const c={name:t,command:r.command};if(Array.isArray(r.args)&&(c.args=r.args.filter(a=>typeof a=="string")),r.env&&typeof r.env=="object"&&!Array.isArray(r.env)){const a={};for(const[n,i]of Object.entries(r.env))typeof i=="string"&&(a[n]=i);Object.keys(a).length&&(c.env=a)}return c}const C=Object.fromEntries(h.flatMap(t=>Object.values(A[t].dirs).map(e=>e?.project).filter(e=>e!==void 0).map(e=>[p(e),t])));export async function scanLibraryFileAssets(t,e){const r={};for(const c of h)r[c]=[];await b(t,t,r,e);for(const c of h)r[c].sort((a,n)=>a.name.localeCompare(n.name));return r}async function b(t,e,r,c){if(w(f(t,e).replace(/\\/g,"/"),c))return;let a;try{a=await l(e,{withFileTypes:!0})}catch{return}if(a.some(i=>i.isFile()&&i.name==="SKILL.md"))return;const n=C[p(e)];if(n){const i=A[n];for(const s of a){if(!s.isFile()||!s.name.endsWith(i.ext))continue;const u=s.name.slice(0,-i.ext.length);if(!u)continue;const m=o(e,s.name);r[n].push({name:u,filePath:m,relPath:f(t,m).replace(/\\/g,"/"),group:f(t,S(e)).replace(/\\/g,"/"),category:n})}return}for(const i of a)i.isDirectory()&&(i.name.startsWith(".")||y.has(i.name)||await b(t,o(e,i.name),r,c))}
@@ -1,2 +1,2 @@
1
- import{readFile as f,writeFile as u,mkdir as b,access as p}from"node:fs/promises";import o from"node:path";const c=".claude/settings.json";async function v(r){try{return await p(r),!0}catch{return!1}}async function d(r){const e=o.join(r,c);if(!await v(e))return{};try{const n=JSON.parse(await f(e,"utf-8"));return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}catch{return{}}}async function y(r,e){const n=o.join(r,c);await b(o.dirname(n),{recursive:!0}),await u(n,`${JSON.stringify(e,null,2)}
2
- `,"utf-8")}export async function readMcpEnableMap(r){const e=await d(r),n=i(e.enabledMcpjsonServers),t=i(e.disabledMcpjsonServers),a={};for(const s of n)a[s]="enabled";for(const s of t)a[s]="disabled";return{overrides:a,enableAll:e.enableAllProjectMcpServers===!0}}const M={enabled:"on",disabled:"off",default:"inherit"},S={on:"enabled",off:"disabled",inherit:"default"};export function mcpOverrideOf(r,e){return M[r.overrides[e]??"default"]}export function resolveMcpEffective(r,e){const n=r.overrides[e];return n==="enabled"?!0:n==="disabled"?!1:r.enableAll}export async function setMcpEnableState(r,e,n){const t=await d(r),a=new Set(i(t.enabledMcpjsonServers)),s=new Set(i(t.disabledMcpjsonServers));a.delete(e),s.delete(e),n==="enabled"?a.add(e):n==="disabled"&&s.add(e),l(t,"enabledMcpjsonServers",a),l(t,"disabledMcpjsonServers",s),await y(r,t)}export function setMcpEnableOverride(r,e,n){return setMcpEnableState(r,e,S[n])}function i(r){return Array.isArray(r)?r.filter(e=>typeof e=="string"):[]}function l(r,e,n){n.size===0?delete r[e]:r[e]=[...n].sort()}
1
+ import{readFile as f,writeFile as u,mkdir as b,access as p}from"node:fs/promises";import o from"node:path";const c=".claude/settings.json";async function S(t){try{return await p(t),!0}catch{return!1}}async function d(t){const e=o.join(t,c);if(!await S(e))return{};try{const r=JSON.parse(await f(e,"utf-8"));return r&&typeof r=="object"&&!Array.isArray(r)?r:{}}catch{return{}}}async function v(t,e){const r=o.join(t,c);await b(o.dirname(r),{recursive:!0}),await u(r,`${JSON.stringify(e,null,2)}
2
+ `,"utf-8")}export async function readMcpEnableMap(t){const e=await d(t),r=i(e.enabledMcpjsonServers),n=i(e.disabledMcpjsonServers),s={};for(const a of r)s[a]="enabled";for(const a of n)s[a]="disabled";return{overrides:s,enableAll:e.enableAllProjectMcpServers===!0}}const y={enabled:"on",disabled:"off",default:"inherit"},M={on:"enabled",off:"disabled",inherit:"default"};export function mcpOverrideOf(t,e){return y[t.overrides[e]??"default"]}export function resolveMcpEffective(t,e){const r=t.overrides[e];return r==="enabled"?!0:r==="disabled"?!1:t.enableAll}export async function setMcpEnableState(t,e,r){const n=await d(t),s=new Set(i(n.enabledMcpjsonServers)),a=new Set(i(n.disabledMcpjsonServers));s.delete(e),a.delete(e),r==="enabled"?s.add(e):r==="disabled"&&a.add(e),l(n,"enabledMcpjsonServers",s),l(n,"disabledMcpjsonServers",a),await v(t,n)}export function setMcpEnableOverride(t,e,r){return setMcpEnableState(t,e,M[r])}function i(t){return Array.isArray(t)?t.filter(e=>typeof e=="string"):[]}function l(t,e,r){r.size===0?delete t[e]:t[e]=[...r].sort()}