cade-cli 0.20.6__tar.gz → 0.20.7__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.6 → cade_cli-0.20.7}/PKG-INFO +1 -1
  2. {cade_cli-0.20.6 → cade_cli-0.20.7}/pyproject.toml +1 -1
  3. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/storage/threads.py +51 -0
  4. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/ui/session.py +104 -29
  5. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/ui/slash.py +1 -0
  6. {cade_cli-0.20.6 → cade_cli-0.20.7}/.gitignore +0 -0
  7. {cade_cli-0.20.6 → cade_cli-0.20.7}/LICENSE +0 -0
  8. {cade_cli-0.20.6 → cade_cli-0.20.7}/README.md +0 -0
  9. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/__init__.py +0 -0
  10. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/__main__.py +0 -0
  11. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/_metadata.py +0 -0
  12. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/config.py +0 -0
  13. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/errors.py +0 -0
  14. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/grants.py +0 -0
  15. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/resources.py +0 -0
  16. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/sandbox.py +0 -0
  17. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/server.py +0 -0
  18. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/__init__.py +0 -0
  19. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/_read_cache.py +0 -0
  20. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/access.py +0 -0
  21. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/agents.py +0 -0
  22. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/filesystem.py +0 -0
  23. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/git.py +0 -0
  24. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/notifications.py +0 -0
  25. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/questions.py +0 -0
  26. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/results.py +0 -0
  27. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/schemas.py +0 -0
  28. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/search.py +0 -0
  29. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/shell.py +0 -0
  30. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/tasks.py +0 -0
  31. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/web_fetch.py +0 -0
  32. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/tools/web_search.py +0 -0
  33. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/utils.py +0 -0
  34. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/web/__init__.py +0 -0
  35. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/web/arcade_client.py +0 -0
  36. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/web/cache.py +0 -0
  37. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/web/extract.py +0 -0
  38. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/web/markdown.py +0 -0
  39. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/web/preapproved.py +0 -0
  40. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/web/prompts.py +0 -0
  41. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/web/scrape.py +0 -0
  42. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/web/search/__init__.py +0 -0
  43. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/web/search/arcade.py +0 -0
  44. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/web/search/base.py +0 -0
  45. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cade_mcp_local/web/search/http.py +0 -0
  46. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/__init__.py +0 -0
  47. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/ai/__init__.py +0 -0
  48. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/ai/prompts.py +0 -0
  49. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/__init__.py +0 -0
  50. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/app.py +0 -0
  51. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/auth.py +0 -0
  52. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/__init__.py +0 -0
  53. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/account.py +0 -0
  54. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/agent_group.py +0 -0
  55. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/agents.py +0 -0
  56. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/auth.py +0 -0
  57. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/chat.py +0 -0
  58. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/cron.py +0 -0
  59. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/daemon.py +0 -0
  60. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/grant.py +0 -0
  61. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/hooks.py +0 -0
  62. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/mcp.py +0 -0
  63. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/mem.py +0 -0
  64. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/tasks.py +0 -0
  65. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/thread.py +0 -0
  66. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/commands/tools.py +0 -0
  67. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/mcp_hosts.py +0 -0
  68. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/onboarding.py +0 -0
  69. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/cli/ui.py +0 -0
  70. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/__init__.py +0 -0
  71. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/agent.py +0 -0
  72. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/binary.py +0 -0
  73. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/comms.py +0 -0
  74. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/config.py +0 -0
  75. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/constants.py +0 -0
  76. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/errors.py +0 -0
  77. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/frozen.py +0 -0
  78. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/git.py +0 -0
  79. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/inbox.py +0 -0
  80. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/logging.py +0 -0
  81. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/memory.py +0 -0
  82. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/model_specs.py +0 -0
  83. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/names.py +0 -0
  84. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/paths.py +0 -0
  85. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/runtime.py +0 -0
  86. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/secrets.py +0 -0
  87. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/spawn.py +0 -0
  88. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/text.py +0 -0
  89. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/core/types.py +0 -0
  90. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/__init__.py +0 -0
  91. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/adapters/__init__.py +0 -0
  92. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/adapters/base.py +0 -0
  93. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/adapters/factory.py +0 -0
  94. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/adapters/imessage.py +0 -0
  95. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/adapters/registry.py +0 -0
  96. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/adapters/stub.py +0 -0
  97. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/adapters/telegram.py +0 -0
  98. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/allowlist.py +0 -0
  99. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/attach.py +0 -0
  100. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/chunker.py +0 -0
  101. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/client.py +0 -0
  102. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/commands.py +0 -0
  103. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/config.py +0 -0
  104. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/control.py +0 -0
  105. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/cron.py +0 -0
  106. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/elicitation.py +0 -0
  107. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/ensure.py +0 -0
  108. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/format.py +0 -0
  109. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/__init__.py +0 -0
  110. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/app.py +0 -0
  111. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/auth.py +0 -0
  112. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/constants.py +0 -0
  113. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/elicitation.py +0 -0
  114. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/exposure.py +0 -0
  115. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/host_agent.py +0 -0
  116. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/limits.py +0 -0
  117. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/middleware.py +0 -0
  118. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/principal.py +0 -0
  119. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/resources.py +0 -0
  120. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/subscriptions.py +0 -0
  121. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/gateway/turn_bridge.py +0 -0
  122. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/grants.py +0 -0
  123. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/inbox.py +0 -0
  124. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/inbox_cron.py +0 -0
  125. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/install.py +0 -0
  126. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/lock.py +0 -0
  127. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/mesh.py +0 -0
  128. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/message_pump.py +0 -0
  129. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/observability.py +0 -0
  130. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/owner.py +0 -0
  131. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/progress_sink.py +0 -0
  132. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/registry.py +0 -0
  133. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/router.py +0 -0
  134. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/runner.py +0 -0
  135. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/runner_main.py +0 -0
  136. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/secrets.py +0 -0
  137. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/secrets_broker.py +0 -0
  138. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/server.py +0 -0
  139. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/services.py +0 -0
  140. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/sinks.py +0 -0
  141. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/supervisor.py +0 -0
  142. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/tokens.py +0 -0
  143. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/traffic.py +0 -0
  144. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/turns.py +0 -0
  145. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/daemon/wake.py +0 -0
  146. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/execution/__init__.py +0 -0
  147. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/execution/context_window.py +0 -0
  148. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/execution/mcp_schema_index.py +0 -0
  149. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/execution/orchestrator.py +0 -0
  150. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/execution/parallel.py +0 -0
  151. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/execution/tool_result_store.py +0 -0
  152. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/execution/tool_schema_cache.py +0 -0
  153. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/hooks/__init__.py +0 -0
  154. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/hooks/config.py +0 -0
  155. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/hooks/engine.py +0 -0
  156. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/hooks/executors/__init__.py +0 -0
  157. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/hooks/executors/callback.py +0 -0
  158. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/hooks/executors/command.py +0 -0
  159. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/hooks/executors/http.py +0 -0
  160. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/hooks/executors/prompt.py +0 -0
  161. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/hooks/executors/ssrf_guard.py +0 -0
  162. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/hooks/matchers.py +0 -0
  163. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/hooks/registry.py +0 -0
  164. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/hooks/types.py +0 -0
  165. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/__init__.py +0 -0
  166. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/.claude-plugin/marketplace.json +0 -0
  167. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/.claude-plugin/plugin.json +0 -0
  168. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/.cursor-plugin/marketplace.json +0 -0
  169. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/.cursor-plugin/plugin.json +0 -0
  170. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/agents/operator.md +0 -0
  171. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/commands/ask.md +0 -0
  172. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/commands/memory.md +0 -0
  173. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/commands/tasks.md +0 -0
  174. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/mcp.json +0 -0
  175. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/rules/gateway.mdc +0 -0
  176. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/skills/ask/SKILL.md +0 -0
  177. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/skills/memory/SKILL.md +0 -0
  178. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/assets/skills/tasks/SKILL.md +0 -0
  179. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/doctor.py +0 -0
  180. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/install.py +0 -0
  181. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/paths.py +0 -0
  182. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/host_plugin/state.py +0 -0
  183. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/providers/__init__.py +0 -0
  184. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/providers/anthropic.py +0 -0
  185. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/providers/base.py +0 -0
  186. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/providers/http_client.py +0 -0
  187. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/providers/ollama.py +0 -0
  188. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/providers/openai.py +0 -0
  189. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/storage/__init__.py +0 -0
  190. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tasks/__init__.py +0 -0
  191. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tasks/scheduler.py +0 -0
  192. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tasks/store.py +0 -0
  193. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tasks/types.py +0 -0
  194. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/telemetry/__init__.py +0 -0
  195. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/telemetry/otel.py +0 -0
  196. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/templates/login_failed.html +0 -0
  197. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/templates/login_success.html +0 -0
  198. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/templates/serve/launchd.plist.tmpl +0 -0
  199. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/templates/serve/serve.toml.example +0 -0
  200. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/templates/serve/systemd.service.tmpl +0 -0
  201. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/templates/styles.css +0 -0
  202. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tools/__init__.py +0 -0
  203. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tools/manager/__init__.py +0 -0
  204. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tools/manager/_request_ctx.py +0 -0
  205. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tools/manager/base.py +0 -0
  206. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tools/manager/composite.py +0 -0
  207. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tools/manager/config.py +0 -0
  208. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tools/manager/mcp.py +0 -0
  209. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tools/search/__init__.py +0 -0
  210. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tools/search/discovered.py +0 -0
  211. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tools/search/scoring.py +0 -0
  212. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/tools/search/service.py +0 -0
  213. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/ui/__init__.py +0 -0
  214. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/ui/completion.py +0 -0
  215. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/ui/display.py +0 -0
  216. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/ui/elicitation.py +0 -0
  217. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/ui/input.py +0 -0
  218. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/voice/__init__.py +0 -0
  219. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/voice/audio.py +0 -0
  220. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/voice/cleanup.py +0 -0
  221. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/voice/session.py +0 -0
  222. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/voice/stt.py +0 -0
  223. {cade_cli-0.20.6 → cade_cli-0.20.7}/src/cadecoder/voice/tts.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: cade-cli
