botmancers 0.3.0 → 0.4.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.
- package/CHANGELOG.md +79 -1
- package/README.md +162 -21
- package/app/.next/BUILD_ID +1 -1
- package/app/.next/app-path-routes-manifest.json +20 -1
- package/app/.next/build-manifest.json +3 -3
- package/app/.next/prerender-manifest.json +32 -4
- package/app/.next/required-server-files.json +2 -2
- package/app/.next/routes-manifest.json +143 -0
- package/app/.next/server/app/_global-error/page.js +1 -1
- package/app/.next/server/app/_global-error/page.js.nft.json +1 -1
- package/app/.next/server/app/_global-error/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_global-error.html +1 -1
- package/app/.next/server/app/_global-error.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/app/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/app/.next/server/app/_not-found/page.js +1 -1
- package/app/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/app/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/_not-found.html +1 -1
- package/app/.next/server/app/_not-found.rsc +2 -2
- package/app/.next/server/app/_not-found.segments/_full.segment.rsc +2 -2
- package/app/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/_not-found.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/api/agent-deck/decks/route.js +2 -2
- package/app/.next/server/app/api/agent-deck/decks/route.js.nft.json +1 -1
- package/app/.next/server/app/api/agent-deck/settings/route.js +2 -2
- package/app/.next/server/app/api/agent-deck/settings/route.js.nft.json +1 -1
- package/app/.next/server/app/api/bots/[id]/config/route.js +2 -2
- package/app/.next/server/app/api/bots/[id]/config/route.js.nft.json +1 -1
- package/app/.next/server/app/api/bots/[id]/sessions/[ref]/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/bots/[id]/sessions/[ref]/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/bots/[id]/sessions/[ref]/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/bots/[id]/sessions/[ref]/route.js +9 -0
- package/app/.next/server/app/api/bots/[id]/sessions/[ref]/route.js.nft.json +1 -0
- package/app/.next/server/app/api/bots/[id]/sessions/[ref]/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/bots/[id]/sessions/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/bots/[id]/sessions/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/bots/[id]/sessions/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/bots/[id]/sessions/route.js +9 -0
- package/app/.next/server/app/api/bots/[id]/sessions/route.js.nft.json +1 -0
- package/app/.next/server/app/api/bots/[id]/sessions/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/bots/[id]/skill/route.js +2 -2
- package/app/.next/server/app/api/bots/[id]/skill/route.js.nft.json +1 -1
- package/app/.next/server/app/api/bots/availability/route.js +1 -1
- package/app/.next/server/app/api/bots/availability/route.js.nft.json +1 -1
- package/app/.next/server/app/api/bots/delete-preview/route.js +3 -3
- package/app/.next/server/app/api/bots/delete-preview/route.js.nft.json +1 -1
- package/app/.next/server/app/api/bots/import/route.js +2 -2
- package/app/.next/server/app/api/bots/import/route.js.nft.json +1 -1
- package/app/.next/server/app/api/bots/manage/route.js +2 -2
- package/app/.next/server/app/api/bots/manage/route.js.nft.json +1 -1
- package/app/.next/server/app/api/bots/name-migrations/route.js +2 -2
- package/app/.next/server/app/api/bots/name-migrations/route.js.nft.json +1 -1
- package/app/.next/server/app/api/bots/route.js +6 -6
- package/app/.next/server/app/api/bots/route.js.nft.json +1 -1
- package/app/.next/server/app/api/conversations/[id]/approve/route.js +2 -2
- package/app/.next/server/app/api/conversations/[id]/approve/route.js.nft.json +1 -1
- package/app/.next/server/app/api/conversations/[id]/deny/route.js +2 -2
- package/app/.next/server/app/api/conversations/[id]/deny/route.js.nft.json +1 -1
- package/app/.next/server/app/api/conversations/[id]/draft/route.js +2 -2
- package/app/.next/server/app/api/conversations/[id]/draft/route.js.nft.json +1 -1
- package/app/.next/server/app/api/conversations/[id]/messages/[messageId]/stop/route.js +2 -2
- package/app/.next/server/app/api/conversations/[id]/messages/[messageId]/stop/route.js.nft.json +1 -1
- package/app/.next/server/app/api/conversations/[id]/messages/route.js +6 -6
- package/app/.next/server/app/api/conversations/[id]/messages/route.js.nft.json +1 -1
- package/app/.next/server/app/api/conversations/[id]/route.js +2 -2
- package/app/.next/server/app/api/conversations/[id]/route.js.nft.json +1 -1
- package/app/.next/server/app/api/conversations/[id]/stop/route.js +3 -3
- package/app/.next/server/app/api/conversations/[id]/stop/route.js.nft.json +1 -1
- package/app/.next/server/app/api/conversations/route.js +2 -2
- package/app/.next/server/app/api/conversations/route.js.nft.json +1 -1
- package/app/.next/server/app/api/exchanges/[id]/cancel/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/exchanges/[id]/cancel/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/exchanges/[id]/cancel/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/exchanges/[id]/cancel/route.js +11 -0
- package/app/.next/server/app/api/exchanges/[id]/cancel/route.js.nft.json +1 -0
- package/app/.next/server/app/api/exchanges/[id]/cancel/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/exchanges/[id]/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/exchanges/[id]/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/exchanges/[id]/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/exchanges/[id]/route.js +11 -0
- package/app/.next/server/app/api/exchanges/[id]/route.js.nft.json +1 -0
- package/app/.next/server/app/api/exchanges/[id]/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/exchanges/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/exchanges/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/exchanges/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/exchanges/route.js +12 -0
- package/app/.next/server/app/api/exchanges/route.js.nft.json +1 -0
- package/app/.next/server/app/api/exchanges/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/files/[name]/route.js +1 -1
- package/app/.next/server/app/api/files/[name]/route.js.nft.json +1 -1
- package/app/.next/server/app/api/groups/route.js +2 -2
- package/app/.next/server/app/api/groups/route.js.nft.json +1 -1
- package/app/.next/server/app/api/health/route.js.nft.json +1 -1
- package/app/.next/server/app/api/import-capabilities/route.js +1 -1
- package/app/.next/server/app/api/import-capabilities/route.js.nft.json +1 -1
- package/app/.next/server/app/api/marketplace-handoff/route.js +1 -1
- package/app/.next/server/app/api/marketplace-handoff/route.js.nft.json +1 -1
- package/app/.next/server/app/api/marketplace-handoff/status/route.js +1 -1
- package/app/.next/server/app/api/marketplace-handoff/status/route.js.nft.json +1 -1
- package/app/.next/server/app/api/mcp/route.js +2 -2
- package/app/.next/server/app/api/mcp/route.js.nft.json +1 -1
- package/app/.next/server/app/api/messages/[id]/between/route.js +2 -2
- package/app/.next/server/app/api/messages/[id]/between/route.js.nft.json +1 -1
- package/app/.next/server/app/api/service-grants/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/service-grants/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/service-grants/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/service-grants/route.js +9 -0
- package/app/.next/server/app/api/service-grants/route.js.nft.json +1 -0
- package/app/.next/server/app/api/service-grants/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/conversations/[conversationId]/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/conversations/[conversationId]/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/conversations/[conversationId]/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/conversations/[conversationId]/route.js +11 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/conversations/[conversationId]/route.js.nft.json +1 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/conversations/[conversationId]/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/conversations/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/conversations/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/conversations/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/conversations/route.js +11 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/conversations/route.js.nft.json +1 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/conversations/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/messages/route.js +4 -3
- package/app/.next/server/app/api/v0/agents/[agentId]/messages/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v0/agents/[agentId]/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/route.js +11 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/route.js.nft.json +1 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/sessions/[ref]/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/sessions/[ref]/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/sessions/[ref]/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/sessions/[ref]/route.js +11 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/sessions/[ref]/route.js.nft.json +1 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/sessions/[ref]/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/sessions/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/sessions/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/sessions/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/sessions/route.js +11 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/sessions/route.js.nft.json +1 -0
- package/app/.next/server/app/api/v0/agents/[agentId]/sessions/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/v0/agents/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/v0/agents/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/v0/agents/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/v0/agents/route.js +11 -0
- package/app/.next/server/app/api/v0/agents/route.js.nft.json +1 -0
- package/app/.next/server/app/api/v0/agents/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/v0/capabilities/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/v0/capabilities/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/v0/capabilities/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/v0/capabilities/route.js +11 -0
- package/app/.next/server/app/api/v0/capabilities/route.js.nft.json +1 -0
- package/app/.next/server/app/api/v0/capabilities/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/v0/conversations/[id]/route.js +4 -3
- package/app/.next/server/app/api/v0/conversations/[id]/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v0/exchanges/[id]/cancel/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/v0/exchanges/[id]/cancel/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/v0/exchanges/[id]/cancel/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/v0/exchanges/[id]/cancel/route.js +11 -0
- package/app/.next/server/app/api/v0/exchanges/[id]/cancel/route.js.nft.json +1 -0
- package/app/.next/server/app/api/v0/exchanges/[id]/cancel/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/v0/exchanges/[id]/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/v0/exchanges/[id]/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/v0/exchanges/[id]/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/v0/exchanges/[id]/route.js +11 -0
- package/app/.next/server/app/api/v0/exchanges/[id]/route.js.nft.json +1 -0
- package/app/.next/server/app/api/v0/exchanges/[id]/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/v0/exchanges/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/v0/exchanges/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/v0/exchanges/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/v0/exchanges/route.js +11 -0
- package/app/.next/server/app/api/v0/exchanges/route.js.nft.json +1 -0
- package/app/.next/server/app/api/v0/exchanges/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/v0/mcp/route.js +5 -3
- package/app/.next/server/app/api/v0/mcp/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v0/requests/[id]/route.js +4 -3
- package/app/.next/server/app/api/v0/requests/[id]/route.js.nft.json +1 -1
- package/app/.next/server/app/api/v0/sessions/[ref]/messages/route/app-paths-manifest.json +3 -0
- package/app/.next/server/app/api/v0/sessions/[ref]/messages/route/build-manifest.json +12 -0
- package/app/.next/server/app/api/v0/sessions/[ref]/messages/route/server-reference-manifest.json +4 -0
- package/app/.next/server/app/api/v0/sessions/[ref]/messages/route.js +11 -0
- package/app/.next/server/app/api/v0/sessions/[ref]/messages/route.js.nft.json +1 -0
- package/app/.next/server/app/api/v0/sessions/[ref]/messages/route_client-reference-manifest.js +3 -0
- package/app/.next/server/app/api/wake-grants/[id]/revoke/route.js +5 -5
- package/app/.next/server/app/api/wake-grants/[id]/revoke/route.js.nft.json +1 -1
- package/app/.next/server/app/api/wakes/[id]/decision/route.js +5 -5
- package/app/.next/server/app/api/wakes/[id]/decision/route.js.nft.json +1 -1
- package/app/.next/server/app/api/wakes/[id]/retry/route.js +5 -5
- package/app/.next/server/app/api/wakes/[id]/retry/route.js.nft.json +1 -1
- package/app/.next/server/app/bots/[id]/config/page.js +1 -1
- package/app/.next/server/app/bots/[id]/config/page.js.nft.json +1 -1
- package/app/.next/server/app/bots/[id]/config/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/exchanges/page/app-paths-manifest.json +3 -0
- package/app/.next/server/app/exchanges/page/build-manifest.json +20 -0
- package/app/.next/server/app/exchanges/page/next-font-manifest.json +11 -0
- package/app/.next/server/app/exchanges/page/react-loadable-manifest.json +1 -0
- package/app/.next/server/app/exchanges/page/server-reference-manifest.json +4 -0
- package/app/.next/server/app/exchanges/page.js +13 -0
- package/app/.next/server/app/exchanges/page.js.nft.json +1 -0
- package/app/.next/server/app/exchanges/page_client-reference-manifest.js +3 -0
- package/app/.next/server/app/exchanges.html +1 -0
- package/app/.next/server/app/exchanges.meta +34 -0
- package/app/.next/server/app/exchanges.rsc +22 -0
- package/app/.next/server/app/exchanges.segments/_full.segment.rsc +22 -0
- package/app/.next/server/app/exchanges.segments/_tree.segment.rsc +4 -0
- package/app/.next/server/app/exchanges.segments/exchanges/__PAGE__.segment.rsc +26 -0
- package/app/.next/server/app/index.html +1 -1
- package/app/.next/server/app/index.rsc +3 -3
- package/app/.next/server/app/index.segments/__PAGE__.segment.rsc +3 -3
- package/app/.next/server/app/index.segments/_full.segment.rsc +3 -3
- package/app/.next/server/app/index.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/page.js +1 -1
- package/app/.next/server/app/page.js.nft.json +1 -1
- package/app/.next/server/app/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/settings/page.js +1 -1
- package/app/.next/server/app/settings/page.js.nft.json +1 -1
- package/app/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/app/.next/server/app/settings.html +1 -1
- package/app/.next/server/app/settings.rsc +2 -2
- package/app/.next/server/app/settings.segments/_full.segment.rsc +2 -2
- package/app/.next/server/app/settings.segments/_tree.segment.rsc +2 -2
- package/app/.next/server/app/settings.segments/settings/__PAGE__.segment.rsc +2 -2
- package/app/.next/server/app/threads/[id]/page/app-paths-manifest.json +3 -0
- package/app/.next/server/app/threads/[id]/page/build-manifest.json +20 -0
- package/app/.next/server/app/threads/[id]/page/next-font-manifest.json +11 -0
- package/app/.next/server/app/threads/[id]/page/react-loadable-manifest.json +1 -0
- package/app/.next/server/app/threads/[id]/page/server-reference-manifest.json +4 -0
- package/app/.next/server/app/threads/[id]/page.js +13 -0
- package/app/.next/server/app/threads/[id]/page.js.nft.json +1 -0
- package/app/.next/server/app/threads/[id]/page_client-reference-manifest.js +3 -0
- package/app/.next/server/app-paths-manifest.json +20 -1
- package/app/.next/server/chunks/0ivl_api_v0_agents_[agentId]_conversations_[conversationId]_route_actions_0lvijtu.js +3 -0
- package/app/.next/server/chunks/1oeh_server_app_api_v0_agents_[agentId]_conversations_route_actions_0ko3117.js +3 -0
- package/app/.next/server/chunks/1oeh_server_app_api_v0_agents_[agentId]_sessions_[ref]_route_actions_0o7q3vt.js +3 -0
- package/app/.next/server/chunks/{[externals]__18bqksw._.js → [externals]__06lqs5i._.js} +1 -1
- package/app/.next/server/chunks/{[root-of-the-server]__1vxmbdl._.js → [root-of-the-server]__0-45blq._.js} +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__0ab4e_k._.js +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__0izjfmr._.js +285 -53
- package/app/.next/server/chunks/{[root-of-the-server]__07l_rgn._.js → [root-of-the-server]__0j0i8xz._.js} +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__0wtzcge._.js +3 -0
- package/app/.next/server/chunks/{[root-of-the-server]__19hjzs0._.js → [root-of-the-server]__15hknun._.js} +1 -1
- package/app/.next/server/chunks/{[root-of-the-server]__08i4wq6._.js → [root-of-the-server]__16ikszu._.js} +1 -1
- package/app/.next/server/chunks/{[root-of-the-server]__1khwkvb._.js → [root-of-the-server]__1c3e2ds._.js} +1 -1
- package/app/.next/server/chunks/[root-of-the-server]__1kvvdpx._.js +2 -2
- package/app/.next/server/chunks/[root-of-the-server]__1qoa704._.js +2 -2
- package/app/.next/server/chunks/[root-of-the-server]__1slu7d7._.js +7 -0
- package/app/.next/server/chunks/_06rti77._.js +30 -0
- package/app/.next/server/chunks/_09k38l1._.js +3 -0
- package/app/.next/server/chunks/_0dlg5kj._.js +30 -0
- package/app/.next/server/chunks/_0dyculb._.js +30 -0
- package/app/.next/server/chunks/_0eig2jc._.js +30 -0
- package/app/.next/server/chunks/_0ggf7vy._.js +1 -1
- package/app/.next/server/chunks/_0kghtb6._.js +3 -0
- package/app/.next/server/chunks/_0th2j4w._.js +1 -1
- package/app/.next/server/chunks/_0uz7r06._.js +30 -0
- package/app/.next/server/chunks/_0x05ts4._.js +3 -0
- package/app/.next/server/chunks/_0y3geoj._.js +30 -0
- package/app/.next/server/chunks/_1-5mthb._.js +1 -1
- package/app/.next/server/chunks/_12tq5uv._.js +30 -0
- package/app/.next/server/chunks/_147-4gl._.js +3 -0
- package/app/.next/server/chunks/_14ky6a2._.js +30 -0
- package/app/.next/server/chunks/_16kbxdt._.js +30 -0
- package/app/.next/server/chunks/_1963m2f._.js +30 -0
- package/app/.next/server/chunks/_1_34_h3._.js +30 -0
- package/app/.next/server/chunks/_1cc-2mx._.js +3 -0
- package/app/.next/server/chunks/_1inyx08._.js +1 -1
- package/app/.next/server/chunks/_1nurj3f._.js +30 -0
- package/app/.next/server/chunks/_1p2rf_n._.js +30 -0
- package/app/.next/server/chunks/_1u6tw78._.js +30 -0
- package/app/.next/server/chunks/_20azcus._.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_bots_[id]_sessions_[ref]_route_actions_02gp9-5.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_bots_[id]_sessions_route_actions_1s_wxg4.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_exchanges_[id]_cancel_route_actions_0lh0fl4.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_exchanges_[id]_route_actions_1w4jhin.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_exchanges_route_actions_028wchg.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_service-grants_route_actions_1459xk1.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_v0_agents_[agentId]_route_actions_127sxvv.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_v0_agents_[agentId]_sessions_route_actions_0pm6tcu.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_v0_agents_route_actions_00azkhd.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_v0_capabilities_route_actions_0d-eefd.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_v0_exchanges_[id]_cancel_route_actions_1hb2q7i.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_v0_exchanges_[id]_route_actions_098f50-.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_v0_exchanges_route_actions_1ftmhhm.js +3 -0
- package/app/.next/server/chunks/_next-internal_server_app_api_v0_sessions_[ref]_messages_route_actions_1-rgf_k.js +3 -0
- package/app/.next/server/chunks/lib_0kik6bx._.js +1 -1
- package/app/.next/server/chunks/lib_0pe3tiv._.js +1 -1
- package/app/.next/server/chunks/lib_0t3s3rj._.js +30 -0
- package/app/.next/server/chunks/lib_0zxi6rx._.js +148 -0
- package/app/.next/server/chunks/lib_12udr7g._.js +148 -0
- package/app/.next/server/chunks/lib_service-api-http_ts_0xzqhny._.js +25 -0
- package/app/.next/server/chunks/lib_session-catalog_ts_1i7f38f._.js +30 -0
- package/app/.next/server/chunks/ssr/{[root-of-the-server]__0sq4frf._.js → [root-of-the-server]__03186rx._.js} +1 -1
- package/app/.next/server/chunks/ssr/[root-of-the-server]__03xw2d9._.js +3 -0
- package/app/.next/server/chunks/ssr/{[root-of-the-server]__1x7o-fe._.js → [root-of-the-server]__0zzcbqg._.js} +1 -1
- package/app/.next/server/chunks/ssr/{[root-of-the-server]__029oxo_._.js → [root-of-the-server]__1feicqq._.js} +1 -1
- package/app/.next/server/chunks/ssr/[root-of-the-server]__1t063pe._.js +3 -0
- package/app/.next/server/chunks/ssr/_00ysoah._.js +3 -0
- package/app/.next/server/chunks/ssr/_157wnb_._.js +3 -0
- package/app/.next/server/chunks/ssr/_1o94bnv._.js +1 -1
- package/app/.next/server/chunks/ssr/_next-internal_server_app_exchanges_page_actions_0hcso2x.js +3 -0
- package/app/.next/server/chunks/ssr/_next-internal_server_app_threads_[id]_page_actions_1fte2n3.js +3 -0
- package/app/.next/server/chunks/ssr/app_1-nwnha._.js +3 -0
- package/app/.next/server/chunks/ssr/app_bots_[id]_config_page_tsx_1e0uue9._.js +3 -0
- package/app/.next/server/chunks/ssr/app_components_AgentDeckRuntime_tsx_024janf._.js +3 -0
- package/app/.next/server/chunks/ssr/node_modules_1nkgb45._.js +23 -0
- package/app/.next/server/chunks/ssr/node_modules_next_0x3i8za._.js +131 -0
- package/app/.next/server/middleware-build-manifest.js +3 -3
- package/app/.next/server/middleware.js +1 -1
- package/app/.next/server/next-font-manifest.js +1 -1
- package/app/.next/server/next-font-manifest.json +8 -0
- package/app/.next/server/pages/404.html +1 -1
- package/app/.next/server/pages/500.html +1 -1
- package/app/.next/server/prefetch-hints.json +14 -0
- package/app/.next/server/server-reference-manifest.js +1 -1
- package/app/.next/server/server-reference-manifest.json +1 -1
- package/app/.next/static/chunks/1i5xroz391zkb.js +1 -0
- package/app/.next/static/chunks/{3zqbpbm93yqzh.css → 1vz50l951sr9e.css} +1 -1
- package/app/.next/static/chunks/24ggj819yt3y6.js +1 -0
- package/app/.next/static/chunks/2_8lcalraul5s.js +3 -0
- package/app/.next/static/chunks/30i0-l04mmdvk.js +1 -0
- package/app/BUILD_INFO.json +2 -2
- package/app/package.json +1 -1
- package/app/server.js +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +33 -5
- package/dist/clients.d.ts +86 -0
- package/dist/clients.js +635 -0
- package/dist/config.js +2 -2
- package/dist/contract.d.ts +6 -1
- package/dist/contract.js +28 -8
- package/dist/index.d.ts +1 -1
- package/dist/index.js +3 -3
- package/dist/managed.js +7 -0
- package/dist/product.d.ts +2 -0
- package/dist/product.js +6 -0
- package/dist/server.js +5 -4
- package/dist/upstream.js +21 -7
- package/package.json +7 -6
- package/schemas/botmancers.mcp.v2.tools.json +2981 -0
- package/skills/botmancers-collaboration/SKILL.md +99 -0
- package/skills/botmancers-collaboration/references/workflows.md +209 -0
- package/app/.next/server/chunks/[root-of-the-server]__09d-yrq._.js +0 -3
- package/app/.next/server/chunks/[root-of-the-server]__0za34e1._.js +0 -7
- package/app/.next/server/chunks/[root-of-the-server]__1fjpie4._.js +0 -3
- package/app/.next/server/chunks/[root-of-the-server]__1qanlbg._.js +0 -3
- package/app/.next/server/chunks/[root-of-the-server]__20wve4_._.js +0 -3
- package/app/.next/server/chunks/lib_051fv4x._.js +0 -111
- package/app/.next/server/chunks/lib_07adeq3._.js +0 -111
- package/app/.next/server/chunks/ssr/_0k_7i66._.js +0 -131
- package/app/.next/server/chunks/ssr/_1flnty7._.js +0 -23
- package/app/.next/server/chunks/ssr/node_modules_@swc_helpers_cjs__interop_require_default_cjs_1ztp13a._.js +0 -3
- package/app/.next/static/chunks/0qbtymorcz-l9.js +0 -3
- /package/app/.next/static/{u4r8RPgEfpxk-DGXeKV6g → ewp56HqU5-d9bpFog3bli}/_buildManifest.js +0 -0
- /package/app/.next/static/{u4r8RPgEfpxk-DGXeKV6g → ewp56HqU5-d9bpFog3bli}/_clientMiddlewareManifest.js +0 -0
- /package/app/.next/static/{u4r8RPgEfpxk-DGXeKV6g → ewp56HqU5-d9bpFog3bli}/_ssgManifest.js +0 -0
package/dist/clients.js
ADDED
|
@@ -0,0 +1,635 @@
|
|
|
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 } 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
|
+
mcp = { state: 'stale', reason: 'its URL or token no longer matches this Botmancers' };
|
|
268
|
+
else
|
|
269
|
+
mcp = { state: 'conflict', reason: `${layout.config} already has an MCP server named "${MCP_SERVER_NAME}" that Botmancers did not write or that was edited` };
|
|
270
|
+
const conflicts = [];
|
|
271
|
+
let changes = 0;
|
|
272
|
+
let present = 0;
|
|
273
|
+
let dirProblem = null;
|
|
274
|
+
try {
|
|
275
|
+
const info = lstatSync(layout.skillDir);
|
|
276
|
+
if (!info.isDirectory())
|
|
277
|
+
dirProblem = `${layout.skillDir} is not a directory`;
|
|
278
|
+
}
|
|
279
|
+
catch { /* absent */ }
|
|
280
|
+
if (dirProblem)
|
|
281
|
+
conflicts.push(dirProblem);
|
|
282
|
+
else {
|
|
283
|
+
for (const file of skill) {
|
|
284
|
+
const current = fileHash(join(layout.skillDir, file.rel));
|
|
285
|
+
if (current !== null)
|
|
286
|
+
present += 1;
|
|
287
|
+
if (current === file.hash)
|
|
288
|
+
continue;
|
|
289
|
+
changes += 1;
|
|
290
|
+
if (current === null)
|
|
291
|
+
continue;
|
|
292
|
+
if (current !== 'not-a-file' && manifest?.skill.files[file.rel] === current)
|
|
293
|
+
continue;
|
|
294
|
+
conflicts.push(join(layout.skillDir, file.rel));
|
|
295
|
+
}
|
|
296
|
+
for (const [rel, hash] of Object.entries(manifest?.skill.files ?? {})) {
|
|
297
|
+
if (skill.some(file => file.rel === rel))
|
|
298
|
+
continue;
|
|
299
|
+
// A managed file this version no longer ships: removed if untouched, a conflict if edited.
|
|
300
|
+
const current = fileHash(join(layout.skillDir, rel));
|
|
301
|
+
if (current === null)
|
|
302
|
+
continue;
|
|
303
|
+
if (current === hash)
|
|
304
|
+
changes += 1;
|
|
305
|
+
else
|
|
306
|
+
conflicts.push(join(layout.skillDir, rel));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
let skillState;
|
|
310
|
+
if (conflicts.length)
|
|
311
|
+
skillState = 'conflict';
|
|
312
|
+
else if (!changes)
|
|
313
|
+
skillState = 'current';
|
|
314
|
+
else if (!present)
|
|
315
|
+
skillState = manifest ? 'missing' : 'absent';
|
|
316
|
+
else
|
|
317
|
+
skillState = 'stale';
|
|
318
|
+
return { layout, installed, manifest, manifestProblem, mcp, skill: { state: skillState, conflicts, changes } };
|
|
319
|
+
}
|
|
320
|
+
const home = (path, env) => {
|
|
321
|
+
const base = env.HOME?.trim() || homedir();
|
|
322
|
+
return path.startsWith(`${base}${sep}`) ? `~${path.slice(base.length)}` : path;
|
|
323
|
+
};
|
|
324
|
+
export const repairCommand = (id) => `botmancers setup --client ${id}`;
|
|
325
|
+
export function mcpOnlyLines(target, paths) {
|
|
326
|
+
return [
|
|
327
|
+
'Any MCP client works without the skill (MCP-only):',
|
|
328
|
+
` URL ${target.url}`,
|
|
329
|
+
` Header Authorization: Bearer <${ENV.mcpToken} from ${paths.bridgeEnv}>`,
|
|
330
|
+
' The botmancers_* tool descriptions name every step: capabilities, list Agents and sessions, act, poll.',
|
|
331
|
+
];
|
|
332
|
+
}
|
|
333
|
+
function conflictLines(view, env, removing) {
|
|
334
|
+
const id = view.layout.id;
|
|
335
|
+
const lines = [`botmancers setup --client ${id}: changed nothing for ${view.layout.label}; these are not Botmancers-managed or were edited since Botmancers wrote them:`];
|
|
336
|
+
if (view.mcp.state === 'conflict')
|
|
337
|
+
lines.push(` MCP ${view.mcp.reason}`);
|
|
338
|
+
for (const path of view.skill.conflicts)
|
|
339
|
+
lines.push(` skill ${home(path, env)}`);
|
|
340
|
+
if (view.manifestProblem)
|
|
341
|
+
lines.push(` owner the ownership manifest cannot be trusted (${view.manifestProblem}), so nothing counts as Botmancers-managed`);
|
|
342
|
+
lines.push('Botmancers never overwrites them. To let it manage them again, keep a copy of anything you want,', view.mcp.state === 'conflict'
|
|
343
|
+
? `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' : ''}`
|
|
344
|
+
: `remove the files listed above, then re-run: ${repairCommand(id)}${removing ? ' --remove' : ''}`);
|
|
345
|
+
return lines;
|
|
346
|
+
}
|
|
347
|
+
// Writes go through this journal so a failure restores what was there.
|
|
348
|
+
class Journal {
|
|
349
|
+
undo = [];
|
|
350
|
+
write(path, data, mode) {
|
|
351
|
+
const before = existsSync(path) ? { data: readFileSync(path), mode: statSync(path).mode & 0o777 } : null;
|
|
352
|
+
const madeDirs = this.mkdirs(dirname(path));
|
|
353
|
+
const temp = `${path}.botmancers-${process.pid}.tmp`;
|
|
354
|
+
writeFileSync(temp, data, { mode: mode ?? before?.mode ?? 0o644 });
|
|
355
|
+
chmodSync(temp, mode ?? before?.mode ?? 0o644);
|
|
356
|
+
renameSync(temp, path);
|
|
357
|
+
this.undo.push(() => {
|
|
358
|
+
if (before) {
|
|
359
|
+
writeFileSync(path, before.data, { mode: before.mode });
|
|
360
|
+
chmodSync(path, before.mode);
|
|
361
|
+
}
|
|
362
|
+
else
|
|
363
|
+
rmSync(path, { force: true });
|
|
364
|
+
for (const dir of madeDirs.reverse())
|
|
365
|
+
try {
|
|
366
|
+
rmdirSync(dir);
|
|
367
|
+
}
|
|
368
|
+
catch { /* not empty */ }
|
|
369
|
+
});
|
|
370
|
+
}
|
|
371
|
+
remove(path) {
|
|
372
|
+
const before = readFileSync(path);
|
|
373
|
+
const mode = statSync(path).mode & 0o777;
|
|
374
|
+
rmSync(path);
|
|
375
|
+
// Removal prunes empty parents right after, so restoring recreates them.
|
|
376
|
+
this.undo.push(() => {
|
|
377
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
378
|
+
writeFileSync(path, before, { mode });
|
|
379
|
+
chmodSync(path, mode);
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
mkdirs(dir) {
|
|
383
|
+
const made = [];
|
|
384
|
+
let at = dir;
|
|
385
|
+
while (!existsSync(at)) {
|
|
386
|
+
made.unshift(at);
|
|
387
|
+
at = dirname(at);
|
|
388
|
+
}
|
|
389
|
+
for (const path of made)
|
|
390
|
+
mkdirSync(path);
|
|
391
|
+
return made;
|
|
392
|
+
}
|
|
393
|
+
// Returns how many steps could not be undone.
|
|
394
|
+
rollback() {
|
|
395
|
+
let failed = 0;
|
|
396
|
+
for (const step of this.undo.reverse()) {
|
|
397
|
+
try {
|
|
398
|
+
step();
|
|
399
|
+
}
|
|
400
|
+
catch {
|
|
401
|
+
failed += 1;
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
this.undo = [];
|
|
405
|
+
return failed;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
function writeManifest(paths, manifest) {
|
|
409
|
+
ensurePrivateDir(join(paths.config, 'clients'));
|
|
410
|
+
writePrivateFile(manifestPath(paths, manifest.client), `${JSON.stringify(manifest, null, 2)}\n`);
|
|
411
|
+
}
|
|
412
|
+
function pruneEmpty(dir, stop) {
|
|
413
|
+
let at = dir;
|
|
414
|
+
while (at.startsWith(`${stop}${sep}`)) {
|
|
415
|
+
try {
|
|
416
|
+
rmdirSync(at);
|
|
417
|
+
}
|
|
418
|
+
catch {
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
at = dirname(at);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
export function installClient(id, env, paths, target, version, skill = packagedSkill()) {
|
|
425
|
+
const view = inspectClient(id, env, paths, target, skill);
|
|
426
|
+
const { layout } = view;
|
|
427
|
+
if (!view.installed) {
|
|
428
|
+
return {
|
|
429
|
+
ok: false,
|
|
430
|
+
kind: 'missing-client',
|
|
431
|
+
lines: [
|
|
432
|
+
`botmancers setup --client ${id}: ${layout.label} is not set up for this user (${home(layout.root, env)} not found); nothing was written.`,
|
|
433
|
+
`Install and open ${layout.label} once, then re-run: ${repairCommand(id)}`,
|
|
434
|
+
...mcpOnlyLines(target, paths),
|
|
435
|
+
],
|
|
436
|
+
};
|
|
437
|
+
}
|
|
438
|
+
if (view.mcp.state === 'conflict' || view.skill.state === 'conflict')
|
|
439
|
+
return { ok: false, kind: 'conflict', lines: conflictLines(view, env, false) };
|
|
440
|
+
const wanted = wantedEntry(layout, target);
|
|
441
|
+
const journal = new Journal();
|
|
442
|
+
const files = {};
|
|
443
|
+
try {
|
|
444
|
+
for (const file of skill) {
|
|
445
|
+
const path = join(layout.skillDir, file.rel);
|
|
446
|
+
if (fileHash(path) !== file.hash)
|
|
447
|
+
journal.write(path, file.data, 0o644);
|
|
448
|
+
files[file.rel] = file.hash;
|
|
449
|
+
}
|
|
450
|
+
for (const [rel, hash] of Object.entries(view.manifest?.skill.files ?? {})) {
|
|
451
|
+
const path = join(layout.skillDir, rel);
|
|
452
|
+
if (!(rel in files) && fileHash(path) === hash) {
|
|
453
|
+
journal.remove(path);
|
|
454
|
+
pruneEmpty(dirname(path), layout.skillDir);
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
if (view.mcp.state !== 'current') {
|
|
458
|
+
const config = readConfig(layout);
|
|
459
|
+
// A configuration file this command creates holds the token: owner-only.
|
|
460
|
+
journal.write(layout.config, entryState(layout, config.text).rewrite(wanted.value), config.exists ? undefined : 0o600);
|
|
461
|
+
}
|
|
462
|
+
writeManifest(paths, {
|
|
463
|
+
schema: 1, client: id, version, installed_at: new Date().toISOString(),
|
|
464
|
+
skill: { dir: layout.skillDir, files },
|
|
465
|
+
mcp: { config: layout.config, name: MCP_SERVER_NAME, hash: wanted.hash },
|
|
466
|
+
});
|
|
467
|
+
}
|
|
468
|
+
catch (error) {
|
|
469
|
+
const unrestored = journal.rollback();
|
|
470
|
+
const code = error.code ?? error.message;
|
|
471
|
+
return {
|
|
472
|
+
ok: false,
|
|
473
|
+
kind: 'conflict',
|
|
474
|
+
lines: [
|
|
475
|
+
unrestored
|
|
476
|
+
? `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)}.`
|
|
477
|
+
: `botmancers setup --client ${id}: could not write ${layout.label} files (${code}); restored everything this run had changed.`,
|
|
478
|
+
`Fix the permissions under ${home(layout.root, env)}${layout.config.startsWith(layout.root) ? '' : ` and of ${home(layout.config, env)}`}, then re-run: ${repairCommand(id)}`,
|
|
479
|
+
],
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
const verb = (state, fresh) => (state === 'current' ? 'unchanged' : state === 'absent' ? fresh : 'updated');
|
|
483
|
+
return {
|
|
484
|
+
ok: true,
|
|
485
|
+
kind: 'installed',
|
|
486
|
+
lines: [
|
|
487
|
+
`botmancers setup --client ${id}: ${layout.label} is connected to Botmancers ${version}.`,
|
|
488
|
+
` MCP ${home(layout.config, env)} "${MCP_SERVER_NAME}" -> ${target.url} (${verb(view.mcp.state, 'added')})`,
|
|
489
|
+
` skill ${home(layout.skillDir, env)} ${SKILL_NAME} ${version} (${verb(view.skill.state, 'installed')})`,
|
|
490
|
+
` owner ${manifestPath(paths, id)} records what Botmancers manages; edited files are never overwritten.`,
|
|
491
|
+
`Restart ${layout.label} (or reload its MCP servers) to pick up changes. Remove with: ${repairCommand(id)} --remove`,
|
|
492
|
+
],
|
|
493
|
+
};
|
|
494
|
+
}
|
|
495
|
+
export function removeClient(id, env, paths) {
|
|
496
|
+
const view = inspectClient(id, env, paths, null);
|
|
497
|
+
const { layout, manifest } = view;
|
|
498
|
+
if (view.manifestProblem) {
|
|
499
|
+
return {
|
|
500
|
+
ok: false,
|
|
501
|
+
kind: 'conflict',
|
|
502
|
+
lines: [
|
|
503
|
+
`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.`,
|
|
504
|
+
`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.`,
|
|
505
|
+
],
|
|
506
|
+
};
|
|
507
|
+
}
|
|
508
|
+
if (!manifest) {
|
|
509
|
+
return { ok: true, kind: 'removed', lines: [`botmancers setup --client ${id} --remove: Botmancers has not set up ${layout.label}; nothing to remove.`] };
|
|
510
|
+
}
|
|
511
|
+
const kept = [];
|
|
512
|
+
const journal = new Journal();
|
|
513
|
+
try {
|
|
514
|
+
for (const [rel, hash] of Object.entries(manifest.skill.files)) {
|
|
515
|
+
const path = join(manifest.skill.dir, rel);
|
|
516
|
+
const current = fileHash(path);
|
|
517
|
+
if (current === null)
|
|
518
|
+
continue;
|
|
519
|
+
if (current === hash) {
|
|
520
|
+
journal.remove(path);
|
|
521
|
+
pruneEmpty(dirname(path), dirname(manifest.skill.dir));
|
|
522
|
+
}
|
|
523
|
+
else
|
|
524
|
+
kept.push(path);
|
|
525
|
+
}
|
|
526
|
+
const config = readConfig(layout);
|
|
527
|
+
const state = config.problem ? null : entryState(layout, config.text);
|
|
528
|
+
if (state?.found === 'present' && state.hash === manifest.mcp.hash)
|
|
529
|
+
journal.write(layout.config, state.rewrite(null));
|
|
530
|
+
else if (state?.found === 'present' || config.problem || state?.found === 'unmanageable')
|
|
531
|
+
kept.push(`${layout.config} "${MCP_SERVER_NAME}" MCP server entry`);
|
|
532
|
+
}
|
|
533
|
+
catch (error) {
|
|
534
|
+
const unrestored = journal.rollback();
|
|
535
|
+
const code = error.code ?? error.message;
|
|
536
|
+
return {
|
|
537
|
+
ok: false,
|
|
538
|
+
kind: 'conflict',
|
|
539
|
+
lines: [unrestored
|
|
540
|
+
? `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)}.`
|
|
541
|
+
: `botmancers setup --client ${id} --remove: could not change ${layout.label} files (${code}); restored them.`],
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
rmSync(manifestPath(paths, id), { force: true });
|
|
545
|
+
const lines = [`botmancers setup --client ${id} --remove: removed the Botmancers MCP connection and the ${SKILL_NAME} skill from ${layout.label}.`];
|
|
546
|
+
if (kept.length) {
|
|
547
|
+
lines.push('Kept, because they were edited after Botmancers wrote them (Botmancers no longer manages them):');
|
|
548
|
+
for (const path of kept)
|
|
549
|
+
lines.push(` ${home(path, env)}`);
|
|
550
|
+
}
|
|
551
|
+
return { ok: true, kind: 'removed', lines };
|
|
552
|
+
}
|
|
553
|
+
export function clientDoctorLines(env, paths, target) {
|
|
554
|
+
const out = [];
|
|
555
|
+
const skill = packagedSkill();
|
|
556
|
+
const detected = [];
|
|
557
|
+
for (const id of CLIENT_IDS) {
|
|
558
|
+
const view = inspectClient(id, env, paths, target, skill);
|
|
559
|
+
const { layout, manifest } = view;
|
|
560
|
+
if (view.manifestProblem) {
|
|
561
|
+
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)}`]);
|
|
562
|
+
continue;
|
|
563
|
+
}
|
|
564
|
+
if (!manifest) {
|
|
565
|
+
if (view.installed)
|
|
566
|
+
detected.push(id);
|
|
567
|
+
continue;
|
|
568
|
+
}
|
|
569
|
+
const where = home(layout.skillDir, env);
|
|
570
|
+
if (!view.installed) {
|
|
571
|
+
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`]);
|
|
572
|
+
continue;
|
|
573
|
+
}
|
|
574
|
+
if (view.mcp.state === 'conflict' || view.skill.state === 'conflict') {
|
|
575
|
+
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}` : '']
|
|
576
|
+
.filter(Boolean).join(' and ');
|
|
577
|
+
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)}`]);
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
const mcp = view.mcp.state === 'current' ? 'MCP connected' : view.mcp.state === 'missing' ? 'MCP entry missing' : `MCP entry stale (${view.mcp.reason})`;
|
|
581
|
+
const skillText = view.skill.state === 'current'
|
|
582
|
+
? `skill ${SKILL_NAME} ${manifest.version} current (${where})`
|
|
583
|
+
: view.skill.state === 'missing' ? `skill ${SKILL_NAME} missing (${where})`
|
|
584
|
+
: `skill ${SKILL_NAME} ${manifest.version} stale (${view.skill.changes} file${view.skill.changes > 1 ? 's differ' : ' differs'} from this release)`;
|
|
585
|
+
const healthy = view.mcp.state === 'current' && view.skill.state === 'current';
|
|
586
|
+
out.push([healthy ? 'ok' : 'warn', id, `${mcp}; ${skillText}${healthy ? '' : `; repair: ${repairCommand(id)}`}`]);
|
|
587
|
+
}
|
|
588
|
+
if (detected.length) {
|
|
589
|
+
out.push(['info', 'clients', `${detected.map(id => LABELS[id]).join(', ')} found but not connected (optional): ${detected.map(repairCommand).join(' / ')}`]);
|
|
590
|
+
}
|
|
591
|
+
else if (!out.length) {
|
|
592
|
+
out.push(['info', 'clients', `no MCP client set up by Botmancers (optional): ${repairCommand('codex')}|cursor|claude, or connect any MCP client by hand`]);
|
|
593
|
+
}
|
|
594
|
+
return out;
|
|
595
|
+
}
|
|
596
|
+
export class ClientUsageError extends Error {
|
|
597
|
+
}
|
|
598
|
+
export function parseSetupArgs(argv) {
|
|
599
|
+
const clients = [];
|
|
600
|
+
let remove = false;
|
|
601
|
+
for (let at = 0; at < argv.length; at += 1) {
|
|
602
|
+
const arg = argv[at];
|
|
603
|
+
const inline = arg.startsWith('--client=') ? arg.slice('--client='.length) : null;
|
|
604
|
+
if (arg === '--client' || inline !== null) {
|
|
605
|
+
const value = inline ?? argv[++at];
|
|
606
|
+
if (!value)
|
|
607
|
+
throw new ClientUsageError('--client needs a value: codex, cursor, or claude.');
|
|
608
|
+
for (const name of value.split(',').map(part => part.trim()).filter(Boolean)) {
|
|
609
|
+
if (!isClientId(name)) {
|
|
610
|
+
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).`);
|
|
611
|
+
}
|
|
612
|
+
if (!clients.includes(name))
|
|
613
|
+
clients.push(name);
|
|
614
|
+
}
|
|
615
|
+
}
|
|
616
|
+
else if (arg === '--remove')
|
|
617
|
+
remove = true;
|
|
618
|
+
else
|
|
619
|
+
throw new ClientUsageError(`unknown argument ${arg}.`);
|
|
620
|
+
}
|
|
621
|
+
if (remove && !clients.length)
|
|
622
|
+
throw new ClientUsageError('--remove needs --client codex|cursor|claude.');
|
|
623
|
+
return { clients, remove };
|
|
624
|
+
}
|
|
625
|
+
// Plain `botmancers setup` refreshes the clients Botmancers already set up
|
|
626
|
+
// (for example after an upgrade); `--client` installs or refreshes the named ones.
|
|
627
|
+
export function setupClients(options, env, paths, target, version) {
|
|
628
|
+
if (options.remove)
|
|
629
|
+
return options.clients.map(id => removeClient(id, env, paths));
|
|
630
|
+
const ids = options.clients.length ? options.clients : CLIENT_IDS.filter(id => existsSync(manifestPath(paths, id)));
|
|
631
|
+
if (!target)
|
|
632
|
+
return ids.map(id => ({ ok: false, kind: 'conflict', lines: [`botmancers setup --client ${id}: the bridge credentials are missing; run botmancers setup first.`] }));
|
|
633
|
+
const skill = packagedSkill();
|
|
634
|
+
return ids.map(id => installClient(id, env, paths, target, version, skill));
|
|
635
|
+
}
|
package/dist/config.js
CHANGED
|
@@ -160,8 +160,8 @@ export function parseCli(argv, env) {
|
|
|
160
160
|
}
|
|
161
161
|
export const HELP = `Usage: botmancers [options]
|
|
162
162
|
|
|
163
|
-
Run the Botmancers MCP bridge: a Streamable HTTP MCP server (
|
|
164
|
-
botmancers.mcp.v1) that forwards tool calls to a running Botmancers app.
|
|
163
|
+
Run the Botmancers MCP bridge: a Streamable HTTP MCP server (contracts
|
|
164
|
+
botmancers.mcp.v1 and v2) that forwards tool calls to a running Botmancers app.
|
|
165
165
|
|
|
166
166
|
Options:
|
|
167
167
|
--botmancers-url <url> Botmancers base URL (env ${ENV.url}, required)
|
package/dist/contract.d.ts
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
export declare const MCP_CONTRACT = "botmancers.mcp.
|
|
1
|
+
export declare const MCP_CONTRACT = "botmancers.mcp.v2";
|
|
2
|
+
export declare const MCP_CONTRACT_V1 = "botmancers.mcp.v1";
|
|
3
|
+
export declare const MCP_CONTRACTS: readonly ["botmancers.mcp.v1", "botmancers.mcp.v2"];
|
|
2
4
|
export declare const MCP_PROTOCOL_VERSIONS: readonly ["2025-11-25", "2025-06-18", "2025-03-26"];
|
|
3
5
|
export declare const MCP_INSTRUCTIONS: string;
|
|
4
6
|
export interface McpTool {
|
|
@@ -12,10 +14,13 @@ export interface McpTool {
|
|
|
12
14
|
}
|
|
13
15
|
export interface ToolContract {
|
|
14
16
|
contract: string;
|
|
17
|
+
contracts?: string[];
|
|
15
18
|
tools: McpTool[];
|
|
16
19
|
}
|
|
17
20
|
export declare const TOOL_SCHEMA_URL: import("url").URL;
|
|
21
|
+
export declare const TOOL_SCHEMA_V1_URL: import("url").URL;
|
|
18
22
|
export declare function loadToolContract(): ToolContract;
|
|
23
|
+
export declare function toolContractOf(tool: McpTool): string;
|
|
19
24
|
export declare function negotiateProtocolVersion(requested: unknown): string;
|
|
20
25
|
export declare const PACKAGE_JSON_URL: import("url").URL;
|
|
21
26
|
export declare function packageVersion(): string;
|