cade-cli 0.20.2__tar.gz → 0.20.4__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 (223) hide show
  1. {cade_cli-0.20.2 → cade_cli-0.20.4}/PKG-INFO +2 -2
  2. {cade_cli-0.20.2 → cade_cli-0.20.4}/pyproject.toml +1 -1
  3. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/agent.py +2 -0
  4. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/config.py +9 -0
  5. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/runtime.py +1 -0
  6. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/gateway/app.py +5 -2
  7. cade_cli-0.20.4/src/cadecoder/daemon/gateway/principal.py +40 -0
  8. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/gateway/resources.py +6 -3
  9. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/install.py +17 -0
  10. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/runner.py +11 -0
  11. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/supervisor.py +37 -2
  12. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/execution/context_window.py +12 -3
  13. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/execution/orchestrator.py +17 -1
  14. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/providers/anthropic.py +1 -1
  15. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/providers/base.py +3 -1
  16. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/providers/openai.py +4 -1
  17. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/telemetry/otel.py +17 -1
  18. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/templates/serve/launchd.plist.tmpl +2 -0
  19. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/templates/serve/systemd.service.tmpl +1 -0
  20. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/ui/session.py +6 -0
  21. {cade_cli-0.20.2 → cade_cli-0.20.4}/.gitignore +0 -0
  22. {cade_cli-0.20.2 → cade_cli-0.20.4}/LICENSE +0 -0
  23. {cade_cli-0.20.2 → cade_cli-0.20.4}/README.md +0 -0
  24. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/__init__.py +0 -0
  25. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/__main__.py +0 -0
  26. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/_metadata.py +0 -0
  27. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/config.py +0 -0
  28. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/errors.py +0 -0
  29. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/grants.py +0 -0
  30. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/resources.py +0 -0
  31. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/sandbox.py +0 -0
  32. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/server.py +0 -0
  33. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/__init__.py +0 -0
  34. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/_read_cache.py +0 -0
  35. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/access.py +0 -0
  36. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/agents.py +0 -0
  37. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/filesystem.py +0 -0
  38. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/git.py +0 -0
  39. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/notifications.py +0 -0
  40. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/questions.py +0 -0
  41. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/results.py +0 -0
  42. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/schemas.py +0 -0
  43. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/search.py +0 -0
  44. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/shell.py +0 -0
  45. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/tasks.py +0 -0
  46. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/web_fetch.py +0 -0
  47. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/tools/web_search.py +0 -0
  48. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/utils.py +0 -0
  49. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/web/__init__.py +0 -0
  50. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/web/arcade_client.py +0 -0
  51. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/web/cache.py +0 -0
  52. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/web/extract.py +0 -0
  53. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/web/markdown.py +0 -0
  54. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/web/preapproved.py +0 -0
  55. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/web/prompts.py +0 -0
  56. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/web/scrape.py +0 -0
  57. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/web/search/__init__.py +0 -0
  58. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/web/search/arcade.py +0 -0
  59. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/web/search/base.py +0 -0
  60. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cade_mcp_local/web/search/http.py +0 -0
  61. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/__init__.py +0 -0
  62. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/ai/__init__.py +0 -0
  63. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/ai/prompts.py +0 -0
  64. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/__init__.py +0 -0
  65. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/app.py +0 -0
  66. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/auth.py +0 -0
  67. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/__init__.py +0 -0
  68. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/account.py +0 -0
  69. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/agent_group.py +0 -0
  70. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/agents.py +0 -0
  71. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/auth.py +0 -0
  72. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/chat.py +0 -0
  73. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/cron.py +0 -0
  74. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/daemon.py +0 -0
  75. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/grant.py +0 -0
  76. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/hooks.py +0 -0
  77. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/mcp.py +0 -0
  78. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/mem.py +0 -0
  79. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/tasks.py +0 -0
  80. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/thread.py +0 -0
  81. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/commands/tools.py +0 -0
  82. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/mcp_hosts.py +0 -0
  83. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/onboarding.py +0 -0
  84. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/cli/ui.py +0 -0
  85. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/__init__.py +0 -0
  86. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/binary.py +0 -0
  87. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/comms.py +0 -0
  88. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/constants.py +0 -0
  89. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/errors.py +0 -0
  90. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/frozen.py +0 -0
  91. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/git.py +0 -0
  92. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/inbox.py +0 -0
  93. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/logging.py +0 -0
  94. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/memory.py +0 -0
  95. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/model_specs.py +0 -0
  96. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/names.py +0 -0
  97. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/paths.py +0 -0
  98. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/secrets.py +0 -0
  99. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/spawn.py +0 -0
  100. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/text.py +0 -0
  101. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/core/types.py +0 -0
  102. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/__init__.py +0 -0
  103. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/adapters/__init__.py +0 -0
  104. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/adapters/base.py +0 -0
  105. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/adapters/factory.py +0 -0
  106. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/adapters/imessage.py +0 -0
  107. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/adapters/registry.py +0 -0
  108. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/adapters/stub.py +0 -0
  109. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/adapters/telegram.py +0 -0
  110. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/allowlist.py +0 -0
  111. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/attach.py +0 -0
  112. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/chunker.py +0 -0
  113. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/client.py +0 -0
  114. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/commands.py +0 -0
  115. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/config.py +0 -0
  116. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/control.py +0 -0
  117. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/cron.py +0 -0
  118. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/elicitation.py +0 -0
  119. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/ensure.py +0 -0
  120. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/format.py +0 -0
  121. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/gateway/__init__.py +0 -0
  122. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/gateway/auth.py +0 -0
  123. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/gateway/constants.py +0 -0
  124. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/gateway/elicitation.py +0 -0
  125. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/gateway/exposure.py +0 -0
  126. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/gateway/host_agent.py +0 -0
  127. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/gateway/limits.py +0 -0
  128. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/gateway/middleware.py +0 -0
  129. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/gateway/subscriptions.py +0 -0
  130. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/gateway/turn_bridge.py +0 -0
  131. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/grants.py +0 -0
  132. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/inbox.py +0 -0
  133. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/inbox_cron.py +0 -0
  134. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/lock.py +0 -0
  135. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/mesh.py +0 -0
  136. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/message_pump.py +0 -0
  137. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/observability.py +0 -0
  138. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/owner.py +0 -0
  139. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/progress_sink.py +0 -0
  140. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/registry.py +0 -0
  141. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/router.py +0 -0
  142. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/runner_main.py +0 -0
  143. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/secrets.py +0 -0
  144. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/secrets_broker.py +0 -0
  145. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/server.py +0 -0
  146. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/services.py +0 -0
  147. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/sinks.py +0 -0
  148. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/tokens.py +0 -0
  149. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/traffic.py +0 -0
  150. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/turns.py +0 -0
  151. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/daemon/wake.py +0 -0
  152. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/execution/__init__.py +0 -0
  153. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/execution/mcp_schema_index.py +0 -0
  154. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/execution/parallel.py +0 -0
  155. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/execution/tool_result_store.py +0 -0
  156. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/execution/tool_schema_cache.py +0 -0
  157. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/hooks/__init__.py +0 -0
  158. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/hooks/config.py +0 -0
  159. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/hooks/engine.py +0 -0
  160. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/hooks/executors/__init__.py +0 -0
  161. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/hooks/executors/callback.py +0 -0
  162. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/hooks/executors/command.py +0 -0
  163. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/hooks/executors/http.py +0 -0
  164. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/hooks/executors/prompt.py +0 -0
  165. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/hooks/executors/ssrf_guard.py +0 -0
  166. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/hooks/matchers.py +0 -0
  167. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/hooks/registry.py +0 -0
  168. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/hooks/types.py +0 -0
  169. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/__init__.py +0 -0
  170. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/.claude-plugin/marketplace.json +0 -0
  171. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/.claude-plugin/plugin.json +0 -0
  172. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/.cursor-plugin/marketplace.json +0 -0
  173. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/.cursor-plugin/plugin.json +0 -0
  174. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/agents/operator.md +0 -0
  175. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/commands/ask.md +0 -0
  176. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/commands/memory.md +0 -0
  177. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/commands/tasks.md +0 -0
  178. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/mcp.json +0 -0
  179. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/rules/gateway.mdc +0 -0
  180. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/skills/ask/SKILL.md +0 -0
  181. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/skills/memory/SKILL.md +0 -0
  182. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/assets/skills/tasks/SKILL.md +0 -0
  183. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/doctor.py +0 -0
  184. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/install.py +0 -0
  185. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/paths.py +0 -0
  186. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/host_plugin/state.py +0 -0
  187. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/providers/__init__.py +0 -0
  188. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/providers/http_client.py +0 -0
  189. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/providers/ollama.py +0 -0
  190. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/storage/__init__.py +0 -0
  191. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/storage/threads.py +0 -0
  192. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tasks/__init__.py +0 -0
  193. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tasks/scheduler.py +0 -0
  194. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tasks/store.py +0 -0
  195. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tasks/types.py +0 -0
  196. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/telemetry/__init__.py +0 -0
  197. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/templates/login_failed.html +0 -0
  198. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/templates/login_success.html +0 -0
  199. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/templates/serve/serve.toml.example +0 -0
  200. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/templates/styles.css +0 -0
  201. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tools/__init__.py +0 -0
  202. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tools/manager/__init__.py +0 -0
  203. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tools/manager/_request_ctx.py +0 -0
  204. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tools/manager/base.py +0 -0
  205. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tools/manager/composite.py +0 -0
  206. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tools/manager/config.py +0 -0
  207. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tools/manager/mcp.py +0 -0
  208. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tools/search/__init__.py +0 -0
  209. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tools/search/discovered.py +0 -0
  210. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tools/search/scoring.py +0 -0
  211. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/tools/search/service.py +0 -0
  212. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/ui/__init__.py +0 -0
  213. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/ui/completion.py +0 -0
  214. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/ui/display.py +0 -0
  215. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/ui/elicitation.py +0 -0
  216. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/ui/input.py +0 -0
  217. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/ui/slash.py +0 -0
  218. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/voice/__init__.py +0 -0
  219. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/voice/audio.py +0 -0
  220. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/voice/cleanup.py +0 -0
  221. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/voice/session.py +0 -0
  222. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/voice/stt.py +0 -0
  223. {cade_cli-0.20.2 → cade_cli-0.20.4}/src/cadecoder/voice/tts.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.4