3
- Version: 0.20.6
3
+ Version: 0.20.7
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.6"
3
+ version = "0.20.7"
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"
@@ -176,6 +176,16 @@ class BaseThreadHistory(ABC):
176
176
  """Retrieves all messages for a given thread."""
177
177
  raise NotImplementedError
178
178
 
179
+ @abstractmethod
180
+ def replace_messages(self, thread_id: str, messages: list[Message]) -> None:
181
+ """Atomically replace all of a thread's messages (used by manual compaction).
182
+
183
+ Args:
184
+ thread_id: Thread whose messages are replaced.
185
+ messages: New messages to persist in place of the existing ones.
186
+ """
187
+ raise NotImplementedError
188
+
179
189
  @abstractmethod
180
190
  def get_thread(self, thread_id: str) -> Thread | None:
181
191
  """Retrieves thread metadata."""
@@ -533,6 +543,47 @@ class SqliteThreadHistory(BaseThreadHistory):
533
543
  log.error(f"Failed to add message: {e}")
534
544
  raise
535
545
 
546
+ def replace_messages(self, thread_id: str, messages: list[Message]) -> None:
547
+ """Delete a thread's messages and insert ``messages`` in their place.
548
+
549
+ Used by manual compaction (``/compact``): a turn always reloads the
550
+ full persisted thread from storage, so compacting only the in-memory
551
+ request would have no lasting effect — the next turn reconstructs the
552
+ same bloated context. This is the write-back half of that fix.
553
+ """
554
+ if not self._conn:
555
+ raise StorageError("Database connection is not available.")
556
+ try:
557
+ self._conn.execute("BEGIN")
558
+ self._execute("DELETE FROM messages WHERE conversation_id = ?", (thread_id,))
559
+ for message in messages:
560
+ message.thread_id = thread_id
561
+ if not message.message_id:
562
+ message.message_id = str(ulid()).lower()
563
+ msg_data = message.model_dump_db()
564
+ self._execute(
565
+ """
566
+ INSERT INTO messages (
567
+ id, conversation_id, role, content, timestamp,
568
+ tool_calls_json, tool_call_id, model_info_json,
569
+ parent_message_id, conversation_turn
570
+ )
571
+ VALUES (
572
+ :id, :conversation_id, :role, :content, :timestamp,
573
+ :tool_calls_json, :tool_call_id, :model_info_json,
574
+ :parent_message_id, :conversation_turn
575
+ )
576
+ """,
577
+ msg_data,
578
+ )
579
+ self._conn.execute("COMMIT")
580
+ except Exception as e:
581
+ self._conn.execute("ROLLBACK")
582
+ log.error(f"Failed to replace messages for thread {thread_id}: {e}")
583
+ raise
584
+ self.update_thread_timestamp(thread_id)
585
+ log.info(f"Replaced thread {thread_id} history with {len(messages)} message(s)")
586
+
536
587
  def _ensure_thread_exists(self, thread_id: str) -> None:
