botmancers 0.3.0 → 0.5.0

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 (471) hide show
  1. package/CHANGELOG.md +107 -1
  2. package/README.md +178 -32
  3. package/app/.next/BUILD_ID +1 -1
  4. package/app/.next/app-path-routes-manifest.json +27 -1
  5. package/app/.next/build-manifest.json +3 -3
  6. package/app/.next/prerender-manifest.json +33 -5
  7. package/app/.next/required-server-files.json +2 -2
  8. package/app/.next/routes-manifest.json +198 -0
  9. package/app/.next/server/app/_global-error/page.js +1 -1
  10. package/app/.next/server/app/_global-error/page.js.nft.json +1 -1
  11. package/app/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
  12. package/app/.next/server/app/_global-error.html +1 -1
  13. package/app/.next/server/app/_global-error.rsc +1 -1
  14. package/app/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  15. package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  16. package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  17. package/app/.next/server/app/_not-found/page.js +1 -1
  18. package/app/.next/server/app/_not-found/page.js.nft.json +1 -1
  19. package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  20. package/app/.next/server/app/_not-found.html +1 -1
  21. package/app/.next/server/app/_not-found.rsc +2 -2
  22. package/app/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
  23. package/app/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
  24. package/app/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
  25. package/app/.next/server/app/api/agent-deck/decks/route.js +3 -3
  26. package/app/.next/server/app/api/agent-deck/decks/route.js.nft.json +1 -1
  27. package/app/.next/server/app/api/agent-deck/settings/route.js +3 -3
  28. package/app/.next/server/app/api/agent-deck/settings/route.js.nft.json +1 -1
  29. package/app/.next/server/app/api/bots/[id]/config/route.js +3 -3
  30. package/app/.next/server/app/api/bots/[id]/config/route.js.nft.json +1 -1
  31. package/app/.next/server/app/api/bots/[id]/sessions/[ref]/pins/route/app-paths-manifest.json +3 -0
  32. package/app/.next/server/app/api/bots/[id]/sessions/[ref]/pins/route/build-manifest.json +12 -0
  33. package/app/.next/server/app/api/bots/[id]/sessions/[ref]/pins/route/server-reference-manifest.json +4 -0
  34. package/app/.next/server/app/api/bots/[id]/sessions/[ref]/pins/route.js +12 -0
  35. package/app/.next/server/app/api/bots/[id]/sessions/[ref]/pins/route.js.nft.json +1 -0
  36. package/app/.next/server/app/api/bots/[id]/sessions/[ref]/pins/route_client-reference-manifest.js +3 -0
  37. package/app/.next/server/app/api/bots/[id]/sessions/[ref]/route/app-paths-manifest.json +3 -0
  38. package/app/.next/server/app/api/bots/[id]/sessions/[ref]/route/build-manifest.json +12 -0
  39. package/app/.next/server/app/api/bots/[id]/sessions/[ref]/route/server-reference-manifest.json +4 -0
  40. package/app/.next/server/app/api/bots/[id]/sessions/[ref]/route.js +9 -0
  41. package/app/.next/server/app/api/bots/[id]/sessions/[ref]/route.js.nft.json +1 -0
  42. package/app/.next/server/app/api/bots/[id]/sessions/[ref]/route_client-reference-manifest.js +3 -0
  43. package/app/.next/server/app/api/bots/[id]/sessions/route/app-paths-manifest.json +3 -0
  44. package/app/.next/server/app/api/bots/[id]/sessions/route/build-manifest.json +12 -0
  45. package/app/.next/server/app/api/bots/[id]/sessions/route/server-reference-manifest.json +4 -0
  46. package/app/.next/server/app/api/bots/[id]/sessions/route.js +12 -0
  47. package/app/.next/server/app/api/bots/[id]/sessions/route.js.nft.json +1 -0
  48. package/app/.next/server/app/api/bots/[id]/sessions/route_client-reference-manifest.js +3 -0
  49. package/app/.next/server/app/api/bots/[id]/skill/route.js +3 -3
  50. package/app/.next/server/app/api/bots/[id]/skill/route.js.nft.json +1 -1
  51. package/app/.next/server/app/api/bots/availability/route.js +2 -2
  52. package/app/.next/server/app/api/bots/availability/route.js.nft.json +1 -1
  53. package/app/.next/server/app/api/bots/delete-preview/route.js +4 -4
  54. package/app/.next/server/app/api/bots/delete-preview/route.js.nft.json +1 -1
  55. package/app/.next/server/app/api/bots/import/route.js +3 -3
  56. package/app/.next/server/app/api/bots/import/route.js.nft.json +1 -1
  57. package/app/.next/server/app/api/bots/manage/route.js +3 -3
  58. package/app/.next/server/app/api/bots/manage/route.js.nft.json +1 -1
  59. package/app/.next/server/app/api/bots/name-migrations/route.js +3 -3
  60. package/app/.next/server/app/api/bots/name-migrations/route.js.nft.json +1 -1
  61. package/app/.next/server/app/api/bots/route.js +7 -7
  62. package/app/.next/server/app/api/bots/route.js.nft.json +1 -1
  63. package/app/.next/server/app/api/conversations/[id]/approve/route.js +3 -3
  64. package/app/.next/server/app/api/conversations/[id]/approve/route.js.nft.json +1 -1
  65. package/app/.next/server/app/api/conversations/[id]/deny/route.js +3 -3
  66. package/app/.next/server/app/api/conversations/[id]/deny/route.js.nft.json +1 -1
  67. package/app/.next/server/app/api/conversations/[id]/draft/route.js +3 -3
  68. package/app/.next/server/app/api/conversations/[id]/draft/route.js.nft.json +1 -1
  69. package/app/.next/server/app/api/conversations/[id]/messages/[messageId]/stop/route.js +3 -3
  70. package/app/.next/server/app/api/conversations/[id]/messages/[messageId]/stop/route.js.nft.json +1 -1
  71. package/app/.next/server/app/api/conversations/[id]/messages/route.js +6 -6
  72. package/app/.next/server/app/api/conversations/[id]/messages/route.js.nft.json +1 -1
  73. package/app/.next/server/app/api/conversations/[id]/route.js +3 -3
  74. package/app/.next/server/app/api/conversations/[id]/route.js.nft.json +1 -1
  75. package/app/.next/server/app/api/conversations/[id]/stop/route.js +4 -4
  76. package/app/.next/server/app/api/conversations/[id]/stop/route.js.nft.json +1 -1
  77. package/app/.next/server/app/api/conversations/route.js +3 -3
  78. package/app/.next/server/app/api/conversations/route.js.nft.json +1 -1
  79. package/app/.next/server/app/api/exchanges/[id]/cancel/route/app-paths-manifest.json +3 -0
  80. package/app/.next/server/app/api/exchanges/[id]/cancel/route/build-manifest.json +12 -0
  81. package/app/.next/server/app/api/exchanges/[id]/cancel/route/server-reference-manifest.json +4 -0
  82. package/app/.next/server/app/api/exchanges/[id]/cancel/route.js +11 -0
  83. package/app/.next/server/app/api/exchanges/[id]/cancel/route.js.nft.json +1 -0
  84. package/app/.next/server/app/api/exchanges/[id]/cancel/route_client-reference-manifest.js +3 -0
  85. package/app/.next/server/app/api/exchanges/[id]/route/app-paths-manifest.json +3 -0
  86. package/app/.next/server/app/api/exchanges/[id]/route/build-manifest.json +12 -0
  87. package/app/.next/server/app/api/exchanges/[id]/route/server-reference-manifest.json +4 -0
  88. package/app/.next/server/app/api/exchanges/[id]/route.js +11 -0
  89. package/app/.next/server/app/api/exchanges/[id]/route.js.nft.json +1 -0
  90. package/app/.next/server/app/api/exchanges/[id]/route_client-reference-manifest.js +3 -0
  91. package/app/.next/server/app/api/exchanges/route/app-paths-manifest.json +3 -0
  92. package/app/.next/server/app/api/exchanges/route/build-manifest.json +12 -0
  93. package/app/.next/server/app/api/exchanges/route/server-reference-manifest.json +4 -0
  94. package/app/.next/server/app/api/exchanges/route.js +12 -0
  95. package/app/.next/server/app/api/exchanges/route.js.nft.json +1 -0
  96. package/app/.next/server/app/api/exchanges/route_client-reference-manifest.js +3 -0
  97. package/app/.next/server/app/api/files/[name]/route.js +3 -2
  98. package/app/.next/server/app/api/files/[name]/route.js.nft.json +1 -1
  99. package/app/.next/server/app/api/groups/route.js +3 -3
  100. package/app/.next/server/app/api/groups/route.js.nft.json +1 -1
  101. package/app/.next/server/app/api/health/route.js +3 -2
  102. package/app/.next/server/app/api/health/route.js.nft.json +1 -1
  103. package/app/.next/server/app/api/import-capabilities/route.js +1 -1
  104. package/app/.next/server/app/api/import-capabilities/route.js.nft.json +1 -1
  105. package/app/.next/server/app/api/marketplace-handoff/route.js +1 -1
  106. package/app/.next/server/app/api/marketplace-handoff/route.js.nft.json +1 -1
  107. package/app/.next/server/app/api/marketplace-handoff/status/route.js +1 -1
  108. package/app/.next/server/app/api/marketplace-handoff/status/route.js.nft.json +1 -1
  109. package/app/.next/server/app/api/mcp/route.js +3 -3
  110. package/app/.next/server/app/api/mcp/route.js.nft.json +1 -1
  111. package/app/.next/server/app/api/messages/[id]/between/route.js +3 -3
  112. package/app/.next/server/app/api/messages/[id]/between/route.js.nft.json +1 -1
  113. package/app/.next/server/app/api/runtime-connections/route/app-paths-manifest.json +3 -0
  114. package/app/.next/server/app/api/runtime-connections/route/build-manifest.json +12 -0
  115. package/app/.next/server/app/api/runtime-connections/route/server-reference-manifest.json +4 -0
  116. package/app/.next/server/app/api/runtime-connections/route.js +9 -0
  117. package/app/.next/server/app/api/runtime-connections/route.js.nft.json +1 -0
  118. package/app/.next/server/app/api/runtime-connections/route_client-reference-manifest.js +3 -0
  119. package/app/.next/server/app/api/service-grants/route/app-paths-manifest.json +3 -0
  120. package/app/.next/server/app/api/service-grants/route/build-manifest.json +12 -0
  121. package/app/.next/server/app/api/service-grants/route/server-reference-manifest.json +4 -0
  122. package/app/.next/server/app/api/service-grants/route.js +9 -0
  123. package/app/.next/server/app/api/service-grants/route.js.nft.json +1 -0
  124. package/app/.next/server/app/api/service-grants/route_client-reference-manifest.js +3 -0
  125. package/app/.next/server/app/api/v0/agents/[agentId]/conversations/[conversationId]/route/app-paths-manifest.json +3 -0
  126. package/app/.next/server/app/api/v0/agents/[agentId]/conversations/[conversationId]/route/build-manifest.json +12 -0
  127. package/app/.next/server/app/api/v0/agents/[agentId]/conversations/[conversationId]/route/server-reference-manifest.json +4 -0
  128. package/app/.next/server/app/api/v0/agents/[agentId]/conversations/[conversationId]/route.js +12 -0
  129. package/app/.next/server/app/api/v0/agents/[agentId]/conversations/[conversationId]/route.js.nft.json +1 -0
  130. package/app/.next/server/app/api/v0/agents/[agentId]/conversations/[conversationId]/route_client-reference-manifest.js +3 -0
  131. package/app/.next/server/app/api/v0/agents/[agentId]/conversations/route/app-paths-manifest.json +3 -0
  132. package/app/.next/server/app/api/v0/agents/[agentId]/conversations/route/build-manifest.json +12 -0
  133. package/app/.next/server/app/api/v0/agents/[agentId]/conversations/route/server-reference-manifest.json +4 -0
  134. package/app/.next/server/app/api/v0/agents/[agentId]/conversations/route.js +12 -0
  135. package/app/.next/server/app/api/v0/agents/[agentId]/conversations/route.js.nft.json +1 -0
  136. package/app/.next/server/app/api/v0/agents/[agentId]/conversations/route_client-reference-manifest.js +3 -0
  137. package/app/.next/server/app/api/v0/agents/[agentId]/messages/route.js +5 -4
  138. package/app/.next/server/app/api/v0/agents/[agentId]/messages/route.js.nft.json +1 -1
  139. package/app/.next/server/app/api/v0/agents/[agentId]/pins/route/app-paths-manifest.json +3 -0
  140. package/app/.next/server/app/api/v0/agents/[agentId]/pins/route/build-manifest.json +12 -0
  141. package/app/.next/server/app/api/v0/agents/[agentId]/pins/route/server-reference-manifest.json +4 -0
  142. package/app/.next/server/app/api/v0/agents/[agentId]/pins/route.js +12 -0
  143. package/app/.next/server/app/api/v0/agents/[agentId]/pins/route.js.nft.json +1 -0
  144. package/app/.next/server/app/api/v0/agents/[agentId]/pins/route_client-reference-manifest.js +3 -0
  145. package/app/.next/server/app/api/v0/agents/[agentId]/route/app-paths-manifest.json +3 -0
  146. package/app/.next/server/app/api/v0/agents/[agentId]/route/build-manifest.json +12 -0
  147. package/app/.next/server/app/api/v0/agents/[agentId]/route/server-reference-manifest.json +4 -0
  148. package/app/.next/server/app/api/v0/agents/[agentId]/route.js +12 -0
  149. package/app/.next/server/app/api/v0/agents/[agentId]/route.js.nft.json +1 -0
  150. package/app/.next/server/app/api/v0/agents/[agentId]/route_client-reference-manifest.js +3 -0
  151. package/app/.next/server/app/api/v0/agents/[agentId]/sessions/[ref]/route/app-paths-manifest.json +3 -0
  152. package/app/.next/server/app/api/v0/agents/[agentId]/sessions/[ref]/route/build-manifest.json +12 -0
  153. package/app/.next/server/app/api/v0/agents/[agentId]/sessions/[ref]/route/server-reference-manifest.json +4 -0
  154. package/app/.next/server/app/api/v0/agents/[agentId]/sessions/[ref]/route.js +12 -0
  155. package/app/.next/server/app/api/v0/agents/[agentId]/sessions/[ref]/route.js.nft.json +1 -0
  156. package/app/.next/server/app/api/v0/agents/[agentId]/sessions/[ref]/route_client-reference-manifest.js +3 -0
  157. package/app/.next/server/app/api/v0/agents/[agentId]/sessions/route/app-paths-manifest.json +3 -0
  158. package/app/.next/server/app/api/v0/agents/[agentId]/sessions/route/build-manifest.json +12 -0
  159. package/app/.next/server/app/api/v0/agents/[agentId]/sessions/route/server-reference-manifest.json +4 -0
  160. package/app/.next/server/app/api/v0/agents/[agentId]/sessions/route.js +12 -0
  161. package/app/.next/server/app/api/v0/agents/[agentId]/sessions/route.js.nft.json +1 -0
  162. package/app/.next/server/app/api/v0/agents/[agentId]/sessions/route_client-reference-manifest.js +3 -0
  163. package/app/.next/server/app/api/v0/agents/route/app-paths-manifest.json +3 -0
  164. package/app/.next/server/app/api/v0/agents/route/build-manifest.json +12 -0
  165. package/app/.next/server/app/api/v0/agents/route/server-reference-manifest.json +4 -0
  166. package/app/.next/server/app/api/v0/agents/route.js +12 -0
  167. package/app/.next/server/app/api/v0/agents/route.js.nft.json +1 -0
  168. package/app/.next/server/app/api/v0/agents/route_client-reference-manifest.js +3 -0
  169. package/app/.next/server/app/api/v0/capabilities/route/app-paths-manifest.json +3 -0
  170. package/app/.next/server/app/api/v0/capabilities/route/build-manifest.json +12 -0
  171. package/app/.next/server/app/api/v0/capabilities/route/server-reference-manifest.json +4 -0
  172. package/app/.next/server/app/api/v0/capabilities/route.js +12 -0
  173. package/app/.next/server/app/api/v0/capabilities/route.js.nft.json +1 -0
  174. package/app/.next/server/app/api/v0/capabilities/route_client-reference-manifest.js +3 -0
  175. package/app/.next/server/app/api/v0/conversations/[id]/route.js +5 -4
  176. package/app/.next/server/app/api/v0/conversations/[id]/route.js.nft.json +1 -1
  177. package/app/.next/server/app/api/v0/exchanges/[id]/cancel/route/app-paths-manifest.json +3 -0
  178. package/app/.next/server/app/api/v0/exchanges/[id]/cancel/route/build-manifest.json +12 -0
  179. package/app/.next/server/app/api/v0/exchanges/[id]/cancel/route/server-reference-manifest.json +4 -0
  180. package/app/.next/server/app/api/v0/exchanges/[id]/cancel/route.js +12 -0
  181. package/app/.next/server/app/api/v0/exchanges/[id]/cancel/route.js.nft.json +1 -0
  182. package/app/.next/server/app/api/v0/exchanges/[id]/cancel/route_client-reference-manifest.js +3 -0
  183. package/app/.next/server/app/api/v0/exchanges/[id]/route/app-paths-manifest.json +3 -0
  184. package/app/.next/server/app/api/v0/exchanges/[id]/route/build-manifest.json +12 -0
  185. package/app/.next/server/app/api/v0/exchanges/[id]/route/server-reference-manifest.json +4 -0
  186. package/app/.next/server/app/api/v0/exchanges/[id]/route.js +12 -0
  187. package/app/.next/server/app/api/v0/exchanges/[id]/route.js.nft.json +1 -0
  188. package/app/.next/server/app/api/v0/exchanges/[id]/route_client-reference-manifest.js +3 -0
  189. package/app/.next/server/app/api/v0/exchanges/route/app-paths-manifest.json +3 -0
  190. package/app/.next/server/app/api/v0/exchanges/route/build-manifest.json +12 -0
  191. package/app/.next/server/app/api/v0/exchanges/route/server-reference-manifest.json +4 -0
  192. package/app/.next/server/app/api/v0/exchanges/route.js +12 -0
  193. package/app/.next/server/app/api/v0/exchanges/route.js.nft.json +1 -0
  194. package/app/.next/server/app/api/v0/exchanges/route_client-reference-manifest.js +3 -0
  195. package/app/.next/server/app/api/v0/mcp/route.js +7 -4
  196. package/app/.next/server/app/api/v0/mcp/route.js.nft.json +1 -1
  197. package/app/.next/server/app/api/v0/pins/[pinRef]/detach/route/app-paths-manifest.json +3 -0
  198. package/app/.next/server/app/api/v0/pins/[pinRef]/detach/route/build-manifest.json +12 -0
  199. package/app/.next/server/app/api/v0/pins/[pinRef]/detach/route/server-reference-manifest.json +4 -0
  200. package/app/.next/server/app/api/v0/pins/[pinRef]/detach/route.js +12 -0
  201. package/app/.next/server/app/api/v0/pins/[pinRef]/detach/route.js.nft.json +1 -0
  202. package/app/.next/server/app/api/v0/pins/[pinRef]/detach/route_client-reference-manifest.js +3 -0
  203. package/app/.next/server/app/api/v0/pins/[pinRef]/messages/route/app-paths-manifest.json +3 -0
  204. package/app/.next/server/app/api/v0/pins/[pinRef]/messages/route/build-manifest.json +12 -0
  205. package/app/.next/server/app/api/v0/pins/[pinRef]/messages/route/server-reference-manifest.json +4 -0
  206. package/app/.next/server/app/api/v0/pins/[pinRef]/messages/route.js +12 -0
  207. package/app/.next/server/app/api/v0/pins/[pinRef]/messages/route.js.nft.json +1 -0
  208. package/app/.next/server/app/api/v0/pins/[pinRef]/messages/route_client-reference-manifest.js +3 -0
  209. package/app/.next/server/app/api/v0/pins/[pinRef]/route/app-paths-manifest.json +3 -0
  210. package/app/.next/server/app/api/v0/pins/[pinRef]/route/build-manifest.json +12 -0
  211. package/app/.next/server/app/api/v0/pins/[pinRef]/route/server-reference-manifest.json +4 -0
  212. package/app/.next/server/app/api/v0/pins/[pinRef]/route.js +12 -0
  213. package/app/.next/server/app/api/v0/pins/[pinRef]/route.js.nft.json +1 -0
  214. package/app/.next/server/app/api/v0/pins/[pinRef]/route_client-reference-manifest.js +3 -0
  215. package/app/.next/server/app/api/v0/requests/[id]/route.js +5 -4
  216. package/app/.next/server/app/api/v0/requests/[id]/route.js.nft.json +1 -1
  217. package/app/.next/server/app/api/v0/sessions/[ref]/messages/route/app-paths-manifest.json +3 -0
  218. package/app/.next/server/app/api/v0/sessions/[ref]/messages/route/build-manifest.json +12 -0
  219. package/app/.next/server/app/api/v0/sessions/[ref]/messages/route/server-reference-manifest.json +4 -0
  220. package/app/.next/server/app/api/v0/sessions/[ref]/messages/route.js +12 -0
  221. package/app/.next/server/app/api/v0/sessions/[ref]/messages/route.js.nft.json +1 -0
  222. package/app/.next/server/app/api/v0/sessions/[ref]/messages/route_client-reference-manifest.js +3 -0
  223. package/app/.next/server/app/api/v0/sessions/[ref]/pins/route/app-paths-manifest.json +3 -0
  224. package/app/.next/server/app/api/v0/sessions/[ref]/pins/route/build-manifest.json +12 -0
  225. package/app/.next/server/app/api/v0/sessions/[ref]/pins/route/server-reference-manifest.json +4 -0
  226. package/app/.next/server/app/api/v0/sessions/[ref]/pins/route.js +12 -0
  227. package/app/.next/server/app/api/v0/sessions/[ref]/pins/route.js.nft.json +1 -0
  228. package/app/.next/server/app/api/v0/sessions/[ref]/pins/route_client-reference-manifest.js +3 -0
  229. package/app/.next/server/app/api/wake-grants/[id]/revoke/route.js +5 -5
  230. package/app/.next/server/app/api/wake-grants/[id]/revoke/route.js.nft.json +1 -1
  231. package/app/.next/server/app/api/wakes/[id]/decision/route.js +5 -5
  232. package/app/.next/server/app/api/wakes/[id]/decision/route.js.nft.json +1 -1
  233. package/app/.next/server/app/api/wakes/[id]/retry/route.js +5 -5
  234. package/app/.next/server/app/api/wakes/[id]/retry/route.js.nft.json +1 -1
  235. package/app/.next/server/app/bots/[id]/config/page.js +1 -1
  236. package/app/.next/server/app/bots/[id]/config/page.js.nft.json +1 -1
  237. package/app/.next/server/app/bots/[id]/config/page_client-reference-manifest.js +1 -1
  238. package/app/.next/server/app/exchanges/page/app-paths-manifest.json +3 -0
  239. package/app/.next/server/app/exchanges/page/build-manifest.json +20 -0
  240. package/app/.next/server/app/exchanges/page/next-font-manifest.json +11 -0
  241. package/app/.next/server/app/exchanges/page/react-loadable-manifest.json +1 -0
  242. package/app/.next/server/app/exchanges/page/server-reference-manifest.json +4 -0
  243. package/app/.next/server/app/exchanges/page.js +13 -0
  244. package/app/.next/server/app/exchanges/page.js.nft.json +1 -0
  245. package/app/.next/server/app/exchanges/page_client-reference-manifest.js +3 -0
  246. package/app/.next/server/app/exchanges.html +1 -0
  247. package/app/.next/server/app/exchanges.meta +34 -0
  248. package/app/.next/server/app/exchanges.rsc +22 -0
  249. package/app/.next/server/app/exchanges.segments/_full.segment.rsc +22 -0
  250. package/app/.next/server/app/exchanges.segments/_tree.segment.rsc +4 -0
  251. package/app/.next/server/app/exchanges.segments/exchanges/__PAGE__.segment.rsc +26 -0
  252. package/app/.next/server/app/index.html +1 -1
  253. package/app/.next/server/app/index.rsc +3 -3
  254. package/app/.next/server/app/index.segments/__PAGE__.segment.rsc +3 -3
  255. package/app/.next/server/app/index.segments/_full.segment.rsc +3 -3
  256. package/app/.next/server/app/index.segments/_tree.segment.rsc +2 -2
  257. package/app/.next/server/app/page.js +1 -1
  258. package/app/.next/server/app/page.js.nft.json +1 -1
  259. package/app/.next/server/app/page_client-reference-manifest.js +1 -1
  260. package/app/.next/server/app/settings/page.js +1 -1
  261. package/app/.next/server/app/settings/page.js.nft.json +1 -1
  262. package/app/.next/server/app/settings/page_client-reference-manifest.js +1 -1
  263. package/app/.next/server/app/settings.html +1 -1
  264. package/app/.next/server/app/settings.rsc +3 -3
  265. package/app/.next/server/app/settings.segments/_full.segment.rsc +3 -3
  266. package/app/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
  267. package/app/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +3 -3
  268. package/app/.next/server/app/threads/[id]/page/app-paths-manifest.json +3 -0
  269. package/app/.next/server/app/threads/[id]/page/build-manifest.json +20 -0
  270. package/app/.next/server/app/threads/[id]/page/next-font-manifest.json +11 -0
  271. package/app/.next/server/app/threads/[id]/page/react-loadable-manifest.json +1 -0
  272. package/app/.next/server/app/threads/[id]/page/server-reference-manifest.json +4 -0
  273. package/app/.next/server/app/threads/[id]/page.js +13 -0
  274. package/app/.next/server/app/threads/[id]/page.js.nft.json +1 -0
  275. package/app/.next/server/app/threads/[id]/page_client-reference-manifest.js +3 -0
  276. package/app/.next/server/app-paths-manifest.json +27 -1
  277. package/app/.next/server/chunks/0ivl_api_v0_agents_[agentId]_conversations_[conversationId]_route_actions_0lvijtu.js +3 -0
  278. package/app/.next/server/chunks/1oeh_server_app_api_bots_[id]_sessions_[ref]_pins_route_actions_0e1st6o.js +3 -0
  279. package/app/.next/server/chunks/1oeh_server_app_api_v0_agents_[agentId]_conversations_route_actions_0ko3117.js +3 -0
  280. package/app/.next/server/chunks/1oeh_server_app_api_v0_agents_[agentId]_sessions_[ref]_route_actions_0o7q3vt.js +3 -0
  281. package/app/.next/server/chunks/{[externals]__18bqksw._.js → [externals]__06lqs5i._.js} +1 -1
  282. package/app/.next/server/chunks/{[root-of-the-server]__1vxmbdl._.js → [root-of-the-server]__0-45blq._.js} +1 -1
  283. package/app/.next/server/chunks/[root-of-the-server]__02kssr-._.js +3 -0
  284. package/app/.next/server/chunks/[root-of-the-server]__06qkt0f._.js +3 -0
  285. package/app/.next/server/chunks/[root-of-the-server]__08qhrch._.js +3 -0
  286. package/app/.next/server/chunks/[root-of-the-server]__097ptn_._.js +3 -0
  287. package/app/.next/server/chunks/[root-of-the-server]__09m9-pe._.js +3 -0
  288. package/app/.next/server/chunks/[root-of-the-server]__0b7w1z3._.js +3 -0
  289. package/app/.next/server/chunks/[root-of-the-server]__0f5yqjs._.js +3 -0
  290. package/app/.next/server/chunks/[root-of-the-server]__0g4um3-._.js +44 -0
  291. package/app/.next/server/chunks/[root-of-the-server]__0hro5ey._.js +3 -0
  292. package/app/.next/server/chunks/[root-of-the-server]__0hwpgxq._.js +3 -0
  293. package/app/.next/server/chunks/[root-of-the-server]__0izjfmr._.js +582 -55
  294. package/app/.next/server/chunks/{[root-of-the-server]__07l_rgn._.js → [root-of-the-server]__0j0i8xz._.js} +1 -1
  295. package/app/.next/server/chunks/[root-of-the-server]__0lwsto-._.js +5 -0
  296. package/app/.next/server/chunks/[root-of-the-server]__0s1enbp._.js +3 -0
  297. package/app/.next/server/chunks/[root-of-the-server]__0uq7sci._.js +3 -0
  298. package/app/.next/server/chunks/[root-of-the-server]__0wg992i._.js +3 -0
  299. package/app/.next/server/chunks/[root-of-the-server]__13cd2fb._.js +44 -0
  300. package/app/.next/server/chunks/[root-of-the-server]__17mum5-._.js +3 -0
  301. package/app/.next/server/chunks/[root-of-the-server]__1879cge._.js +3 -0
  302. package/app/.next/server/chunks/{[root-of-the-server]__17oz13o._.js → [root-of-the-server]__1_01-13._.js} +3 -3
  303. package/app/.next/server/chunks/[root-of-the-server]__1a2dh11._.js +3 -0
  304. package/app/.next/server/chunks/[root-of-the-server]__1bhzfu_._.js +7 -0
  305. package/app/.next/server/chunks/{[root-of-the-server]__1khwkvb._.js → [root-of-the-server]__1c3e2ds._.js} +1 -1
  306. package/app/.next/server/chunks/[root-of-the-server]__1co3sok._.js +44 -0
  307. package/app/.next/server/chunks/[root-of-the-server]__1eh30sp._.js +3 -0
  308. package/app/.next/server/chunks/[root-of-the-server]__1fmsid0._.js +44 -0
  309. package/app/.next/server/chunks/[root-of-the-server]__1i388e2._.js +3 -0
  310. package/app/.next/server/chunks/[root-of-the-server]__1kvvs4u._.js +3 -0
  311. package/app/.next/server/chunks/[root-of-the-server]__1qbgs3m._.js +3 -0
  312. package/app/.next/server/chunks/[root-of-the-server]__1s6h1sj._.js +3 -0
  313. package/app/.next/server/chunks/[root-of-the-server]__1slu7d7._.js +7 -0
  314. package/app/.next/server/chunks/[root-of-the-server]__1tuqc5v._.js +3 -0
  315. package/app/.next/server/chunks/[root-of-the-server]__1v609eq._.js +44 -0
  316. package/app/.next/server/chunks/[root-of-the-server]__1y_j43n._.js +3 -0
  317. package/app/.next/server/chunks/[root-of-the-server]__1zdv-vb._.js +3 -0
  318. package/app/.next/server/chunks/[root-of-the-server]__1zjs2tr._.js +3 -0
  319. package/app/.next/server/chunks/_0061c2q._.js +3 -0
  320. package/app/.next/server/chunks/_023se5j._.js +44 -0
  321. package/app/.next/server/chunks/_02pb_qv._.js +44 -0
  322. package/app/.next/server/chunks/_05ro-21._.js +44 -0
  323. package/app/.next/server/chunks/_07on0dc._.js +44 -0
  324. package/app/.next/server/chunks/_08208nz._.js +44 -0
  325. package/app/.next/server/chunks/_0a2do3x._.js +1 -1
  326. package/app/.next/server/chunks/_0fe5qz5._.js +44 -0
  327. package/app/.next/server/chunks/_0i8_xso._.js +3 -0
  328. package/app/.next/server/chunks/_0qoji5a._.js +44 -0
  329. package/app/.next/server/chunks/_0uv2pi5._.js +44 -0
  330. package/app/.next/server/chunks/_0wdl90-._.js +44 -0
  331. package/app/.next/server/chunks/_1-5mthb._.js +1 -1
  332. package/app/.next/server/chunks/_11-q8k1._.js +3 -0
  333. package/app/.next/server/chunks/_11ijk9k._.js +44 -0
  334. package/app/.next/server/chunks/_198sn69._.js +44 -0
  335. package/app/.next/server/chunks/_1ba_5hd._.js +44 -0
  336. package/app/.next/server/chunks/_1ess5if._.js +3 -0
  337. package/app/.next/server/chunks/_1i0zod4._.js +3 -0
  338. package/app/.next/server/chunks/_1m89jq5._.js +44 -0
  339. package/app/.next/server/chunks/_1n39wr_._.js +44 -0
  340. package/app/.next/server/chunks/_1ryxqo1._.js +44 -0
  341. package/app/.next/server/chunks/_1vemgly._.js +44 -0
  342. package/app/.next/server/chunks/_20azcus._.js +3 -0
  343. package/app/.next/server/chunks/_next-internal_server_app_api_bots_[id]_sessions_[ref]_route_actions_02gp9-5.js +3 -0
  344. package/app/.next/server/chunks/_next-internal_server_app_api_bots_[id]_sessions_route_actions_1s_wxg4.js +3 -0
  345. package/app/.next/server/chunks/_next-internal_server_app_api_exchanges_[id]_cancel_route_actions_0lh0fl4.js +3 -0
  346. package/app/.next/server/chunks/_next-internal_server_app_api_exchanges_[id]_route_actions_1w4jhin.js +3 -0
  347. package/app/.next/server/chunks/_next-internal_server_app_api_exchanges_route_actions_028wchg.js +3 -0
  348. package/app/.next/server/chunks/_next-internal_server_app_api_runtime-connections_route_actions_06rulng.js +3 -0
  349. package/app/.next/server/chunks/_next-internal_server_app_api_service-grants_route_actions_1459xk1.js +3 -0
  350. package/app/.next/server/chunks/_next-internal_server_app_api_v0_agents_[agentId]_pins_route_actions_08uftk9.js +3 -0
  351. package/app/.next/server/chunks/_next-internal_server_app_api_v0_agents_[agentId]_route_actions_127sxvv.js +3 -0
  352. package/app/.next/server/chunks/_next-internal_server_app_api_v0_agents_[agentId]_sessions_route_actions_0pm6tcu.js +3 -0
  353. package/app/.next/server/chunks/_next-internal_server_app_api_v0_agents_route_actions_00azkhd.js +3 -0
  354. package/app/.next/server/chunks/_next-internal_server_app_api_v0_capabilities_route_actions_0d-eefd.js +3 -0
  355. package/app/.next/server/chunks/_next-internal_server_app_api_v0_exchanges_[id]_cancel_route_actions_1hb2q7i.js +3 -0
  356. package/app/.next/server/chunks/_next-internal_server_app_api_v0_exchanges_[id]_route_actions_098f50-.js +3 -0
  357. package/app/.next/server/chunks/_next-internal_server_app_api_v0_exchanges_route_actions_1ftmhhm.js +3 -0
  358. package/app/.next/server/chunks/_next-internal_server_app_api_v0_pins_[pinRef]_detach_route_actions_0nk3268.js +3 -0
  359. package/app/.next/server/chunks/_next-internal_server_app_api_v0_pins_[pinRef]_messages_route_actions_1wenu96.js +3 -0
  360. package/app/.next/server/chunks/_next-internal_server_app_api_v0_pins_[pinRef]_route_actions_0z7fu_c.js +3 -0
  361. package/app/.next/server/chunks/_next-internal_server_app_api_v0_sessions_[ref]_messages_route_actions_1-rgf_k.js +3 -0
  362. package/app/.next/server/chunks/_next-internal_server_app_api_v0_sessions_[ref]_pins_route_actions_0y3ere3.js +3 -0
  363. package/app/.next/server/chunks/lib_0kik6bx._.js +1 -1
  364. package/app/.next/server/chunks/lib_0lqoyb4._.js +217 -0
  365. package/app/.next/server/chunks/lib_0pe3tiv._.js +1 -1
  366. package/app/.next/server/chunks/lib_0riiofz._.js +44 -0
  367. package/app/.next/server/chunks/lib_16j2293._.js +217 -0
  368. package/app/.next/server/chunks/lib_1nb_61e._.js +217 -0
  369. package/app/.next/server/chunks/lib_service-api-http_ts_0xzqhny._.js +25 -0
  370. package/app/.next/server/chunks/lib_session-pins_ts_0lmxnwj._.js +20 -0
  371. package/app/.next/server/chunks/ssr/{[root-of-the-server]__0sq4frf._.js → [root-of-the-server]__03186rx._.js} +1 -1
  372. package/app/.next/server/chunks/ssr/[root-of-the-server]__03xw2d9._.js +3 -0
  373. package/app/.next/server/chunks/ssr/{[root-of-the-server]__1x7o-fe._.js → [root-of-the-server]__0zzcbqg._.js} +1 -1
  374. package/app/.next/server/chunks/ssr/{[root-of-the-server]__029oxo_._.js → [root-of-the-server]__1feicqq._.js} +1 -1
  375. package/app/.next/server/chunks/ssr/[root-of-the-server]__1t063pe._.js +3 -0
  376. package/app/.next/server/chunks/ssr/_0epgorw._.js +3 -0
  377. package/app/.next/server/chunks/ssr/_1cvuhjt._.js +3 -0
  378. package/app/.next/server/chunks/ssr/_1n5mvo5._.js +3 -0
  379. package/app/.next/server/chunks/ssr/_1o94bnv._.js +1 -1
  380. package/app/.next/server/chunks/ssr/_next-internal_server_app_exchanges_page_actions_0hcso2x.js +3 -0
  381. package/app/.next/server/chunks/ssr/_next-internal_server_app_threads_[id]_page_actions_1fte2n3.js +3 -0
  382. package/app/.next/server/chunks/ssr/app_bots_[id]_config_page_tsx_1e0uue9._.js +3 -0
  383. package/app/.next/server/chunks/ssr/app_components_AgentDeckRuntime_tsx_024janf._.js +3 -0
  384. package/app/.next/server/chunks/ssr/app_components_ExchangeCard_tsx_1shfcgn._.js +3 -0
  385. package/app/.next/server/chunks/ssr/app_exchanges_page_tsx_0j-n2a1._.js +3 -0
  386. package/app/.next/server/chunks/ssr/node_modules_1nkgb45._.js +23 -0
  387. package/app/.next/server/chunks/ssr/node_modules_next_0x3i8za._.js +131 -0
  388. package/app/.next/server/middleware-build-manifest.js +3 -3
  389. package/app/.next/server/middleware.js +1 -1
  390. package/app/.next/server/next-font-manifest.js +1 -1
  391. package/app/.next/server/next-font-manifest.json +8 -0
  392. package/app/.next/server/pages/404.html +1 -1
  393. package/app/.next/server/pages/500.html +1 -1
  394. package/app/.next/server/prefetch-hints.json +14 -0
  395. package/app/.next/server/server-reference-manifest.js +1 -1
  396. package/app/.next/server/server-reference-manifest.json +1 -1
  397. package/app/.next/static/chunks/0bhd8eso48g27.js +1 -0
  398. package/app/.next/static/chunks/1ku9himlsx-hn.js +1 -0
  399. package/app/.next/static/chunks/21aqekm5z0j47.js +1 -0
  400. package/app/.next/static/chunks/2a8bomryx66oj.css +3 -0
  401. package/app/.next/static/chunks/3230ywnpii0s6.js +3 -0
  402. package/app/.next/static/chunks/35l2c95bd-jud.js +1 -0
  403. package/app/.next/static/chunks/3cijpn6vx3yzv.js +1 -0
  404. package/app/.next/static/chunks/3ue9194j59kem.js +1 -0
  405. package/app/.next/static/chunks/44ese2s4gzze_.js +1 -0
  406. package/app/BUILD_INFO.json +2 -2
  407. package/app/package.json +1 -1
  408. package/app/server.js +1 -1
  409. package/dist/cli.d.ts +1 -1
  410. package/dist/cli.js +35 -7
  411. package/dist/clients.d.ts +86 -0
  412. package/dist/clients.js +639 -0
  413. package/dist/config.d.ts +2 -1
  414. package/dist/config.js +7 -6
  415. package/dist/contract.d.ts +7 -1
  416. package/dist/contract.js +33 -8
  417. package/dist/home.d.ts +1 -1
  418. package/dist/home.js +1 -1
  419. package/dist/index.d.ts +1 -1
  420. package/dist/index.js +3 -3
  421. package/dist/managed.js +7 -0
  422. package/dist/product.d.ts +2 -0
  423. package/dist/product.js +7 -1
  424. package/dist/server.js +5 -4
  425. package/dist/upstream.js +21 -7
  426. package/package.json +7 -6
  427. package/schemas/botmancers.mcp.v2.tools.json +4565 -0
  428. package/skills/botmancers-collaboration/SKILL.md +114 -0
  429. package/skills/botmancers-collaboration/references/workflows.md +281 -0
  430. package/app/.next/server/chunks/[root-of-the-server]__08i4wq6._.js +0 -3
  431. package/app/.next/server/chunks/[root-of-the-server]__09d-yrq._.js +0 -3
  432. package/app/.next/server/chunks/[root-of-the-server]__0ab4e_k._.js +0 -3
  433. package/app/.next/server/chunks/[root-of-the-server]__0qozubc._.js +0 -3
  434. package/app/.next/server/chunks/[root-of-the-server]__0za34e1._.js +0 -7
  435. package/app/.next/server/chunks/[root-of-the-server]__10m3szc._.js +0 -3
  436. package/app/.next/server/chunks/[root-of-the-server]__19hjzs0._.js +0 -3
  437. package/app/.next/server/chunks/[root-of-the-server]__1afl75n._.js +0 -3
  438. package/app/.next/server/chunks/[root-of-the-server]__1fjpie4._.js +0 -3
  439. package/app/.next/server/chunks/[root-of-the-server]__1kvvdpx._.js +0 -7
  440. package/app/.next/server/chunks/[root-of-the-server]__1qanlbg._.js +0 -3
  441. package/app/.next/server/chunks/[root-of-the-server]__1qoa704._.js +0 -7
  442. package/app/.next/server/chunks/[root-of-the-server]__20wve4_._.js +0 -3
  443. package/app/.next/server/chunks/_0ggf7vy._.js +0 -3
  444. package/app/.next/server/chunks/_0gtqbub._.js +0 -3
  445. package/app/.next/server/chunks/_0i7ga8c._.js +0 -3
  446. package/app/.next/server/chunks/_0orubev._.js +0 -3
  447. package/app/.next/server/chunks/_0sfpe9z._.js +0 -3
  448. package/app/.next/server/chunks/_0th2j4w._.js +0 -3
  449. package/app/.next/server/chunks/_1ee4ej2._.js +0 -3
  450. package/app/.next/server/chunks/_1esxu1s._.js +0 -3
  451. package/app/.next/server/chunks/_1gn7eh7._.js +0 -3
  452. package/app/.next/server/chunks/_1gw7qwf._.js +0 -3
  453. package/app/.next/server/chunks/_1inyx08._.js +0 -3
  454. package/app/.next/server/chunks/_1kjsnlr._.js +0 -3
  455. package/app/.next/server/chunks/_1p8rola._.js +0 -3
  456. package/app/.next/server/chunks/app_api_import-capabilities_route_ts_013w1kt._.js +0 -3
  457. package/app/.next/server/chunks/lib_051fv4x._.js +0 -111
  458. package/app/.next/server/chunks/lib_07adeq3._.js +0 -111
  459. package/app/.next/server/chunks/lib_draft_ts_1atoius._.js +0 -3
  460. package/app/.next/server/chunks/ssr/_0k_7i66._.js +0 -131
  461. package/app/.next/server/chunks/ssr/_1flnty7._.js +0 -23
  462. package/app/.next/server/chunks/ssr/app_components_0bhuhd-._.js +0 -3
  463. package/app/.next/server/chunks/ssr/app_components_0w2_b3t._.js +0 -3
  464. package/app/.next/static/chunks/0774d7ob6aze_.js +0 -1
  465. package/app/.next/static/chunks/0d3ein53nlgja.js +0 -1
  466. package/app/.next/static/chunks/0qbtymorcz-l9.js +0 -3
  467. package/app/.next/static/chunks/3wdlh25l1vww9.js +0 -1
  468. package/app/.next/static/chunks/3zqbpbm93yqzh.css +0 -3
  469. /package/app/.next/static/{u4r8RPgEfpxk-DGXeKV6g → gh3shm8hnVqXLr75rmvsL}/_buildManifest.js +0 -0
  470. /package/app/.next/static/{u4r8RPgEfpxk-DGXeKV6g → gh3shm8hnVqXLr75rmvsL}/_clientMiddlewareManifest.js +0 -0
  471. /package/app/.next/static/{u4r8RPgEfpxk-DGXeKV6g → gh3shm8hnVqXLr75rmvsL}/_ssgManifest.js +0 -0