1
+ Metadata-Version: 2.5
2
2
  Name: cade-cli
3
- Version: 0.20.2
3
+ Version: 0.20.4
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
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "cade-cli"
3
- version = "0.20.2"
3
+ version = "0.20.4"
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"
@@ -120,6 +120,8 @@ class AgentConfig(BaseModel):
120
120
  model: str = constants.DEFAULT_AI_MODEL
121
121
  provider: str | None = None
122
122
  temperature: float | None = None
123
+ # Overrides the model registry's context window (tokens) for this agent.
124
+ context_window: int | None = None
123
125
 
124
126
  # Personality
125
127
  system_prompt: str | None = None
@@ -54,6 +54,9 @@ class GlobalConfig(BaseModel):
54
54
  provider: str = "anthropic"
55
55
  model: str = constants.DEFAULT_AI_MODEL
56
56
  temperature: float | None = None
57
+ # Overrides the model registry's context window (tokens). Per-agent
58
+ # ``context_window`` in ``config/agents/<name>.toml`` takes precedence.
59
+ context_window: int | None = None
57
60
  debug_mode: bool = False
58
61
  voice: VoiceConfig = Field(default_factory=VoiceConfig)
59
62
  ui: UIConfig = Field(default_factory=UIConfig)
@@ -192,6 +195,11 @@ def build_runtime():
192
195
  if active_agent.temperature is not None
