cade-cli 0.16.2__tar.gz → 0.16.3__tar.gz

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 (201) hide show
  1. {cade_cli-0.16.2 → cade_cli-0.16.3}/PKG-INFO +2 -2
  2. {cade_cli-0.16.2 → cade_cli-0.16.3}/README.md +1 -1
  3. {cade_cli-0.16.2 → cade_cli-0.16.3}/pyproject.toml +1 -1
  4. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/mcp.py +64 -0
  5. cade_cli-0.16.3/src/cadecoder/cli/mcp_hosts.py +351 -0
  6. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/onboarding.py +16 -0
  7. {cade_cli-0.16.2 → cade_cli-0.16.3}/.gitignore +0 -0
  8. {cade_cli-0.16.2 → cade_cli-0.16.3}/LICENSE +0 -0
  9. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/__init__.py +0 -0
  10. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/__main__.py +0 -0
  11. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/_metadata.py +0 -0
  12. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/config.py +0 -0
  13. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/errors.py +0 -0
  14. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/grants.py +0 -0
  15. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/resources.py +0 -0
  16. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/sandbox.py +0 -0
  17. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/server.py +0 -0
  18. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/__init__.py +0 -0
  19. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/_read_cache.py +0 -0
  20. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/access.py +0 -0
  21. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/agents.py +0 -0
  22. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/context.py +0 -0
  23. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/filesystem.py +0 -0
  24. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/git.py +0 -0
  25. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/notifications.py +0 -0
  26. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/questions.py +0 -0
  27. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/results.py +0 -0
  28. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/schemas.py +0 -0
  29. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/search.py +0 -0
  30. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/shell.py +0 -0
  31. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/snippets.py +0 -0
  32. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/tasks.py +0 -0
  33. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/web_fetch.py +0 -0
  34. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/tools/web_search.py +0 -0
  35. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/utils.py +0 -0
  36. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/web/__init__.py +0 -0
  37. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/web/arcade_client.py +0 -0
  38. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/web/cache.py +0 -0
  39. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/web/extract.py +0 -0
  40. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/web/markdown.py +0 -0
  41. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/web/preapproved.py +0 -0
  42. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/web/prompts.py +0 -0
  43. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/web/scrape.py +0 -0
  44. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/web/search/__init__.py +0 -0
  45. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/web/search/arcade.py +0 -0
  46. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/web/search/base.py +0 -0
  47. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cade_mcp_local/web/search/http.py +0 -0
  48. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/__init__.py +0 -0
  49. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/ai/__init__.py +0 -0
  50. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/ai/prompts.py +0 -0
  51. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/__init__.py +0 -0
  52. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/app.py +0 -0
  53. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/auth.py +0 -0
  54. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/__init__.py +0 -0
  55. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/account.py +0 -0
  56. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/agents.py +0 -0
  57. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/auth.py +0 -0
  58. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/chat.py +0 -0
  59. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/cron.py +0 -0
  60. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/daemon.py +0 -0
  61. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/grant.py +0 -0
  62. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/hooks.py +0 -0
  63. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/mem.py +0 -0
  64. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/tasks.py +0 -0
  65. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/thread.py +0 -0
  66. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/cli/commands/tools.py +0 -0
  67. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/__init__.py +0 -0
  68. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/agent.py +0 -0
  69. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/comms.py +0 -0
  70. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/config.py +0 -0
  71. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/constants.py +0 -0
  72. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/errors.py +0 -0
  73. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/frozen.py +0 -0
  74. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/git.py +0 -0
  75. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/inbox.py +0 -0
  76. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/logging.py +0 -0
  77. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/memory.py +0 -0
  78. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/model_specs.py +0 -0
  79. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/names.py +0 -0
  80. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/paths.py +0 -0
  81. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/runtime.py +0 -0
  82. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/secrets.py +0 -0
  83. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/spawn.py +0 -0
  84. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/core/types.py +0 -0
  85. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/__init__.py +0 -0
  86. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/adapters/__init__.py +0 -0
  87. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/adapters/base.py +0 -0
  88. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/adapters/factory.py +0 -0
  89. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/adapters/imessage.py +0 -0
  90. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/adapters/registry.py +0 -0
  91. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/adapters/stub.py +0 -0
  92. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/adapters/telegram.py +0 -0
  93. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/allowlist.py +0 -0
  94. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/attach.py +0 -0
  95. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/chunker.py +0 -0
  96. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/client.py +0 -0
  97. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/commands.py +0 -0
  98. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/config.py +0 -0
  99. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/control.py +0 -0
  100. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/cron.py +0 -0
  101. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/elicitation.py +0 -0
  102. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/ensure.py +0 -0
  103. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/format.py +0 -0
  104. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/gateway/__init__.py +0 -0
  105. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/gateway/app.py +0 -0
  106. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/gateway/arcade_export.py +0 -0
  107. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/gateway/auth.py +0 -0
  108. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/gateway/constants.py +0 -0
  109. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/gateway/elicitation.py +0 -0
  110. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/gateway/exposure.py +0 -0
  111. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/gateway/limits.py +0 -0
  112. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/gateway/middleware.py +0 -0
  113. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/gateway/resources.py +0 -0
  114. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/gateway/subscriptions.py +0 -0
  115. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/gateway/turn_bridge.py +0 -0
  116. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/grants.py +0 -0
  117. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/inbox_cron.py +0 -0
  118. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/install.py +0 -0
  119. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/live.py +0 -0
  120. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/lock.py +0 -0
  121. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/mesh.py +0 -0
  122. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/message_pump.py +0 -0
  123. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/observability.py +0 -0
  124. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/owner.py +0 -0
  125. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/progress_sink.py +0 -0
  126. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/registry.py +0 -0
  127. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/router.py +0 -0
  128. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/runner.py +0 -0
  129. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/runner_main.py +0 -0
  130. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/secrets.py +0 -0
  131. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/secrets_broker.py +0 -0
  132. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/server.py +0 -0
  133. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/services.py +0 -0
  134. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/shim.py +0 -0
  135. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/sinks.py +0 -0
  136. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/supervisor.py +0 -0
  137. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/tokens.py +0 -0
  138. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/traffic.py +0 -0
  139. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/turns.py +0 -0
  140. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/daemon/wake.py +0 -0
  141. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/execution/__init__.py +0 -0
  142. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/execution/context_window.py +0 -0
  143. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/execution/mcp_schema_index.py +0 -0
  144. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/execution/orchestrator.py +0 -0
  145. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/execution/parallel.py +0 -0
  146. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/execution/tool_result_store.py +0 -0
  147. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/execution/tool_schema_cache.py +0 -0
  148. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/hooks/__init__.py +0 -0
  149. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/hooks/config.py +0 -0
  150. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/hooks/engine.py +0 -0
  151. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/hooks/executors/__init__.py +0 -0
  152. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/hooks/executors/callback.py +0 -0
  153. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/hooks/executors/command.py +0 -0
  154. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/hooks/executors/http.py +0 -0
  155. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/hooks/executors/prompt.py +0 -0
  156. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/hooks/executors/ssrf_guard.py +0 -0
  157. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/hooks/matchers.py +0 -0
  158. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/hooks/registry.py +0 -0
  159. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/hooks/types.py +0 -0
  160. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/providers/__init__.py +0 -0
  161. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/providers/anthropic.py +0 -0
  162. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/providers/base.py +0 -0
  163. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/providers/ollama.py +0 -0
  164. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/providers/openai.py +0 -0
  165. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/serve/__init__.py +0 -0
  166. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/storage/__init__.py +0 -0
  167. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/storage/threads.py +0 -0
  168. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tasks/__init__.py +0 -0
  169. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tasks/scheduler.py +0 -0
  170. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tasks/store.py +0 -0
  171. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tasks/types.py +0 -0
  172. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/templates/login_failed.html +0 -0
  173. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/templates/login_success.html +0 -0
  174. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/templates/serve/launchd.plist.tmpl +0 -0
  175. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/templates/serve/serve.toml.example +0 -0
  176. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/templates/serve/systemd.service.tmpl +0 -0
  177. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/templates/styles.css +0 -0
  178. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tools/__init__.py +0 -0
  179. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tools/manager/__init__.py +0 -0
  180. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tools/manager/_request_ctx.py +0 -0
  181. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tools/manager/base.py +0 -0
  182. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tools/manager/composite.py +0 -0
  183. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tools/manager/config.py +0 -0
  184. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tools/manager/mcp.py +0 -0
  185. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tools/search/__init__.py +0 -0
  186. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tools/search/discovered.py +0 -0
  187. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tools/search/scoring.py +0 -0
  188. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/tools/search/service.py +0 -0
  189. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/ui/__init__.py +0 -0
  190. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/ui/completion.py +0 -0
  191. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/ui/display.py +0 -0
  192. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/ui/elicitation.py +0 -0
  193. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/ui/input.py +0 -0
  194. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/ui/session.py +0 -0
  195. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/ui/slash.py +0 -0
  196. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/voice/__init__.py +0 -0
  197. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/voice/audio.py +0 -0
  198. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/voice/cleanup.py +0 -0
  199. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/voice/session.py +0 -0
  200. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/voice/stt.py +0 -0
  201. {cade_cli-0.16.2 → cade_cli-0.16.3}/src/cadecoder/voice/tts.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cade-cli