@@ -0,0 +1,639 @@
1
+ // `botmancers setup --client codex|cursor|claude`: connect an MCP client to
2
+ // the local bridge and install the optional botmancers-collaboration skill
3
+ // in the place that client loads skills from.
4
+ //
5
+ // Ownership: Botmancers manages only what it wrote. Each install records
6
+ // <home>/config/clients/<client>.json with the package version, the SHA-256
7
+ // of every skill file it wrote, and the SHA-256 of the MCP server entry it
8
+ // wrote. A re-run replaces a file or entry only when it still has the
9
+ // recorded hash (unmodified since Botmancers wrote it) or already has the
10
+ // wanted content; anything else is a conflict, and nothing of that client
11
+ // is written. Files Botmancers never wrote are not touched. A write that
12
+ // fails part way restores everything already written for that client.
13
+ //
14
+ // codex $CODEX_HOME (default ~/.codex): config.toml [mcp_servers.botmancers], skills/
15
+ // cursor ~/.cursor: mcp.json mcpServers.botmancers, skills/
16
+ // claude $CLAUDE_CONFIG_DIR (default ~/.claude): skills/; user MCP servers in
17
+ // ~/.claude.json (or $CLAUDE_CONFIG_DIR/.claude.json) mcpServers.botmancers
18
+ //
19
+ // The skill holds no credentials. The MCP entry carries the bridge's MCP
20
+ // token, as a hand-written client configuration would; nothing here prints it.
21
+ import { createHash } from 'node:crypto';
22
+ import { chmodSync, existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, renameSync, rmSync, rmdirSync, statSync, writeFileSync } from 'node:fs';
23
+ import { homedir } from 'node:os';
24
+ import { dirname, join, relative, sep } from 'node:path';
25
+ import { fileURLToPath } from 'node:url';
26
+ import { ENV, LEGACY_DEFAULT_PORT } from './config.js';
27
+ import { PRODUCT_HOST, ensurePrivateDir, readEnvFile, writePrivateFile } from './home.js';
28
+ export const SKILL_NAME = 'botmancers-collaboration';
29
+ export const MCP_SERVER_NAME = 'botmancers';
30
+ export const CLIENT_IDS = ['codex', 'cursor', 'claude'];
31
+ export const PACKAGED_SKILL_DIR = fileURLToPath(new URL(`../skills/${SKILL_NAME}`, import.meta.url));
32
+ const LABELS = { codex: 'Codex', cursor: 'Cursor', claude: 'Claude Code' };
33
+ export function isClientId(value) {
34
+ return CLIENT_IDS.includes(value);
35
+ }
36
+ export function clientLayout(id, env) {
37
+ const home = env.HOME?.trim() || homedir();
38
+ const label = LABELS[id];
39
+ if (id === 'codex') {
40
+ const root = env.CODEX_HOME?.trim() || join(home, '.codex');
41
+ return { id, label, root, config: join(root, 'config.toml'), format: 'toml', skillDir: join(root, 'skills', SKILL_NAME) };
42
+ }
43
+ if (id === 'cursor') {
44
+ const root = join(home, '.cursor');
45
+ return { id, label, root, config: join(root, 'mcp.json'), format: 'json', skillDir: join(root, 'skills', SKILL_NAME) };
46
+ }
47
+ const custom = env.CLAUDE_CONFIG_DIR?.trim();
48
+ const root = custom || join(home, '.claude');
49
+ return { id, label, root, config: custom ? join(custom, '.claude.json') : join(home, '.claude.json'), format: 'json', skillDir: join(root, 'skills', SKILL_NAME) };
50
+ }
51
+ const sha256 = (data) => createHash('sha256').update(data).digest('hex');
52
+ export function packagedSkill(dir = PACKAGED_SKILL_DIR) {
53
+ const files = [];
54
+ const walk = (path) => {
55
+ for (const entry of readdirSync(path, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name))) {
56
+ const full = join(path, entry.name);
57
+ if (entry.isDirectory())
58
+ walk(full);
59
+ else if (entry.isFile()) {
60
+ const data = readFileSync(full);
61
+ files.push({ rel: relative(dir, full).split(sep).join('/'), data, hash: sha256(data) });
62
+ }
63
+ }
64
+ };
65
+ walk(dir);
66
+ return files;
67
+ }
68
+ export const manifestPath = (paths, id) => join(paths.config, 'clients', `${id}.json`);
69
+ const isRecord = (value) => !!value && typeof value === 'object' && !Array.isArray(value);
70
+ const isHash = (value) => typeof value === 'string' && /^[0-9a-f]{64}$/.test(value);
71
+ const isSafeRel = (rel) => !!rel && !rel.startsWith('/') && !rel.split('/').some(part => !part || part === '.' || part === '..');
72
+ // A manifest that exists but is not one Botmancers wrote is reported, never
73
+ // trusted: without it every file and entry counts as user-owned.
74
+ export function loadManifest(paths, id) {
75
+ let text;
76
+ try {
77
+ text = readFileSync(manifestPath(paths, id), 'utf8');
78
+ }
79
+ catch (error) {
80
+ if (error.code === 'ENOENT')
81
+ return { manifest: null, problem: null };
82
+ return { manifest: null, problem: `it cannot be read (${error.code ?? 'error'})` };
83
+ }
84
+ let doc;
85
+ try {
86
+ doc = JSON.parse(text);
87
+ }
88
+ catch {
89
+ return { manifest: null, problem: 'it is not valid JSON' };
90
+ }
91
+ if (!isRecord(doc) || doc.schema !== 1 || doc.client !== id)
92
+ return { manifest: null, problem: `it is not a schema 1 manifest for ${id}` };
93
+ const { skill, mcp } = doc;
94
+ const valid = typeof doc.version === 'string'
95
+ && isRecord(skill) && typeof skill.dir === 'string' && isRecord(skill.files)
96
+ && Object.entries(skill.files).every(([rel, hash]) => isSafeRel(rel) && isHash(hash))
97
+ && isRecord(mcp) && typeof mcp.config === 'string' && mcp.name === MCP_SERVER_NAME && isHash(mcp.hash);
98
+ return valid ? { manifest: doc, problem: null } : { manifest: null, problem: 'it is missing or has malformed version, skill, or mcp fields' };
99
+ }
100
+ export function readManifest(paths, id) {
101
+ return loadManifest(paths, id).manifest;
102
+ }
103
+ export function mcpTarget(paths, mcpPort) {
104
+ const token = readEnvFile(paths.bridgeEnv)?.[ENV.mcpToken];
105
+ return token ? { url: `http://${PRODUCT_HOST}:${mcpPort}/mcp`, token } : null;
106
+ }
107
+ function stable(value) {
108
+ if (Array.isArray(value))
109
+ return `[${value.map(stable).join(',')}]`;
110
+ if (value && typeof value === 'object') {
111
+ return `{${Object.keys(value).sort().map(key => `${JSON.stringify(key)}:${stable(value[key])}`).join(',')}}`;
112
+ }
113
+ return JSON.stringify(value);
114
+ }
115
+ function jsonEntry(id, target) {
116
+ const headers = { Authorization: `Bearer ${target.token}` };
117
+ return id === 'claude' ? { type: 'http', url: target.url, headers } : { url: target.url, headers };
118
+ }
119
+ const tomlString = (value) => JSON.stringify(value);
120
+ function tomlEntry(target) {
121
+ return [
122
+ `[mcp_servers.${MCP_SERVER_NAME}]`,
123
+ `url = ${tomlString(target.url)}`,
124
+ `http_headers = { "Authorization" = ${tomlString(`Bearer ${target.token}`)} }`,
125
+ ].join('\n');
126
+ }
127
+ const TOML_HEADER = /^\s*\[\s*([^\]]*?)\s*\]\s*(?:#.*)?$/;
128
+ const tomlKey = (key) => key.split('.').map(part => part.trim().replace(/^"(.*)"$/, '$1')).join('.');
129
+ function tomlState(text) {
130
+ const lines = text.split('\n');
131
+ let table = '';
132
+ let start = -1;
133
+ let end = lines.length;
134
+ let other = null;
135
+ lines.forEach((line, index) => {
136
+ const header = TOML_HEADER.exec(line);
137
+ if (header && !line.trim().startsWith('[[')) {
138
+ table = tomlKey(header[1]);
139
+ if (start >= 0 && end === lines.length && index > start)
140
+ end = index;
141
+ if (table === `mcp_servers.${MCP_SERVER_NAME}`) {
142
+ if (start >= 0)
143
+ other = 'it defines [mcp_servers.botmancers] twice';
144
+ else
145
+ start = index;
146
+ }
147
+ else if (table.startsWith(`mcp_servers.${MCP_SERVER_NAME}.`))
148
+ other = `it has a [${header[1].trim()}] table`;
149
+ return;
150
+ }
151
+ if (line.trim().startsWith('[[')) {
152
+ if (start >= 0 && end === lines.length && index > start)
153
+ end = index;
154
+ table = '';
155
+ return;
156
+ }
157
+ const key = /^\s*([A-Za-z0-9_."-]+?)\s*=/.exec(line);
158
+ if (!key)
159
+ return;
160
+ const full = tomlKey(table ? `${table}.${key[1]}` : key[1]);
161
+ if (full.startsWith(`mcp_servers.${MCP_SERVER_NAME}`) && !(start >= 0 && table === `mcp_servers.${MCP_SERVER_NAME}`)) {
162
+ other = `it sets mcp_servers.${MCP_SERVER_NAME} outside a [mcp_servers.${MCP_SERVER_NAME}] table`;
163
+ }
164
+ });
165
+ if (start >= 0)
166
+ while (end > start + 1 && !lines[end - 1].trim())
167
+ end -= 1;
168
+ const block = start >= 0 ? lines.slice(start, end).join('\n') : null;
169
+ const rewrite = (entry) => {
170
+ const replacement = entry === null ? [] : String(entry).split('\n');
171
+ if (start >= 0) {
172
+ const next = [...lines.slice(0, start), ...replacement, ...lines.slice(end)];
173
+ if (entry === null) {
174
+ // Drop the blank line the block leaves behind.
175
+ while (start < next.length && start > 0 && !next[start].trim() && !next[start - 1].trim())
176
+ next.splice(start, 1);
177
+ }
178
+ return next.join('\n');
179
+ }
180
+ if (entry === null)
181
+ return text;
182
+ const body = text.replace(/\s*$/, '');
183
+ return `${body ? `${body}\n\n` : ''}${replacement.join('\n')}\n`;
184
+ };
185
+ if (other)
186
+ return { found: 'unmanageable', hash: null, reason: other, rewrite };
187
+ return block === null ? { found: 'absent', hash: null, rewrite } : { found: 'present', hash: sha256(block.trim()), rewrite };
188
+ }
189
+ function jsonState(text) {
190
+ let doc;
191
+ try {
192
+ doc = text.trim() ? JSON.parse(text) : {};
193
+ }
194
+ catch {
195
+ return { found: 'unmanageable', hash: null, reason: 'it is not valid JSON', rewrite: () => text };
196
+ }
197
+ if (!doc || typeof doc !== 'object' || Array.isArray(doc))
198
+ return { found: 'unmanageable', hash: null, reason: 'it is not a JSON object', rewrite: () => text };
199
+ const servers = doc.mcpServers;
200
+ if (servers !== undefined && (!servers || typeof servers !== 'object' || Array.isArray(servers))) {
201
+ return { found: 'unmanageable', hash: null, reason: 'its mcpServers is not an object', rewrite: () => text };
202
+ }
203
+ const entry = servers?.[MCP_SERVER_NAME];
204
+ const rewrite = (next) => {
205
+ const copy = { ...doc, mcpServers: { ...(servers ?? {}) } };
206
+ if (next === null)
207
+ delete copy.mcpServers[MCP_SERVER_NAME];
208
+ else
209
+ copy.mcpServers[MCP_SERVER_NAME] = next;
210
+ if (next === null && servers === undefined)
211
+ delete copy.mcpServers;
212
+ return `${JSON.stringify(copy, null, 2)}\n`;
213
+ };
214
+ return entry === undefined ? { found: 'absent', hash: null, rewrite } : { found: 'present', hash: sha256(stable(entry)), rewrite };
215
+ }
216
+ function readConfig(layout) {
217
+ try {
218
+ const info = lstatSync(layout.config);
219
+ if (!info.isFile())
220
+ return { text: '', exists: true, problem: 'it is not a regular file' };
221
+ return { text: readFileSync(layout.config, 'utf8'), exists: true };
222
+ }
223
+ catch (error) {
224
+ if (error.code === 'ENOENT')
225
+ return { text: '', exists: false };
226
+ return { text: '', exists: true, problem: `it cannot be read (${error.code ?? 'error'})` };
227
+ }
228
+ }
229
+ function entryState(layout, text) {
230
+ return layout.format === 'toml' ? tomlState(text) : jsonState(text);
231
+ }
232
+ function wantedEntry(layout, target) {
233
+ if (layout.format === 'toml') {
234
+ const value = tomlEntry(target);
235
+ return { value, hash: sha256(value.trim()) };
236
+ }
237
+ const value = jsonEntry(layout.id, target);
238
+ return { value, hash: sha256(stable(value)) };
239
+ }
240
+ function fileHash(path) {
241
+ try {
242
+ const info = lstatSync(path);
243
+ if (!info.isFile())
244
+ return 'not-a-file';
245
+ return sha256(readFileSync(path));
246
+ }
247
+ catch {
248
+ return null;
249
+ }
250
+ }
251
+ export function inspectClient(id, env, paths, target, skill = packagedSkill()) {
252
+ const layout = clientLayout(id, env);
253
+ const { manifest, problem: manifestProblem } = loadManifest(paths, id);
254
+ const installed = existsSync(layout.root);
255
+ let mcp;
256
+ const config = readConfig(layout);
257
+ const state = config.problem ? null : entryState(layout, config.text);
258
+ if (config.problem)
259
+ mcp = { state: 'conflict', reason: `${layout.config}: ${config.problem}` };
260
+ else if (state.found === 'unmanageable')
261
+ mcp = { state: 'conflict', reason: `${layout.config}: ${state.reason}` };
262
+ else if (state.found === 'absent')
263
+ mcp = { state: manifest ? 'missing' : 'absent' };
264
+ else if (target && state.hash === wantedEntry(layout, target).hash)
265
+ mcp = { state: 'current' };
266
+ else if (manifest && state.hash === manifest.mcp.hash) {
267
+ const legacy = target && wantedEntry(layout, { ...target, url: `http://${PRODUCT_HOST}:${LEGACY_DEFAULT_PORT}/mcp` });
268
+ mcp = state.hash === legacy?.hash
269
+ ? { state: 'stale', reason: `it still points to the old default http://${PRODUCT_HOST}:${LEGACY_DEFAULT_PORT}/mcp` }
270
+ : { state: 'stale', reason: 'its URL or token no longer matches this Botmancers' };
271
+ }
272
+ else
273
+ mcp = { state: 'conflict', reason: `${layout.config} already has an MCP server named "${MCP_SERVER_NAME}" that Botmancers did not write or that was edited` };
274
+ const conflicts = [];
275
+ let changes = 0;
276
+ let present = 0;
277
+ let dirProblem = null;
278
+ try {
279
+ const info = lstatSync(layout.skillDir);
280
+ if (!info.isDirectory())
281
+ dirProblem = `${layout.skillDir} is not a directory`;
282
+ }
283
+ catch { /* absent */ }
284
+ if (dirProblem)
285
+ conflicts.push(dirProblem);
286
+ else {
287
+ for (const file of skill) {
288
+ const current = fileHash(join(layout.skillDir, file.rel));
289
+ if (current !== null)
290
+ present += 1;
291
+ if (current === file.hash)
292
+ continue;
293
+ changes += 1;
294
+ if (current === null)
295
+ continue;
296
+ if (current !== 'not-a-file' && manifest?.skill.files[file.rel] === current)
297
+ continue;
298
+ conflicts.push(join(layout.skillDir, file.rel));
299
+ }
300
+ for (const [rel, hash] of Object.entries(manifest?.skill.files ?? {})) {
301
+ if (skill.some(file => file.rel === rel))
302
+ continue;
303
+ // A managed file this version no longer ships: removed if untouched, a conflict if edited.
304
+ const current = fileHash(join(layout.skillDir, rel));
305
+ if (current === null)
306
+ continue;
307
+ if (current === hash)
308
+ changes += 1;
309
+ else
310
+ conflicts.push(join(layout.skillDir, rel));
311
+ }
312
+ }
313
+ let skillState;
314
+ if (conflicts.length)
315
+ skillState = 'conflict';
316
+ else if (!changes)
317
+ skillState = 'current';
318
+ else if (!present)
319
+ skillState = manifest ? 'missing' : 'absent';
320
+ else
321
+ skillState = 'stale';
322
+ return { layout, installed, manifest, manifestProblem, mcp, skill: { state: skillState, conflicts, changes } };
323
+ }
324
+ const home = (path, env) => {
325
+ const base = env.HOME?.trim() || homedir();
326
+ return path.startsWith(`${base}${sep}`) ? `~${path.slice(base.length)}` : path;
327
+ };
328
+ export const repairCommand = (id) => `botmancers setup --client ${id}`;
329
+ export function mcpOnlyLines(target, paths) {
330
+ return [
331
+ 'Any MCP client works without the skill (MCP-only):',
332
+ ` URL ${target.url}`,
333
+ ` Header Authorization: Bearer <${ENV.mcpToken} from ${paths.bridgeEnv}>`,
334
+ ' The botmancers_* tool descriptions name every step: capabilities, list Agents and sessions, act, poll.',
335
+ ];
336
+ }
337
+ function conflictLines(view, env, removing) {
338
+ const id = view.layout.id;
339
+ const lines = [`botmancers setup --client ${id}: changed nothing for ${view.layout.label}; these are not Botmancers-managed or were edited since Botmancers wrote them:`];
340
+ if (view.mcp.state === 'conflict')
341
+ lines.push(` MCP ${view.mcp.reason}`);
342
+ for (const path of view.skill.conflicts)
343
+ lines.push(` skill ${home(path, env)}`);
344
+ if (view.manifestProblem)
345
+ lines.push(` owner the ownership manifest cannot be trusted (${view.manifestProblem}), so nothing counts as Botmancers-managed`);
346
+ lines.push('Botmancers never overwrites them. To let it manage them again, keep a copy of anything you want,', view.mcp.state === 'conflict'
347
+ ? `remove the "${MCP_SERVER_NAME}" MCP server entry from ${home(view.layout.config, env)} and the files listed above, then re-run: ${repairCommand(id)}${removing ? ' --remove' : ''}`
348
+ : `remove the files listed above, then re-run: ${repairCommand(id)}${removing ? ' --remove' : ''}`);
349
+ return lines;
350
+ }
351
+ // Writes go through this journal so a failure restores what was there.
352
+ class Journal {
353
+ undo = [];
354
+ write(path, data, mode) {
355
+ const before = existsSync(path) ? { data: readFileSync(path), mode: statSync(path).mode & 0o777 } : null;
356
+ const madeDirs = this.mkdirs(dirname(path));
357
+ const temp = `${path}.botmancers-${process.pid}.tmp`;
358
+ writeFileSync(temp, data, { mode: mode ?? before?.mode ?? 0o644 });
359
+ chmodSync(temp, mode ?? before?.mode ?? 0o644);
360
+ renameSync(temp, path);
361
+ this.undo.push(() => {
362
+ if (before) {
363
+ writeFileSync(path, before.data, { mode: before.mode });
364
+ chmodSync(path, before.mode);
365
+ }
366
+ else
367
+ rmSync(path, { force: true });
368
+ for (const dir of madeDirs.reverse())
369
+ try {
370
+ rmdirSync(dir);
371
+ }
372
+ catch { /* not empty */ }
373
+ });
374
+ }
375
+ remove(path) {
376
+ const before = readFileSync(path);
377
+ const mode = statSync(path).mode & 0o777;
378
+ rmSync(path);
379
+ // Removal prunes empty parents right after, so restoring recreates them.
380
+ this.undo.push(() => {
381
+ mkdirSync(dirname(path), { recursive: true });
382
+ writeFileSync(path, before, { mode });
383
+ chmodSync(path, mode);
384
+ });
385
+ }
386
+ mkdirs(dir) {
387
+ const made = [];
388
+ let at = dir;
389
+ while (!existsSync(at)) {
390
+ made.unshift(at);
391
+ at = dirname(at);
392
+ }
393
+ for (const path of made)
394
+ mkdirSync(path);
395
+ return made;
396
+ }
397
+ // Returns how many steps could not be undone.
398
+ rollback() {
399
+ let failed = 0;
400
+ for (const step of this.undo.reverse()) {
401
+ try {
402
+ step();
403
+ }
404
+ catch {
405
+ failed += 1;
406
+ }
407
+ }
408
+ this.undo = [];
409
+ return failed;
410
+ }
411
+ }
412
+ function writeManifest(paths, manifest) {
413
+ ensurePrivateDir(join(paths.config, 'clients'));
414
+ writePrivateFile(manifestPath(paths, manifest.client), `${JSON.stringify(manifest, null, 2)}\n`);
415
+ }
416
+ function pruneEmpty(dir, stop) {
417
+ let at = dir;
418
+ while (at.startsWith(`${stop}${sep}`)) {
419
+ try {
420
+ rmdirSync(at);
421
+ }
422
+ catch {
423
+ return;
424
+ }
425
+ at = dirname(at);
426
+ }
427
+ }
428
+ export function installClient(id, env, paths, target, version, skill = packagedSkill()) {
429
+ const view = inspectClient(id, env, paths, target, skill);
430
+ const { layout } = view;
431
+ if (!view.installed) {
432
+ return {
433
+ ok: false,
434
+ kind: 'missing-client',
435
+ lines: [
436
+ `botmancers setup --client ${id}: ${layout.label} is not set up for this user (${home(layout.root, env)} not found); nothing was written.`,
437
+ `Install and open ${layout.label} once, then re-run: ${repairCommand(id)}`,
438
+ ...mcpOnlyLines(target, paths),
439
+ ],
440
+ };
441
+ }
442
+ if (view.mcp.state === 'conflict' || view.skill.state === 'conflict')
443
+ return { ok: false, kind: 'conflict', lines: conflictLines(view, env, false) };
444
+ const wanted = wantedEntry(layout, target);
445
+ const journal = new Journal();
446
+ const files = {};
447
+ try {
448
+ for (const file of skill) {
449
+ const path = join(layout.skillDir, file.rel);
450
+ if (fileHash(path) !== file.hash)
451
+ journal.write(path, file.data, 0o644);
452
+ files[file.rel] = file.hash;
453
+ }
454
+ for (const [rel, hash] of Object.entries(view.manifest?.skill.files ?? {})) {
455
+ const path = join(layout.skillDir, rel);
456
+ if (!(rel in files) && fileHash(path) === hash) {
457
+ journal.remove(path);
458
+ pruneEmpty(dirname(path), layout.skillDir);
459
+ }
460
+ }
461
+ if (view.mcp.state !== 'current') {
462
+ const config = readConfig(layout);
463
+ // A configuration file this command creates holds the token: owner-only.
464
+ journal.write(layout.config, entryState(layout, config.text).rewrite(wanted.value), config.exists ? undefined : 0o600);
465
+ }
466
+ writeManifest(paths, {
467
+ schema: 1, client: id, version, installed_at: new Date().toISOString(),
468
+ skill: { dir: layout.skillDir, files },
469
+ mcp: { config: layout.config, name: MCP_SERVER_NAME, hash: wanted.hash },
470
+ });
471
+ }
472
+ catch (error) {
473
+ const unrestored = journal.rollback();
474
+ const code = error.code ?? error.message;
475
+ return {
476
+ ok: false,
477
+ kind: 'conflict',
478
+ lines: [
479
+ unrestored
480
+ ? `botmancers setup --client ${id}: could not write ${layout.label} files (${code}), and ${unrestored} change${unrestored > 1 ? 's' : ''} could not be undone; check ${home(layout.skillDir, env)} and ${home(layout.config, env)}.`
481
+ : `botmancers setup --client ${id}: could not write ${layout.label} files (${code}); restored everything this run had changed.`,
482
+ `Fix the permissions under ${home(layout.root, env)}${layout.config.startsWith(layout.root) ? '' : ` and of ${home(layout.config, env)}`}, then re-run: ${repairCommand(id)}`,
483
+ ],
484
+ };
485
+ }
486
+ const verb = (state, fresh) => (state === 'current' ? 'unchanged' : state === 'absent' ? fresh : 'updated');
487
+ return {
488
+ ok: true,
489
+ kind: 'installed',
490
+ lines: [
491
+ `botmancers setup --client ${id}: ${layout.label} is connected to Botmancers ${version}.`,
492
+ ` MCP ${home(layout.config, env)} "${MCP_SERVER_NAME}" -> ${target.url} (${verb(view.mcp.state, 'added')})`,
493
+ ` skill ${home(layout.skillDir, env)} ${SKILL_NAME} ${version} (${verb(view.skill.state, 'installed')})`,
494
+ ` owner ${manifestPath(paths, id)} records what Botmancers manages; edited files are never overwritten.`,
495
+ `Restart ${layout.label} (or reload its MCP servers) to pick up changes. Remove with: ${repairCommand(id)} --remove`,
496
+ ],
497
+ };
498
+ }
499
+ export function removeClient(id, env, paths) {
500
+ const view = inspectClient(id, env, paths, null);
501
+ const { layout, manifest } = view;
502
+ if (view.manifestProblem) {
503
+ return {
504
+ ok: false,
505
+ kind: 'conflict',
506
+ lines: [
507
+ `botmancers setup --client ${id} --remove: changed nothing; the ownership manifest ${manifestPath(paths, id)} cannot be trusted (${view.manifestProblem}), so Botmancers cannot tell which ${layout.label} files it wrote.`,
508
+ `Re-run ${repairCommand(id)} to rebuild it from files that match this release, or remove the "${MCP_SERVER_NAME}" MCP entry and ${home(layout.skillDir, env)} by hand and delete the manifest.`,
509
+ ],
510
+ };
511
+ }
512
+ if (!manifest) {
513
+ return { ok: true, kind: 'removed', lines: [`botmancers setup --client ${id} --remove: Botmancers has not set up ${layout.label}; nothing to remove.`] };
514
+ }
515
+ const kept = [];
516
+ const journal = new Journal();
517
+ try {
518
+ for (const [rel, hash] of Object.entries(manifest.skill.files)) {
519
+ const path = join(manifest.skill.dir, rel);
520
+ const current = fileHash(path);
521
+ if (current === null)
522
+ continue;
523
+ if (current === hash) {
524
+ journal.remove(path);
525
+ pruneEmpty(dirname(path), dirname(manifest.skill.dir));
526
+ }
527
+ else
528
+ kept.push(path);
529
+ }
530
+ const config = readConfig(layout);
531
+ const state = config.problem ? null : entryState(layout, config.text);
532
+ if (state?.found === 'present' && state.hash === manifest.mcp.hash)
533
+ journal.write(layout.config, state.rewrite(null));
534
+ else if (state?.found === 'present' || config.problem || state?.found === 'unmanageable')
535
+ kept.push(`${layout.config} "${MCP_SERVER_NAME}" MCP server entry`);
536
+ }
537
+ catch (error) {
538
+ const unrestored = journal.rollback();
539
+ const code = error.code ?? error.message;
540
+ return {
541
+ ok: false,
542
+ kind: 'conflict',
543
+ lines: [unrestored
544
+ ? `botmancers setup --client ${id} --remove: could not change ${layout.label} files (${code}), and ${unrestored} change${unrestored > 1 ? 's' : ''} could not be undone; check ${home(manifest.skill.dir, env)} and ${home(layout.config, env)}.`
545
+ : `botmancers setup --client ${id} --remove: could not change ${layout.label} files (${code}); restored them.`],
546
+ };
547
+ }
548
+ rmSync(manifestPath(paths, id), { force: true });
549
+ const lines = [`botmancers setup --client ${id} --remove: removed the Botmancers MCP connection and the ${SKILL_NAME} skill from ${layout.label}.`];
550
+ if (kept.length) {
551
+ lines.push('Kept, because they were edited after Botmancers wrote them (Botmancers no longer manages them):');
552
+ for (const path of kept)
553
+ lines.push(` ${home(path, env)}`);
554
+ }
555
+ return { ok: true, kind: 'removed', lines };
556
+ }
557
+ export function clientDoctorLines(env, paths, target) {
558
+ const out = [];
559
+ const skill = packagedSkill();
560
+ const detected = [];
561
+ for (const id of CLIENT_IDS) {
562
+ const view = inspectClient(id, env, paths, target, skill);
563
+ const { layout, manifest } = view;
564
+ if (view.manifestProblem) {
565
+ out.push(['warn', id, `ownership manifest ${manifestPath(paths, id)} cannot be trusted (${view.manifestProblem}); Botmancers treats ${layout.label} files as user-owned until it is rebuilt; repair: ${repairCommand(id)}`]);
566
+ continue;
567
+ }
568
+ if (!manifest) {
569
+ if (view.installed)
570
+ detected.push(id);
571
+ continue;
572
+ }
573
+ const where = home(layout.skillDir, env);
574
+ if (!view.installed) {
575
+ out.push(['warn', id, `${layout.label} was set up by Botmancers ${manifest.version}, but ${home(layout.root, env)} is gone; reinstall ${layout.label}, or forget it: ${repairCommand(id)} --remove`]);
576
+ continue;
577
+ }
578
+ if (view.mcp.state === 'conflict' || view.skill.state === 'conflict') {
579
+ const what = [view.mcp.state === 'conflict' ? 'its "botmancers" MCP entry' : '', view.skill.conflicts.length ? `${view.skill.conflicts.length} skill file${view.skill.conflicts.length > 1 ? 's' : ''} in ${where}` : '']
580
+ .filter(Boolean).join(' and ');
581
+ out.push(['warn', id, `conflicted: ${what} changed since Botmancers wrote them, so setup will not overwrite them; keep a copy of your edits, remove them, then run: ${repairCommand(id)}`]);
582
+ continue;
583
+ }
584
+ const mcp = view.mcp.state === 'current' ? 'MCP connected' : view.mcp.state === 'missing' ? 'MCP entry missing' : `MCP entry stale (${view.mcp.reason})`;
585
+ const skillText = view.skill.state === 'current'
586
+ ? `skill ${SKILL_NAME} ${manifest.version} current (${where})`
587
+ : view.skill.state === 'missing' ? `skill ${SKILL_NAME} missing (${where})`
588
+ : `skill ${SKILL_NAME} ${manifest.version} stale (${view.skill.changes} file${view.skill.changes > 1 ? 's differ' : ' differs'} from this release)`;
589
+ const healthy = view.mcp.state === 'current' && view.skill.state === 'current';
590
+ out.push([healthy ? 'ok' : 'warn', id, `${mcp}; ${skillText}${healthy ? '' : `; repair: ${repairCommand(id)}`}`]);
591
+ }
592
+ if (detected.length) {
593
+ out.push(['info', 'clients', `${detected.map(id => LABELS[id]).join(', ')} found but not connected (optional): ${detected.map(repairCommand).join(' / ')}`]);
594
+ }
595
+ else if (!out.length) {
596
+ out.push(['info', 'clients', `no MCP client set up by Botmancers (optional): ${repairCommand('codex')}|cursor|claude, or connect any MCP client by hand`]);
597
+ }
598
+ return out;
599
+ }
600
+ export class ClientUsageError extends Error {
601
+ }
602
+ export function parseSetupArgs(argv) {
603
+ const clients = [];
604
+ let remove = false;
605
+ for (let at = 0; at < argv.length; at += 1) {
606
+ const arg = argv[at];
607
+ const inline = arg.startsWith('--client=') ? arg.slice('--client='.length) : null;
608
+ if (arg === '--client' || inline !== null) {
609
+ const value = inline ?? argv[++at];
610
+ if (!value)
611
+ throw new ClientUsageError('--client needs a value: codex, cursor, or claude.');
612
+ for (const name of value.split(',').map(part => part.trim()).filter(Boolean)) {
613
+ if (!isClientId(name)) {
614
+ throw new ClientUsageError(`unsupported client "${name}"; supported: ${CLIENT_IDS.join(', ')}. Other MCP clients need no setup: point them at the bridge URL with the MCP token header (botmancers setup prints both).`);
615
+ }
616
+ if (!clients.includes(name))
617
+ clients.push(name);
618
+ }
619
+ }
620
+ else if (arg === '--remove')
621
+ remove = true;
622
+ else
623
+ throw new ClientUsageError(`unknown argument ${arg}.`);
624
+ }
625
+ if (remove && !clients.length)
626
+ throw new ClientUsageError('--remove needs --client codex|cursor|claude.');
627
+ return { clients, remove };
628
+ }
629
+ // Plain `botmancers setup` refreshes the clients Botmancers already set up
630
+ // (for example after an upgrade); `--client` installs or refreshes the named ones.
631
+ export function setupClients(options, env, paths, target, version) {
632
+ if (options.remove)
633
+ return options.clients.map(id => removeClient(id, env, paths));
634
+ const ids = options.clients.length ? options.clients : CLIENT_IDS.filter(id => existsSync(manifestPath(paths, id)));
635
+ if (!target)
636
+ return ids.map(id => ({ ok: false, kind: 'conflict', lines: [`botmancers setup --client ${id}: the bridge credentials are missing; run botmancers setup first.`] }));
637
+ const skill = packagedSkill();
638
+ return ids.map(id => installClient(id, env, paths, target, version, skill));
639
+ }
package/dist/config.d.ts CHANGED
@@ -6,7 +6,8 @@ export declare const ENV: {
6
6
  readonly port: "BOTMANCERS_MCP_PORT";
7
7
  };
8
8
  export declare const DEFAULT_HOST = "127.0.0.1";
9
- export declare const DEFAULT_PORT = 43124;
9
+ export declare const DEFAULT_PORT = 3332;
10
+ export declare const LEGACY_DEFAULT_PORT = 43124;
10
11
  export declare const MIN_MCP_TOKEN_LENGTH = 16;
11
12
  export interface BridgeConfig {
12
13
  botmancersUrl: string;