193
196
  else global_config.temperature
194
197
  )
198
+ context_window = (
199
+ active_agent.context_window
200
+ if active_agent.context_window is not None
201
+ else global_config.context_window
202
+ )
195
203
  runtime = RuntimeEnvironment(
196
204
  paths=paths,
197
205
  context_name=active_agent.id,
@@ -201,6 +209,7 @@ def build_runtime():
201
209
  model=model,
202
210
  provider=provider,
203
211
  temperature=temperature,
212
+ context_window=context_window,
204
213
  agent=active_agent,
205
214
  )
206
215
  runtime.ensure_dirs()
@@ -23,6 +23,7 @@ class RuntimeEnvironment:
23
23
  model: str
24
24
  provider: str
25
25
  temperature: float | None = None
26
+ context_window: int | None = None
26
27
  agent: object | None = None
27
28
 
28
29
  @property
@@ -24,6 +24,7 @@ from cadecoder.daemon.gateway.exposure import LOCAL_GROUPS, ExposurePolicy
24
24
  from cadecoder.daemon.gateway.host_agent import get_host_agent
25
25
  from cadecoder.daemon.gateway.limits import PrincipalLimits
26
26
  from cadecoder.daemon.gateway.middleware import ExposureMiddleware, HostAgentMiddleware