537
588
  """Create a thread record if it doesn't already exist."""
538
589
  if self.get_thread(thread_id):
@@ -19,8 +19,14 @@ from cadecoder.core.constants import DEFAULT_AI_MODEL
19
19
  from cadecoder.core.errors import AuthError
20
20
  from cadecoder.core.git import get_current_branch_name
21
21
  from cadecoder.core.logging import log
22
+ from cadecoder.core.runtime import get_runtime
22
23
  from cadecoder.core.text import strip_control_signals
23
24
  from cadecoder.core.types import ExecutionEventType
25
+ from cadecoder.execution.context_window import (
26
+ CompactionStrategy,
27
+ ContextWindowManager,
28
+ create_context_manager,
29
+ )
24
30
  from cadecoder.execution.orchestrator import (
25
31
  ExecutionContext,
26
32
  create_orchestrator,
@@ -241,6 +247,30 @@ class ChatSession:
241
247
  log.warning(f"Failed to save user message: {e}")
242
248
  return message
243
249
 
250
+ @staticmethod
251
+ def _tool_call_infos(tool_calls: list[dict[str, Any]] | None) -> list[ToolCallInfo]:
252
+ """Convert OpenAI-format ``tool_calls`` into storable ``ToolCallInfo``."""
253
+ tc_infos = []
254
+ for tc in tool_calls or []:
255
+ func = tc.get("function", {})
256
+ args_raw = func.get("arguments", "{}")
257
+ if isinstance(args_raw, str):
258
+ try:
259
+ params = json.loads(args_raw)
260
+ except json.JSONDecodeError:
261
+ params = {"raw": args_raw}
262
+ else:
263
+ params = args_raw if isinstance(args_raw, dict) else {}
264
+
265
+ tc_infos.append(
266
+ ToolCallInfo(
267
+ call_id=tc.get("id", str(ulid()).lower()),
268
+ tool_name=func.get("name", "unknown"),
269
+ parameters=params,
270
+ )
271
+ )
272
+ return tc_infos
273
+
244
274
  def save_assistant_message(
245
275
  self,
246
276
  content: str | None,
@@ -248,33 +278,12 @@ class ChatSession:
248
278
  model_info: ModelInfo | None = None,
249
279
  ) -> Message:
250
280
  """Save an assistant message."""
251
- tc_infos = []
252
- if tool_calls:
253
- for tc in tool_calls:
254
- func = tc.get("function", {})
255
- args_raw = func.get("arguments", "{}")
256
- if isinstance(args_raw, str):
257
- try:
258
- params = json.loads(args_raw)
259
- except json.JSONDecodeError:
260
- params = {"raw": args_raw}
261
- else:
262
- params = args_raw if isinstance(args_raw, dict) else {}
263
-
264
- tc_infos.append(
265
- ToolCallInfo(
266
- call_id=tc.get("id", str(ulid()).lower()),
267
- tool_name=func.get("name", "unknown"),
268
- parameters=params,
269
- )
270
- )
271
-
272
281
  message = Message(
273
282
  id=str(ulid()).lower(),
274
283
  thread_id=self.thread_id,
275
284
  role="assistant",
276
285
  content=content,
277
- tool_calls=tc_infos,
286
+ tool_calls=self._tool_call_infos(tool_calls),
278
287
  model_info=model_info,
279
288
  )
280
289
  try:
@@ -601,6 +610,8 @@ class ChatSession:
601
610
  self._print_thread_info()
602
611
  self._print_context_usage()
603
612
  self._print_history()
613
+ elif cmd == "/compact":
614
+ await self._handle_compact_command()
604
615
  elif cmd == "/logs":
605
616
  display_logs()
606
617
  elif cmd == "/tools":
@@ -840,22 +851,86 @@ class ChatSession:
840
851
  else:
841
852
  console.print(f"[cyan]Thread:[/cyan] [dim]{self.thread_id}[/dim]")
842
853
 
854
+ def _resolve_context_manager(self) -> ContextWindowManager:
855
+ """Return the live orchestrator's context manager, or build an equivalent one.
856
+
857
+ Attached-to-daemon sessions (the default when a daemon is running)
858
+ have no local orchestrator — turns run server-side — so ``self.orchestrator``
859
+ is ``None`` and there's nothing to delegate to. Build a standalone
860
+ manager from this run's resolved model/context_window instead of
861
+ crashing; it computes the same status/compaction a live one would.
862
+ """
863
+ if self.orchestrator is not None:
864
+ return self.orchestrator.context_manager
865
+ return create_context_manager(
866
+ model=self.model, context_window_override=get_runtime().context_window
867
+ )
868
+
869
+ def _message_from_llm_dict(self, msg: dict[str, Any]) -> Message:
870
+ """Convert a compacted LLM-format message dict back into a persistable ``Message``."""
871
+ role = msg.get("role", "user")
872
+ return Message(
873
+ id=str(ulid()).lower(),
874
+ thread_id=self.thread_id,
875
+ role=role,
876
+ content=msg.get("content"),
877
+ tool_calls=self._tool_call_infos(msg.get("tool_calls")) if role == "assistant" else [],
878
+ responding_tool_call_id=msg.get("tool_call_id") if role == "tool" else None,
879
+ )
880
+
843
881
  def _print_context_usage(self) -> None:
844
882
  """Print context-window usage and tool-output summary."""
845
883
  history = self.get_conversation_history()
846
- status = self.orchestrator.get_context_status(history)
884
+ context_manager = self._resolve_context_manager()
885
+ status = context_manager.check_context_status(history)
847
886
  console.print("\n[cyan]Context Window:[/cyan]")
848
887
  console.print(f" Tokens: {status['token_count']:,} / {status['effective_limit']:,}")
849
888
  console.print(f" Used: {status['percentage_used']}%")
850
889
  console.print(f" Messages: {status['message_count']}")
851
890
  console.print(f" Needs compaction: {status['needs_compaction']}")
852
891
 
853
- tool_summary = self.orchestrator.get_tool_outputs_summary()
854
- if tool_summary["total_outputs"] > 0:
855
- console.print("\n[cyan]Tool Outputs:[/cyan]")
856
- console.print(f" Total outputs: {tool_summary['total_outputs']}")
857
- console.print(f" Unique tools: {tool_summary['unique_tools']}")
858
- console.print(f" Estimated tokens: {tool_summary['estimated_tokens']:,}")
892
+ if self.orchestrator is not None:
893
+ tool_summary = self.orchestrator.get_tool_outputs_summary()
894
+ if tool_summary["total_outputs"] > 0:
895
+ console.print("\n[cyan]Tool Outputs:[/cyan]")
896
+ console.print(f" Total outputs: {tool_summary['total_outputs']}")
897
+ console.print(f" Unique tools: {tool_summary['unique_tools']}")
898
+ console.print(f" Estimated tokens: {tool_summary['estimated_tokens']:,}")
899
+
900
+ async def _handle_compact_command(self) -> None:
901
+ """Manually compact the current thread's history ahead of the auto-compaction threshold.
902
+
903
+ Unlike the automatic compaction that runs mid-turn (transient — it
904
+ only shrinks that one outgoing request), this persists the trimmed
905
+ history back to storage via ``replace_messages`` so the *next* turn
906
+ — which always reloads the full thread from disk — actually sees a
907
+ smaller context instead of reconstructing the same bloated one.
908
+ """
909
+ history = self.get_conversation_history()
910
+ if not history:
911
+ console.print("[dim]Nothing to compact — no messages yet.[/dim]")
912
+ return
913
+
914
+ context_manager = self._resolve_context_manager()
915
+ before = context_manager.check_context_status(history)
916
+ compacted, backup = context_manager.compact_context(
917
+ history, strategy=CompactionStrategy.KEEP_RECENT, thread_id=self.thread_id
918
+ )
919
+ try:
920
+ self.history_manager.replace_messages(
921
+ self.thread_id, [self._message_from_llm_dict(m) for m in compacted]
922
+ )
923
+ except Exception as e:
924
+ console.print(f"[red]Failed to persist compacted history: {escape(str(e))}[/red]")
925
+ return
926
+
927
+ after = context_manager.check_context_status(compacted)
928
+ console.print(
929
+ f"[green]Compacted:[/green] {before['token_count']:,} -> "
930
+ f"{after['token_count']:,} tokens "
931
+ f"({before['message_count']} -> {after['message_count']} messages), "
932
+ f"backup saved {backup.timestamp.isoformat()}"
933
+ )
859
934
 
860
935
  def _print_history(self) -> None:
861
936
  """Print the conversation history for the current thread."""
@@ -35,6 +35,7 @@ SLASH_COMMANDS: tuple[SlashCommand, ...] = (
35
35
  SlashCommand("/thread", "", "Show thread info, context usage, and history"),
36
36
  SlashCommand("/usage", "", "Show context window status and token usage", hidden=True),
37
37
  SlashCommand("/history", "", "Show conversation history", hidden=True),
38
+ SlashCommand("/compact", "", "Compact the context window now, ahead of the auto threshold"),
38
39
  SlashCommand("/model", " [list|name]", "Show, list, or switch model", ("list",)),
39
40
  SlashCommand(
40
41
  "/tasks",
File without changes
File without changes
File without changes