3
- Version: 0.16.2
3
+ Version: 0.16.3
4
4
  Summary: Cade - The CLI Agent from Arcade.dev (install: curl -fsSL https://arcadeagent.dev/install | sh)
5
5
  Project-URL: Homepage, https://arcade.dev
6
6
  Project-URL: Documentation, https://arcadeagent.dev/docs
@@ -129,7 +129,7 @@ The script detects your OS/arch, downloads the matching prebuilt binary
129
129
  `~/.local/bin`. Pin a version or install location:
130
130
 
131
131
  ```bash
132
- CADE_VERSION=0.16.2 CADE_INSTALL_DIR=/usr/local/bin \
132
+ CADE_VERSION=0.16.3 CADE_INSTALL_DIR=/usr/local/bin \
133
133
  sh -c "$(curl -fsSL https://arcadeagent.dev/install)"
134
134
  ```
135
135
 
@@ -38,7 +38,7 @@ The script detects your OS/arch, downloads the matching prebuilt binary
38
38
  `~/.local/bin`. Pin a version or install location:
39
39
 
40
40
  ```bash
41
- CADE_VERSION=0.16.2 CADE_INSTALL_DIR=/usr/local/bin \
41
+ CADE_VERSION=0.16.3 CADE_INSTALL_DIR=/usr/local/bin \
42
42
  sh -c "$(curl -fsSL https://arcadeagent.dev/install)"
43
43
  ```
44
44
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cade-cli"
3
- version = "0.16.2"
3
+ version = "0.16.3"
4
4
  description = "Cade - The CLI Agent from Arcade.dev (install: curl -fsSL https://arcadeagent.dev/install | sh)"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -617,6 +617,70 @@ def authorize_server(
617
617
  raise typer.Exit(1)
618
618
 
619
619
 
620
+ @mcp_app.command("install-hosts")
621
+ def install_hosts_cmd(
622
+ agent: Annotated[
623
+ str,
624
+ typer.Option("--agent", "-a", help="Agent the stdio shim targets."),
625
+ ] = "default",
626
+ force: Annotated[
627
+ bool,
628
+ typer.Option("--force", "-f", help="Overwrite an existing cade MCP entry."),
629
+ ] = False,
630
+ dry_run: Annotated[
631
+ bool,
632
+ typer.Option("--dry-run", help="Show what would change without writing."),
633
+ ] = False,
634
+ ) -> None:
635
+ """Register Cade as an MCP server in Claude Desktop, Cursor, Claude Code, etc.
636
+
637
+ Only touches hosts that already look installed (their config dir/file exists
638
+ under your home directory). Safe to re-run — updates the command path after
639
+ upgrades. The curl installer runs this automatically unless
640
+ ``CADE_SKIP_MCP_HOSTS=1``.
641
+ """
642
+ from cadecoder.cli.mcp_hosts import install_into_hosts, resolve_cade_command
643
+
644
+ command = resolve_cade_command()
645
+ updates = install_into_hosts(command=command, agent=agent, force=force, dry_run=dry_run)
646
+ if not updates:
647
+ console.print(
648
+ "[dim]No MCP hosts detected (looked for Cursor, Claude Desktop, "
649
+ "Claude Code, OpenCode, Windsurf).[/dim]"
650
+ )
651
+ console.print(
652
+ "[dim]After installing a host, re-run [bold]cade mcp install-hosts[/bold].[/dim]"
653
+ )
654
+ return
655
+
656
+ console.print(f"[dim]Using binary:[/dim] {command}")
657
+ changed = 0
658
+ for u in updates:
659
+ style = {
660
+ "added": "green",
661
+ "updated": "cyan",
662
+ "unchanged": "dim",
663
+ "would-added": "yellow",
664
+ "would-updated": "yellow",
665
+ "error": "red",
666
+ "skipped": "dim",
667
+ }.get(u.status, "white")
668
+ msg = f"[{style}]{u.status}[/{style}] {u.name} [dim]{u.path}[/dim]"
669
+ if u.detail:
670
+ msg += f" ({u.detail})"
671
+ console.print(msg)
672
+ if u.status in ("added", "updated", "would-added", "would-updated"):
673
+ changed += 1
674
+
675
+ if changed and not dry_run:
676
+ console.print(
677
+ "\n[green]Done.[/green] Restart those apps, then run "
678
+ "[bold]cade daemon start[/bold] (or just [bold]cade[/bold] — it autostarts)."
679
+ )
680
+ elif dry_run:
681
+ console.print(f"\n[dim]Dry run — {changed} host(s) would change.[/dim]")
682
+
683
+
620
684
  @mcp_app.command("token-info")
621
685
  def token_info(
622
686
  name: Annotated[str, typer.Argument(help="Name of the server")],
@@ -0,0 +1,351 @@
1
+ """Register Cade as an MCP server in detected AI host apps.
2
+
3
+ Scans typical home-directory config locations for Claude Desktop, Cursor,
4
+ Claude Code, OpenCode, and Windsurf. When a host's config dir (or file)
5
+ already exists, merges a ``cade`` stdio entry that points at
6
+ ``cade __mcp-adapter`` — using an absolute path so GUI apps find the binary
7
+ even when ``PATH`` is incomplete.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ import json
13
+ import os
14
+ import platform
15
+ import re
16
+ import shutil
17
+ import sys
18
+ from dataclasses import dataclass
19
+ from enum import Enum
20
+ from pathlib import Path
21
+ from typing import Any
22
+
23
+
24
+ SERVER_KEY = "cade"
25
+ DEFAULT_AGENT = "default"
26
+
27
+
28
+ class HostKind(str, Enum):
29
+ """How a host stores MCP server entries."""
30
+
31
+ MCP_SERVERS = "mcpServers" # Claude Desktop / Cursor / Claude Code
32
+ OPENCODE = "opencode" # OpenCode ``mcp`` map with type/command
33
+ WINDSURF = "windsurf" # Windsurf mcp_config.json
34
+
35
+
36
+ @dataclass(frozen=True)
37
+ class HostTarget:
38
+ """One MCP host config file we may update."""
39
+
40
+ name: str
41
+ path: Path
42
+ kind: HostKind
43
+ # Parent path that must exist (app installed / used before).
44
+ marker: Path
45
+
46
+
47
+ @dataclass(frozen=True)
48
+ class HostUpdate:
49
+ """Result of attempting to register Cade with one host."""
50
+
51
+ name: str
52
+ path: Path
53
+ status: str # added | updated | unchanged | skipped | error
54
+ detail: str = ""
55
+
56
+
57
+ def resolve_cade_command() -> str:
58
+ """Absolute path to the ``cade`` binary when possible."""
59
+ if getattr(sys, "frozen", False):
60
+ return str(Path(sys.executable).resolve())
61
+ which = shutil.which("cade")
62
+ if which:
63
+ return str(Path(which).resolve())
64
+ # Dev / module invocation fallback — hosts need a real executable.
65
+ return sys.executable
66
+
67
+
68
+ def stdio_entry(*, command: str | None = None, agent: str = DEFAULT_AGENT) -> dict[str, Any]:
69
+ """Claude/Cursor/Claude Code mcpServers entry."""
70
+ cmd = command or resolve_cade_command()
71
+ return {
72
+ "command": cmd,
73
+ "args": ["__mcp-adapter", "--agent", agent],
74
+ }
75
+
76
+
77
+ def opencode_entry(*, command: str | None = None, agent: str = DEFAULT_AGENT) -> dict[str, Any]:
78
+ """OpenCode ``mcp.<name>`` local server entry."""
79
+ cmd = command or resolve_cade_command()
80
+ return {
81
+ "type": "local",
82
+ "command": [cmd, "__mcp-adapter", "--agent", agent],
83
+ "enabled": True,
84
+ }
85
+
86
+
87
+ def discover_hosts(home: Path | None = None) -> list[HostTarget]:
88
+ """Return host configs that look installed (marker path exists)."""
89
+ home = home or Path.home()
90
+ system = platform.system()
91
+ targets: list[HostTarget] = []
92
+
93
+ # Cursor (all platforms)
94
+ cursor_dir = home / ".cursor"
95
+ targets.append(
96
+ HostTarget(
97
+ name="Cursor",
98
+ path=cursor_dir / "mcp.json",
99
+ kind=HostKind.MCP_SERVERS,
100
+ marker=cursor_dir,
101
+ )
102
+ )
103
+
104
+ # Claude Code
105
+ claude_json = home / ".claude.json"
106
+ claude_dir = home / ".claude"
107
+ targets.append(
108
+ HostTarget(
109
+ name="Claude Code",
110
+ path=claude_json,
111
+ kind=HostKind.MCP_SERVERS,
112
+ marker=claude_json if claude_json.exists() else claude_dir,
113
+ )
114
+ )
115
+
116
+ # Claude Desktop
117
+ if system == "Darwin":
118
+ desktop_dir = home / "Library" / "Application Support" / "Claude"
119
+ elif system == "Windows":
120
+ appdata = os.environ.get("APPDATA", str(home / "AppData" / "Roaming"))
121
+ desktop_dir = Path(appdata) / "Claude"
122
+ else:
123
+ desktop_dir = home / ".config" / "Claude"
124
+ targets.append(
125
+ HostTarget(
126
+ name="Claude Desktop",
127
+ path=desktop_dir / "claude_desktop_config.json",
128
+ kind=HostKind.MCP_SERVERS,
129
+ marker=desktop_dir,
130
+ )
131
+ )
132
+
133
+ # OpenCode — prefer XDG config; fall back to ~/.opencode
134
+ opencode_xdg = home / ".config" / "opencode"
135
+ opencode_legacy = home / ".opencode"
136
+ if opencode_xdg.exists():
137
+ # Prefer .json over .jsonc (we write strict JSON).
138
+ oc_path = opencode_xdg / "opencode.json"
139
+ if not oc_path.exists() and (opencode_xdg / "opencode.jsonc").exists():
140
+ oc_path = opencode_xdg / "opencode.jsonc"
141
+ targets.append(
142
+ HostTarget(
143
+ name="OpenCode",
144
+ path=oc_path,
145
+ kind=HostKind.OPENCODE,
146
+ marker=opencode_xdg,
147
+ )
148
+ )
149
+ elif opencode_legacy.exists():
150
+ oc_path = opencode_legacy / "opencode.json"
151
+ targets.append(
152
+ HostTarget(
153
+ name="OpenCode",
154
+ path=oc_path,
155
+ kind=HostKind.OPENCODE,
156
+ marker=opencode_legacy,
157
+ )
158
+ )
159
+
160
+ # Windsurf
161
+ windsurf = home / ".codeium" / "windsurf" / "mcp_config.json"
162
+ targets.append(
163
+ HostTarget(
164
+ name="Windsurf",
165
+ path=windsurf,
166
+ kind=HostKind.WINDSURF,
167
+ marker=home / ".codeium" / "windsurf",
168
+ )
169
+ )
170
+
171
+ return [t for t in targets if t.marker.exists()]
172
+
173
+
174
+ def _strip_jsonc(text: str) -> str:
175
+ """Best-effort strip of // and /* */ comments for JSONC files."""
176
+ # Remove /* ... */ blocks
177
+ text = re.sub(r"/\*.*?\*/", "", text, flags=re.DOTALL)
178
+ # Remove // line comments (not inside strings — good enough for config)
179
+ out_lines: list[str] = []
180
+ for line in text.splitlines():
181
+ in_str = False
182
+ escaped = False
183
+ cut = len(line)
184
+ for i, ch in enumerate(line):
185
+ if escaped:
186
+ escaped = False
187
+ continue
188
+ if ch == "\\":
189
+ escaped = True
190
+ continue
191
+ if ch == '"':
192
+ in_str = not in_str
193
+ continue
194
+ if not in_str and ch == "/" and i + 1 < len(line) and line[i + 1] == "/":
195
+ cut = i
196
+ break
197
+ out_lines.append(line[:cut])
198
+ return "\n".join(out_lines)
199
+
200
+
201
+ def _load_config(path: Path) -> dict[str, Any]:
202
+ if not path.exists():
203
+ return {}
204
+ raw = path.read_text(encoding="utf-8")
205
+ if path.suffix == ".jsonc":
206
+ raw = _strip_jsonc(raw)
207
+ data = json.loads(raw) if raw.strip() else {}
208
+ if not isinstance(data, dict):
209
+ raise ValueError(f"{path} root must be a JSON object")
210
+ return data
211
+
212
+
213
+ def _write_config(path: Path, data: dict[str, Any], *, dry_run: bool) -> None:
214
+ if dry_run:
215
+ return
216
+ path.parent.mkdir(parents=True, exist_ok=True)
217
+ if path.exists():
218
+ backup = path.with_suffix(path.suffix + ".bak")
219
+ shutil.copy2(path, backup)
220
+ # Always write .json when source was .jsonc so we don't re-emit comments.
221
+ out = path if path.suffix != ".jsonc" else path.with_suffix(".json")
222
+ out.write_text(json.dumps(data, indent=2) + "\n", encoding="utf-8")
223
+
224
+
225
+ def _merge_mcp_servers(
226
+ data: dict[str, Any],
227
+ entry: dict[str, Any],
228
+ *,
229
+ force: bool,
230
+ ) -> tuple[dict[str, Any], str]:
231
+ servers = data.get("mcpServers")
232
+ if servers is None:
233
+ servers = {}
234
+ data["mcpServers"] = servers
235
+ if not isinstance(servers, dict):
236
+ raise ValueError("mcpServers must be an object")
237
+
238
+ existing = servers.get(SERVER_KEY)
239
+ if existing == entry:
240
+ return data, "unchanged"
241
+ if existing is not None and not force:
242
+ # Update in place when only the command path drifted (common after upgrade).
243
+ if isinstance(existing, dict) and existing.get("args") == entry.get("args"):
244
+ servers[SERVER_KEY] = entry
245
+ return data, "updated"
246
+ if isinstance(existing, dict):
247
+ servers[SERVER_KEY] = entry
248
+ return data, "updated"
249
+ servers[SERVER_KEY] = entry
250
+ return data, "added" if existing is None else "updated"
251
+
252
+
253
+ def _merge_opencode(
254
+ data: dict[str, Any],
255
+ entry: dict[str, Any],
256
+ *,
257
+ force: bool,
258
+ ) -> tuple[dict[str, Any], str]:
259
+ mcp = data.get("mcp")
260
+ if mcp is None:
261
+ mcp = {}
262
+ data["mcp"] = mcp
263
+ if not isinstance(mcp, dict):
264
+ raise ValueError("mcp must be an object")
265
+ existing = mcp.get(SERVER_KEY)
266
+ if existing == entry:
267
+ return data, "unchanged"
268
+ if existing is not None and not force:
269
+ mcp[SERVER_KEY] = entry
270
+ return data, "updated"
271
+ mcp[SERVER_KEY] = entry
272
+ return data, "added" if existing is None else "updated"
273
+
274
+
275
+ def _merge_windsurf(
276
+ data: dict[str, Any],
277
+ entry: dict[str, Any],
278
+ *,
279
+ force: bool,
280
+ ) -> tuple[dict[str, Any], str]:
281
+ # Windsurf uses the same mcpServers shape as Cursor in current builds.
282
+ return _merge_mcp_servers(data, entry, force=force)
283
+
284
+
285
+ def register_host(
286
+ target: HostTarget,
287
+ *,
288
+ command: str | None = None,
289
+ agent: str = DEFAULT_AGENT,
290
+ force: bool = False,
291
+ dry_run: bool = False,
292
+ ) -> HostUpdate:
293
+ """Merge the Cade MCP entry into one host config."""
294
+ cmd = command or resolve_cade_command()
295
+ try:
296
+ data = _load_config(target.path)
297
+ if target.kind == HostKind.OPENCODE:
298
+ entry = opencode_entry(command=cmd, agent=agent)
299
+ data, status = _merge_opencode(data, entry, force=force)
300
+ elif target.kind in (HostKind.MCP_SERVERS, HostKind.WINDSURF):
301
+ entry = stdio_entry(command=cmd, agent=agent)
302
+ merge = _merge_windsurf if target.kind == HostKind.WINDSURF else _merge_mcp_servers
303
+ data, status = merge(data, entry, force=force)
304
+ else:
305
+ return HostUpdate(target.name, target.path, "skipped", "unknown host kind")
306
+
307
+ if status != "unchanged":
308
+ _write_config(target.path, data, dry_run=dry_run)
309
+ if dry_run:
310
+ status = f"would-{status}"
311
+ return HostUpdate(target.name, target.path, status)
312
+ except Exception as e: # noqa: BLE001
313
+ return HostUpdate(target.name, target.path, "error", str(e))
314
+
315
+
316
+ def install_into_hosts(
317
+ *,
318
+ home: Path | None = None,
319
+ command: str | None = None,
320
+ agent: str = DEFAULT_AGENT,
321
+ force: bool = False,
322
+ dry_run: bool = False,
323
+ ) -> list[HostUpdate]:
324
+ """Discover installed hosts and register Cade with each."""
325
+ updates: list[HostUpdate] = []
326
+ for target in discover_hosts(home):
327
+ updates.append(
328
+ register_host(
329
+ target,
330
+ command=command,
331
+ agent=agent,
332
+ force=force,
333
+ dry_run=dry_run,
334
+ )
335
+ )
336
+ return updates
337
+
338
+
339
+ __all__ = [
340
+ "HostKind",
341
+ "HostTarget",
342
+ "HostUpdate",
343
+ "DEFAULT_AGENT",
344
+ "SERVER_KEY",
345
+ "discover_hosts",
346
+ "install_into_hosts",
347
+ "opencode_entry",
348
+ "register_host",
349
+ "resolve_cade_command",
350
+ "stdio_entry",
351
+ ]
@@ -312,6 +312,22 @@ def finish_first_run_cloud(console: Console, *, prefer_skip_login: bool = False)
312
312
  "[bold]cade mcp authorize hub[/bold].[/dim]"
313
313
  )
314
314
 
315
+ # Register Cade in Claude Desktop / Cursor / Claude Code / … when present.
316
+ try:
317
+ from cadecoder.cli.mcp_hosts import install_into_hosts
318
+
319
+ updates = install_into_hosts()
320
+ touched = [u for u in updates if u.status in ("added", "updated")]
321
+ if touched:
322
+ names = ", ".join(u.name for u in touched)
323
+ console.print(
324
+ f"\n[green]✓[/green] Registered Cade as an MCP server in: {names}\n"
325
+ "[dim]Restart those apps, and keep [bold]cade daemon[/bold] running "
326
+ "(or just use [bold]cade[/bold] — it autostarts).[/dim]"
327
+ )
328
+ except Exception: # noqa: BLE001
329
+ pass
330
+
315
331
 
316
332
  def run_onboarding(console: Console, *, force: bool = False) -> OnboardingResult:
317
333
  """Run the interactive model-setup wizard (step 1 of first-run).
File without changes
File without changes