27
+ from cadecoder.daemon.gateway.principal import local_principal
27
28
  from cadecoder.daemon.gateway.resources import register_gateway_resources
28
29
  from cadecoder.daemon.gateway.turn_bridge import TurnBridge, TurnBridgeError
29
30
  from cadecoder.daemon.supervisor import Supervisor
@@ -56,9 +57,11 @@ def _principal_and_policy(context: Context) -> tuple[str, list[str], list[str]]:
56
57
  """
57
58
  owner = getattr(context, "_resource_owner", None)
58
59
  if owner is None:
59
- return "local", [], list(LOCAL_GROUPS)
60
+ return local_principal(context), [], list(LOCAL_GROUPS)
60
61
  claims = getattr(owner, "claims", {}) or {}
61
- principal = str(claims.get("cade_principal") or getattr(context, "user_id", "") or "local")
62
+ principal = str(
63
+ claims.get("cade_principal") or getattr(context, "user_id", "") or local_principal(context)
64
+ )
62
65
  agents = claims.get("cade_agents")
63
66
  expose = claims.get("cade_expose")
64
67
  return (
@@ -0,0 +1,40 @@
1
+ """Shared principal fallback for unauthenticated (loopback/local) MCP callers.
2
+
3
+ Used by both the ``Cade_Ask`` tool (``app.py``) and the ``threads://``
4
+ resource listing (``resources.py``) so a thread written under one is found
5
+ under the other.
6
+ """
7
+
8
+ from __future__ import annotations
9
+
10
+ import re
11
+
12
+ from arcade_mcp_server import Context
13
+
14
+
15
+ def client_app_name(context: Context | None) -> str | None:
16
+ """Best-effort slug of the connecting MCP client (e.g. ``claude``, ``cursor``).
17
+
18
+ Read from the ``clientInfo.name`` negotiated during MCP ``initialize``.
19
+ Returns ``None`` when unavailable, so the caller can fall back to a flat
20
+ ``"local"`` principal.
21
+ """
22
+ session = getattr(context, "_session", None)
23
+ params = getattr(session, "client_params", None)
24
+ client_info = getattr(params, "clientInfo", None)
25
+ name = getattr(client_info, "name", None)
26
+ if not name:
27
+ return None
28
+ slug = re.sub(r"[^a-z0-9]+", "-", name.strip().lower()).strip("-")
29
+ return slug or None
30
+
31
+
32
+ def local_principal(context: Context | None) -> str:
33
+ """Principal for an unauthenticated (loopback/local) caller.
34
+
35
+ Scoped per connecting app when its ``clientInfo.name`` is known, so e.g.
36
+ Claude Desktop and Cursor each keep their own default thread rather than
37
+ sharing one ``local:default`` conversation across every local MCP client.
38
+ """
39
+ app_name = client_app_name(context)
40
+ return f"local:{app_name}" if app_name else "local"
@@ -30,6 +30,7 @@ from cadecoder.daemon.gateway.constants import (
30
30
  THREADS_URI,
31
31
  )
32
32
  from cadecoder.daemon.gateway.host_agent import active_agent_name, get_host_agent
33
+ from cadecoder.daemon.gateway.principal import local_principal
33
34
  from cadecoder.storage.threads import BaseThreadHistory, get_thread_history
34
35
 
35
36
  if TYPE_CHECKING:
@@ -37,13 +38,15 @@ if TYPE_CHECKING:
37
38
 
38
39
 
39
40
  def _current_principal() -> str:
40
- """Principal name from the active model context; 'local' when unauthenticated."""
41
+ """Principal name from the active model context; scoped per local app when unauthenticated."""
41
42
  context = get_current_model_context()
42
43
  owner = getattr(context, "_resource_owner", None) if context else None
43
44
  if owner is None:
44
- return "local"
45
+ return local_principal(context)
45
46
  claims = getattr(owner, "claims", {}) or {}
46
- return str(claims.get("cade_principal") or getattr(owner, "user_id", "") or "local")
47
+ return str(
48
+ claims.get("cade_principal") or getattr(owner, "user_id", "") or local_principal(context)
49
+ )
47
50
 
48
51
 
49
52
  def _active_agent_name() -> str:
@@ -199,6 +199,22 @@ def _log_path() -> str:
199
199
 
200
200
 
201
201
  def _common_vars() -> dict[str, str]:
202
+ """Template substitutions for launchd/systemd unit files.
203
+
204
+ ``CADE_OTEL`` is ``1`` when the env is already set or
205
+ ``~/.cade/config/otel.enable`` exists, so a service reinstall picks up
206
+ tracing without hand-editing the unit.
207
+ """
208
+ otel_on = (
209
+ os.environ.get("CADE_OTEL", "").strip().lower()
210
+ in (
211
+ "1",
212
+ "true",
213
+ "yes",
214
+ "on",
215
+ )
216
+ or (get_runtime().paths.config_dir / "otel.enable").is_file()
217
+ )
202
218
  return {
203
219
  "LABEL": _LABEL,
204
220
  "CADE_BIN": _cade_binary(),
@@ -207,6 +223,7 @@ def _common_vars() -> dict[str, str]:
207
223
  "HOME": str(Path.home()),
208
224
  "PATH": os.environ.get("PATH", "/usr/local/bin:/usr/bin:/bin"),
209
225
  "LOG_PATH": _log_path(),
226
+ "CADE_OTEL": "1" if otel_on else "0",
210
227
  }
211
228
 
212
229
 
@@ -74,6 +74,7 @@ class InProcessRunner:
74
74
  defer_user_mcp_schemas: str = "auto",
75
75
  ) -> None:
76
76
  self.agent_name = agent_name
77
+ self.model = model
77
78
  self._orchestrator = orchestrator or create_orchestrator(
78
79
  default_model=model,
79
80
  persona=persona or agent_name,
@@ -84,6 +85,7 @@ class InProcessRunner:
84
85
  # threads proceed concurrently (subject to TurnRunner's global gate).
85
86
  self._thread_locks: dict[str, asyncio.Lock] = {}
86
87
  self.last_active_at = time.monotonic()
88
+ log.info(f"InProcessRunner ready agent={agent_name!r} model={model}")
87
89
 
88
90
  def _lock_for(self, thread_id: str) -> asyncio.Lock:
89
91
  lock = self._thread_locks.get(thread_id)
@@ -146,6 +148,15 @@ class SubprocessRunner:
146
148
  writer: asyncio.StreamWriter | None = None,
147
149
  ) -> None:
148
150
  self.agent_name = agent_name
151
+ # Mirror the agent's configured model so the supervisor can detect
152
+ # stale subprocess runners after ``cade account init``.
153
+ try:
154
+ from cadecoder.core import agent as agent_mod
155
+
156
+ agent = agent_mod.resolve(agent_name)
157
+ self.model = agent.model if agent is not None else ""
158
+ except Exception: # noqa: BLE001
159
+ self.model = ""
149
160
  self.last_active_at = time.monotonic()
150
161
  self._reader = reader
151
162
  self._writer = writer
@@ -81,9 +81,13 @@ class Supervisor:
81
81
 
82
82
  Concurrent callers for the same agent share one start via a per-agent
83
83
  lock, so a burst of gateway calls never spawns duplicate runners.
84
+
85
+ If the agent's configured model changed since the runner was created
86
+ (e.g. after ``cade account init``), the stale runner is replaced so
87
+ chat does not keep calling the previous provider until idle eviction.
84
88
  """
85
89
  existing = self._runners.get(agent_name)
86
- if existing is not None:
90
+ if existing is not None and not self._runner_is_stale(agent_name, existing):
87
91
  return existing
88
92
 
89
93
  async with self._lock:
@@ -94,14 +98,45 @@ class Supervisor:
94
98
 
95
99
  async with start_lock:
96
100
  existing = self._runners.get(agent_name)
97
- if existing is not None:
101
+ if existing is not None and not self._runner_is_stale(agent_name, existing):
98
102
  return existing
103
+ if existing is not None:
104
+ log.info(
105
+ f"recycling runner for agent {agent_name!r} (config model changed since start)"
106
+ )
107
+ self._runners.pop(agent_name, None)
108
+ try:
109
+ await existing.aclose()
110
+ except Exception as exc: # noqa: BLE001
111
+ log.debug(f"stale runner close failed for {agent_name!r}: {exc}")
99
112
  created = self._factory(agent_name)
100
113
  runner: RunnerHandle = await created if asyncio.iscoroutine(created) else created
101
114
  self._runners[agent_name] = runner
102
115
  log.info(f"started runner for agent {agent_name!r}")
103
116
  return runner
104
117
 
118
+ def _runner_is_stale(self, agent_name: str, runner: RunnerHandle) -> bool:
119
+ """True when the cached runner's model no longer matches agent config."""
120
+ try:
121
+ agent = agent_mod.resolve(agent_name)
122
+ except Exception: # noqa: BLE001
123
+ return False
124
+ if agent is None:
125
+ return False
126
+ runner_model = getattr(runner, "model", None)
127
+ if runner_model is None:
128
+ orch = getattr(runner, "_orchestrator", None)
129
+ runner_model = getattr(orch, "default_model", None)
130
+ if not runner_model:
131
+ return False
132
+ if runner_model == agent.model:
133
+ return False
134
+ log.warning(
135
+ f"agent {agent_name!r} model is {agent.model!r} but runner still has "
136
+ f"{runner_model!r} — will recreate"
137
+ )
138
+ return True
139
+
105
140
  def running_agents(self) -> list[str]:
106
141
  return sorted(self._runners)
107
142
 
@@ -191,6 +191,7 @@ class ContextWindowManager:
191
191
  model: str = DEFAULT_AI_MODEL,
192
192
  backup_dir: Path | None = None,
193
193
  chars_per_token: float = 4.0,
194
+ context_window_override: int | None = None,
194
195
  ) -> None:
195
196
  """Initialize context window manager.
196
197
 
@@ -198,12 +199,15 @@ class ContextWindowManager:
198
199
  model: Model name for context limit lookup
199
200
  backup_dir: Directory for storing context backups
200
201
  chars_per_token: Character to token ratio for estimation
202
+ context_window_override: User-configured context window (tokens)
203
+ that takes precedence over the model registry's value
201
204
  """
202
205
  self.model = model
203
206
  self.chars_per_token = chars_per_token
204
207
 
205
- # Context window and response reserve come from the central model registry.
206
- self.context_limit = model_specs.context_window(model)
208
+ # Context window and response reserve come from the central model
209
+ # registry, unless the user has overridden the window size in config.
210
+ self.context_limit = context_window_override or model_specs.context_window(model)
207
211
  self.response_reserve = model_specs.max_output_tokens(model)
208
212
  self.effective_limit = self.context_limit - self.response_reserve
209
213
 
@@ -888,17 +892,22 @@ class ContextWindowManager:
888
892
  def create_context_manager(
889
893
  model: str = DEFAULT_AI_MODEL,
890
894
  backup_dir: Path | None = None,
895
+ context_window_override: int | None = None,
891
896
  ) -> ContextWindowManager:
892
897
  """Factory function to create a context window manager.
893
898
 
894
899
  Args:
895
900
  model: Model name for context limit lookup
896
901
  backup_dir: Directory for storing context backups
902
+ context_window_override: User-configured context window (tokens)
903
+ that takes precedence over the model registry's value
897
904
 
898
905
  Returns:
899
906
  Configured ContextWindowManager instance
900
907
  """
901
- return ContextWindowManager(model=model, backup_dir=backup_dir)
908
+ return ContextWindowManager(
909
+ model=model, backup_dir=backup_dir, context_window_override=context_window_override
910
+ )
902
911
 
903
912
 
904
913
  __all__ = [
@@ -204,7 +204,9 @@ class Orchestrator:
204
204
  # Context window backups are scoped to the active context.
205
205
  backup_dir = runtime.context_backups_dir
206
206
  self.context_manager = context_manager or create_context_manager(
207
- model=self.default_model, backup_dir=backup_dir
207
+ model=self.default_model,
208
+ backup_dir=backup_dir,
209
+ context_window_override=runtime.context_window,
208
210
  )
209
211
 
210
212
  # Tool result store — uses CADE_TOOL_RESULT_DIR env var (set by create_orchestrator)
@@ -295,6 +297,20 @@ class Orchestrator:
295
297
  while should_continue and iteration < MAX_EXECUTION_ITERATIONS:
296
298
  iteration += 1
297
299
  log.info(f"Execution iteration {iteration}")
300
+ provider_label = ""
301
+ try:
302
+ provider_label = str(
303
+ getattr(getattr(self.provider, "provider_type", None), "value", "")
304
+ or getattr(self.provider, "provider_type", "")
305
+ or ""
306
+ )
307
+ except Exception: # noqa: BLE001
308
+ provider_label = type(self.provider).__name__
309
+ base_url = getattr(self.provider, "base_url", None) or ""
310
+ log.info(
311
+ f"LLM call model={self.default_model} provider={provider_label or '?'} "
312
+ f"base_url={base_url or 'default'} tools={len(tools) if tools else 0}"
313
+ )
298
314
 
299
315
  # Drain task/notification queue as system messages so the LLM
300
316
  # sees pending task completions before the next provider call.
@@ -414,7 +414,7 @@ class AnthropicProvider(Provider):
414
414
  # Convert tools from OpenAI format to Anthropic format
415
415
  if request.tools:
416
416
  anthropic_request["tools"] = self._convert_tools_to_anthropic(request.tools)
417
- log.info(f"Anthropic request includes {len(request.tools)} tools")
417
+ log.info(f"Anthropic request model={request.model} tools={len(request.tools)}")
418
418
  tool_names = [t.get("function", {}).get("name", "unknown") for t in request.tools[:5]]
419
419
  log.debug(f"First few tools: {tool_names}")
420
420
 
@@ -238,7 +238,9 @@ async def stream_with_retry(
238
238
  await asyncio.sleep(delay)
239
239
 
240
240
  assert last_exc is not None
241
- log.error(f"{provider.provider_type.value} streaming failed: {last_exc}")
241
+ log.error(
242
+ f"{provider.provider_type.value} streaming failed: {type(last_exc).__name__}: {last_exc!r}"
243
+ )
242
244
  yield StreamEvent(
243
245
  type="error",
244
246
  content=provider.format_error_for_user(last_exc),
@@ -353,7 +353,10 @@ class OpenAIProvider(Provider):
353
353
 
354
354
  if request.tools:
355
355
  openai_request["tools"] = request.tools
356
- log.info(f"OpenAI request includes {len(request.tools)} tools")
356
+ log.info(
357
+ f"OpenAI request model={request.model} tools={len(request.tools)} "
358
+ f"base_url={self.base_url or 'api.openai.com'}"
359
+ )
357
360
  # Log first few tool names for debugging
358
361
  tool_names = [t.get("function", {}).get("name", "unknown") for t in request.tools[:5]]
359
362
  log.debug(f"First few tools: {tool_names}")
@@ -177,9 +177,22 @@ def _build_exporter() -> tuple[Any, str]:
177
177
  return exporter, f"otlp/http:{http_endpoint}"
178
178
 
179
179
 
180
+ def _otel_enable_file() -> bool:
181
+ """True when ``~/.cade/config/otel.enable`` exists (daemon-friendly toggle)."""
182
+ try:
183
+ from cadecoder.core.paths import get_paths
184
+
185
+ return (get_paths().config_dir / "otel.enable").is_file()
186
+ except Exception: # noqa: BLE001
187
+ return False
188
+
189
+
180
190
  def init_telemetry(*, force: bool = False) -> bool:
181
191
  """Initialize the tracer provider when ``CADE_OTEL=1``.
182
192
 
193
+ Also enabled when ``~/.cade/config/otel.enable`` exists so the launchd
194
+ daemon can emit spans without inheriting the chat process env.
195
+
183
196
  Safe to call multiple times. Returns True when tracing is live.
184
197
 
185
198
  Args:
@@ -190,9 +203,12 @@ def init_telemetry(*, force: bool = False) -> bool:
190
203
  return _enabled
191
204
  _initialized = True
192
205
 
193
- if not _truthy("CADE_OTEL"):
206
+ if not _truthy("CADE_OTEL") and not _otel_enable_file():
194
207
  _enabled = False
195
208
  return False
209
+ # Normalize so child helpers that re-check the env see the same gate.
210
+ if not _truthy("CADE_OTEL"):
211
+ os.environ["CADE_OTEL"] = "1"
196
212
 
197
213
  try:
198
214
  from opentelemetry import trace
@@ -30,6 +30,8 @@
30
30
  <string>{CADE_HOME}</string>
31
31
  <key>CADE_CONTEXT</key>
32
32
  <string>{CADE_CONTEXT}</string>
33
+ <key>CADE_OTEL</key>
34
+ <string>{CADE_OTEL}</string>
33
35
  </dict>
34
36
  </dict>
35
37
  </plist>
@@ -14,6 +14,7 @@ StandardError=append:{LOG_PATH}
14
14
  Environment=PATH={PATH}
15
15
  Environment=CADE_HOME={CADE_HOME}
16
16
  Environment=CADE_CONTEXT={CADE_CONTEXT}
17
+ Environment=CADE_OTEL={CADE_OTEL}
17
18
 
18
19
  [Install]
19
20
  WantedBy=default.target
@@ -108,6 +108,12 @@ def _try_attach_gateway(session: "ChatSession") -> bool:
108
108
  # Probe the session so cold failures fall back before the first turn.
109
109
  session._gateway._ensure_session()
110
110
  log.info("chat session attached to cade daemon gateway")
111
+ if os.environ.get("CADE_OTEL", "").strip().lower() in ("1", "true", "yes", "on"):
112
+ log.warning(
113
+ "CADE_OTEL=1 is set on this chat process, but turns run inside the "
114
+ "daemon — export CADE_OTEL=1 for the daemon and restart it "
115
+ "(`cade daemon restart`), or touch ~/.cade/config/otel.enable"
116
+ )
111
117
  return True
112
118
  except Exception as e: # noqa: BLE001
113
119
  # Warning (not debug): autostart is on by default; a silent fallback
File without changes
File without changes
File without changes