tau-coding-agent 0.3.5__tar.gz → 0.3.9__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 (337) hide show
  1. {tau_coding_agent-0.3.5/tau_coding_agent.egg-info → tau_coding_agent-0.3.9}/PKG-INFO +3 -1
  2. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/auth.md +1 -0
  3. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/extensions.md +0 -24
  4. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/inference-providers.md +42 -1
  5. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/settings.md +13 -5
  6. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/usage.md +2 -2
  7. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/pyproject.toml +4 -1
  8. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/agent/prompt/builder.py +15 -8
  9. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/agent/service.py +153 -75
  10. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/auth/manager.py +6 -2
  11. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/extensions/footer/__init__.py +14 -9
  12. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/extensions/header/__init__.py +7 -2
  13. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/models/text.py +340 -3
  14. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/providers/text.py +39 -0
  15. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/tools/glob.py +22 -3
  16. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/tools/grep.py +48 -18
  17. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/tools/read.py +4 -2
  18. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/console/commands/auth.py +14 -3
  19. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/core/registry.py +1 -1
  20. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/engine/service.py +29 -5
  21. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/engine/types.py +2 -1
  22. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/extensions/__init__.py +0 -2
  23. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/extensions/api.py +0 -14
  24. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/extensions/context.py +10 -2
  25. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/extensions/loader.py +11 -11
  26. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/extensions/runtime.py +15 -0
  27. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/hooks/engine.py +14 -0
  28. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/hooks/service.py +3 -3
  29. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/__init__.py +3 -3
  30. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/audio/gemini_audio.py +2 -2
  31. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/audio/service.py +25 -2
  32. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/image/gemini_image.py +2 -2
  33. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/image/service.py +14 -1
  34. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/anthropic_claude_code.py +26 -12
  35. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/anthropic_messages.py +32 -13
  36. tau_coding_agent-0.3.9/tau/inference/api/text/anthropic_vertex.py +269 -0
  37. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/builtins.py +3 -0
  38. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/gemini_generate.py +26 -22
  39. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/github_copilot_chat.py +5 -0
  40. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/google_antigravity.py +26 -8
  41. tau_coding_agent-0.3.9/tau/inference/api/text/google_vertex.py +366 -0
  42. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/mistral_chat.py +4 -1
  43. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/ollama_chat.py +4 -1
  44. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/openai_codex_responses.py +11 -11
  45. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/openai_completions.py +5 -0
  46. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/openai_responses.py +16 -12
  47. tau_coding_agent-0.3.9/tau/inference/api/text/openai_vertex.py +309 -0
  48. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/service.py +105 -27
  49. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/video/service.py +14 -1
  50. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/model/types.py +6 -1
  51. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/provider/oauth/utils.py +4 -1
  52. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/provider/registry.py +5 -9
  53. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/types.py +1 -0
  54. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/utils.py +49 -0
  55. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/message/types.py +9 -21
  56. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/message/utils.py +3 -2
  57. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/packages/manager.py +5 -2
  58. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/rpc/mode.py +8 -4
  59. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/runtime/service.py +30 -20
  60. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/runtime/types.py +8 -5
  61. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/session/compaction.py +47 -0
  62. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/session/manager.py +36 -8
  63. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/session/utils.py +55 -3
  64. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/settings/manager.py +19 -8
  65. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/trust/manager.py +7 -1
  66. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/agent_hooks.py +4 -1
  67. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/ansi.py +23 -0
  68. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/app.py +11 -1
  69. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/commands/auth.py +24 -18
  70. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/commands/context.py +3 -3
  71. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/commands/session.py +34 -9
  72. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/autocomplete_manager.py +5 -2
  73. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/image.py +9 -2
  74. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/layout.py +12 -0
  75. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/message_list.py +12 -4
  76. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/settings_modal.py +3 -1
  77. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/text_input.py +61 -39
  78. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/input.py +5 -0
  79. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/input_handler.py +49 -22
  80. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/markdown.py +52 -13
  81. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/renderer.py +24 -19
  82. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/terminal.py +9 -10
  83. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/tui.py +15 -4
  84. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/utils/image_processing.py +2 -2
  85. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/utils/secrets.py +16 -3
  86. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9/tau_coding_agent.egg-info}/PKG-INFO +3 -1
  87. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau_coding_agent.egg-info/SOURCES.txt +6 -1
  88. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau_coding_agent.egg-info/requires.txt +3 -0
  89. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_ansi.py +145 -0
  90. tau_coding_agent-0.3.9/tests/test_auth_storage.py +106 -0
  91. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_builtin_tools.py +43 -0
  92. tau_coding_agent-0.3.9/tests/test_compaction.py +433 -0
  93. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_image_processing.py +69 -0
  94. tau_coding_agent-0.3.9/tests/test_inference_api_text_utils.py +127 -0
  95. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_markdown.py +42 -0
  96. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_message_types.py +83 -0
  97. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_message_utils.py +27 -0
  98. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_packages_utils.py +48 -0
  99. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_rpc_mode.py +125 -4
  100. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_secrets.py +6 -1
  101. tau_coding_agent-0.3.9/tests/test_session_trust_persist.py +154 -0
  102. tau_coding_agent-0.3.9/tests/test_session_utils.py +443 -0
  103. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_settings_paths.py +29 -0
  104. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_settings_storage.py +42 -0
  105. tau_coding_agent-0.3.9/tests/test_text_llm_invoke.py +308 -0
  106. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_tool_registry.py +27 -0
  107. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_trust_utils.py +29 -0
  108. tau_coding_agent-0.3.9/tests/test_tui_input.py +401 -0
  109. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_tui_utils.py +9 -2
  110. tau_coding_agent-0.3.5/tau/extensions/events.py +0 -71
  111. tau_coding_agent-0.3.5/tests/test_auth_storage.py +0 -43
  112. tau_coding_agent-0.3.5/tests/test_compaction.py +0 -214
  113. tau_coding_agent-0.3.5/tests/test_session_utils.py +0 -169
  114. tau_coding_agent-0.3.5/tests/test_tui_input.py +0 -211
  115. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/LICENSE +0 -0
  116. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/MANIFEST.in +0 -0
  117. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/README.md +0 -0
  118. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/IMPLEMENTATION_SUMMARY.md +0 -0
  119. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/architecture.md +0 -0
  120. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/cli-reference.md +0 -0
  121. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/development.md +0 -0
  122. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/docs.json +0 -0
  123. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/extension-settings.md +0 -0
  124. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/http-proxy.md +0 -0
  125. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/index.md +0 -0
  126. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/installation.md +0 -0
  127. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/keybindings.md +0 -0
  128. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/messages.md +0 -0
  129. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/project-context.md +0 -0
  130. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/project-structure.md +0 -0
  131. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/prompts.md +0 -0
  132. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/python-api.md +0 -0
  133. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/quickstart.md +0 -0
  134. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/sessions.md +0 -0
  135. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/skills.md +0 -0
  136. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/themes.md +0 -0
  137. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/docs/tools.md +0 -0
  138. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/setup.cfg +0 -0
  139. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/__init__.py +0 -0
  140. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/agent/__init__.py +0 -0
  141. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/agent/prompt/__init__.py +0 -0
  142. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/agent/prompt/types.py +0 -0
  143. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/agent/types.py +0 -0
  144. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/auth/storage.py +0 -0
  145. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/auth/types.py +0 -0
  146. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/__init__.py +0 -0
  147. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/commands/__init__.py +0 -0
  148. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/commands/clear.py +0 -0
  149. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/commands/compact.py +0 -0
  150. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/commands/reload.py +0 -0
  151. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/commands/session.py +0 -0
  152. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/extensions/footer/git.py +0 -0
  153. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/extensions/footer/model.py +0 -0
  154. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/extensions/footer/utils.py +0 -0
  155. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/models/__init__.py +0 -0
  156. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/models/audio.py +0 -0
  157. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/models/image.py +0 -0
  158. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/models/video.py +0 -0
  159. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/prompts/commit.md +0 -0
  160. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/prompts/docs.md +0 -0
  161. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/prompts/explain.md +0 -0
  162. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/prompts/fix.md +0 -0
  163. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/prompts/refactor.md +0 -0
  164. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/prompts/review.md +0 -0
  165. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/prompts/test.md +0 -0
  166. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/providers/__init__.py +0 -0
  167. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/providers/audio.py +0 -0
  168. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/providers/image.py +0 -0
  169. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/providers/video.py +0 -0
  170. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/skills/code-review/SKILL.md +0 -0
  171. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/skills/debug/SKILL.md +0 -0
  172. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/skills/git-commit/SKILL.md +0 -0
  173. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/themes/dark.yaml +0 -0
  174. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/themes/light.yaml +0 -0
  175. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/tools/__init__.py +0 -0
  176. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/tools/edit.py +0 -0
  177. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/tools/ls.py +0 -0
  178. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/tools/terminal.py +0 -0
  179. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/builtins/tools/write.py +0 -0
  180. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/commands/__init__.py +0 -0
  181. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/commands/registry.py +0 -0
  182. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/commands/types.py +0 -0
  183. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/console/__init__.py +0 -0
  184. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/console/cli.py +0 -0
  185. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/console/commands/__init__.py +0 -0
  186. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/console/commands/packages.py +0 -0
  187. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/console/commands/update.py +0 -0
  188. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/core/__init__.py +0 -0
  189. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/engine/__init__.py +0 -0
  190. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/extensions/settings.py +0 -0
  191. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/hooks/__init__.py +0 -0
  192. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/hooks/inference.py +0 -0
  193. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/hooks/runtime.py +0 -0
  194. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/hooks/session.py +0 -0
  195. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/hooks/tui.py +0 -0
  196. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/hooks/types.py +0 -0
  197. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/__init__.py +0 -0
  198. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/audio/__init__.py +0 -0
  199. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/audio/base.py +0 -0
  200. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/audio/builtins.py +0 -0
  201. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/audio/elevenlabs_audio.py +0 -0
  202. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/audio/openai_audio.py +0 -0
  203. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/audio/registry.py +0 -0
  204. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/audio/sarvam_audio.py +0 -0
  205. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/audio/utils.py +0 -0
  206. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/image/__init__.py +0 -0
  207. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/image/base.py +0 -0
  208. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/image/builtins.py +0 -0
  209. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/image/openai_image.py +0 -0
  210. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/image/openrouter.py +0 -0
  211. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/image/registry.py +0 -0
  212. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/registry.py +0 -0
  213. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/__init__.py +0 -0
  214. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/base.py +0 -0
  215. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/registry.py +0 -0
  216. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/types.py +0 -0
  217. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/text/utils.py +0 -0
  218. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/video/__init__.py +0 -0
  219. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/video/base.py +0 -0
  220. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/video/builtins.py +0 -0
  221. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/video/fal_video.py +0 -0
  222. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/video/openrouter_video.py +0 -0
  223. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/api/video/registry.py +0 -0
  224. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/model/__init__.py +0 -0
  225. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/model/registry.py +0 -0
  226. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/provider/__init__.py +0 -0
  227. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/provider/oauth/__init__.py +0 -0
  228. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/provider/oauth/anthropic_claude_code.py +0 -0
  229. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/provider/oauth/github_copilot.py +0 -0
  230. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/provider/oauth/google_antigravity.py +0 -0
  231. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/provider/oauth/openai_codex.py +0 -0
  232. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/provider/oauth/pkce.py +0 -0
  233. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/provider/oauth/types.py +0 -0
  234. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/inference/provider/types.py +0 -0
  235. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/message/__init__.py +0 -0
  236. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/packages/__init__.py +0 -0
  237. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/packages/types.py +0 -0
  238. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/packages/utils.py +0 -0
  239. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/prompts/expand.py +0 -0
  240. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/prompts/loader.py +0 -0
  241. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/prompts/registry.py +0 -0
  242. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/prompts/types.py +0 -0
  243. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/rpc/__init__.py +0 -0
  244. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/rpc/types.py +0 -0
  245. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/session/branch_summarization.py +0 -0
  246. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/session/types.py +0 -0
  247. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/settings/paths.py +0 -0
  248. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/settings/storage.py +0 -0
  249. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/settings/types.py +0 -0
  250. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/settings/utils.py +0 -0
  251. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/skills/loader.py +0 -0
  252. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/skills/registry.py +0 -0
  253. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/skills/types.py +0 -0
  254. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/themes/loader.py +0 -0
  255. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/themes/registry.py +0 -0
  256. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/themes/types.py +0 -0
  257. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tool/__init__.py +0 -0
  258. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tool/registry.py +0 -0
  259. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tool/render.py +0 -0
  260. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tool/types.py +0 -0
  261. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/trust/__init__.py +0 -0
  262. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/trust/types.py +0 -0
  263. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/trust/utils.py +0 -0
  264. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/__init__.py +0 -0
  265. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/autocomplete.py +0 -0
  266. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/capabilities.py +0 -0
  267. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/commands/__init__.py +0 -0
  268. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/commands/appearance.py +0 -0
  269. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/commands/misc.py +0 -0
  270. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/commands/model.py +0 -0
  271. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/component.py +0 -0
  272. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/__init__.py +0 -0
  273. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/autocomplete_picker.py +0 -0
  274. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/box.py +0 -0
  275. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/command_palette.py +0 -0
  276. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/dynamic_border.py +0 -0
  277. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/file_picker.py +0 -0
  278. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/inline_selector.py +0 -0
  279. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/modal.py +0 -0
  280. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/model_palette.py +0 -0
  281. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/picker_overlay.py +0 -0
  282. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/prompt_overlay.py +0 -0
  283. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/resume_modal.py +0 -0
  284. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/select_list.py +0 -0
  285. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/settings_schema.py +0 -0
  286. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/spinner.py +0 -0
  287. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/text_prompt.py +0 -0
  288. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/tree_select_list.py +0 -0
  289. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/components/trust_screen.py +0 -0
  290. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/diff.py +0 -0
  291. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/fuzzy.py +0 -0
  292. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/keybindings.py +0 -0
  293. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/message_renderers.py +0 -0
  294. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/overlay.py +0 -0
  295. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/theme.py +0 -0
  296. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/ui_context.py +0 -0
  297. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/tui/utils.py +0 -0
  298. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/utils/__init__.py +0 -0
  299. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/utils/http_proxy.py +0 -0
  300. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau/utils/version_check.py +0 -0
  301. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau_coding_agent.egg-info/dependency_links.txt +0 -0
  302. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau_coding_agent.egg-info/entry_points.txt +0 -0
  303. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tau_coding_agent.egg-info/top_level.txt +0 -0
  304. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_agent_prompt.py +0 -0
  305. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_agent_types.py +0 -0
  306. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_auth_manager.py +0 -0
  307. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_branch_summarization.py +0 -0
  308. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_command_registry.py +0 -0
  309. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_diff.py +0 -0
  310. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_engine_types.py +0 -0
  311. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_footer_utils.py +0 -0
  312. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_fuzzy.py +0 -0
  313. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_http_proxy.py +0 -0
  314. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_inference_error_utils.py +0 -0
  315. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_inference_types.py +0 -0
  316. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_inference_utils.py +0 -0
  317. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_keybindings.py +0 -0
  318. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_model_registry.py +0 -0
  319. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_model_types.py +0 -0
  320. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_oauth_utils.py +0 -0
  321. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_pkce.py +0 -0
  322. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_prompts_expand.py +0 -0
  323. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_prompts_loader.py +0 -0
  324. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_prompts_registry.py +0 -0
  325. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_provider_registry.py +0 -0
  326. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_session_types.py +0 -0
  327. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_settings_manager.py +0 -0
  328. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_settings_utils.py +0 -0
  329. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_skills_loader.py +0 -0
  330. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_skills_registry.py +0 -0
  331. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_theme_loader.py +0 -0
  332. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_themes_registry.py +0 -0
  333. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_tool_render.py +0 -0
  334. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_trust_manager.py +0 -0
  335. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_tui_capabilities.py +0 -0
  336. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_tui_theme.py +0 -0
  337. {tau_coding_agent-0.3.5 → tau_coding_agent-0.3.9}/tests/test_version_check.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tau-coding-agent
3
- Version: 0.3.5
3
+ Version: 0.3.9
4
4
  Summary: A self-extensible agent CLI with terminal UI, multi-provider LLM support, session management with branching, and a plugin system for tools and commands
5
5
  Requires-Python: >=3.12
6
6
  Description-Content-Type: text/markdown
@@ -26,6 +26,8 @@ Requires-Dist: pygments==2.20.0
26
26
  Requires-Dist: pathspec==1.1.1
27
27
  Requires-Dist: gitpython==3.1.50
28
28
  Requires-Dist: grapheme==0.6.0
29
+ Provides-Extra: tools
30
+ Requires-Dist: ripgrep>=14.0.0; extra == "tools"
29
31
  Dynamic: license-file
30
32
 
31
33
  # Tau (τ)
@@ -143,6 +143,7 @@ The provider ID used as the key in `auth.json` and the `{PROVIDER}_API_KEY` env
143
143
  | OpenAI | `openai` | `OPENAI_API_KEY` |
144
144
  | Google | `google` | `GOOGLE_API_KEY` |
145
145
  | Mistral | `mistral` | `MISTRAL_API_KEY` |
146
+ | Fireworks AI | `fireworks` | `FIREWORKS_API_KEY` |
146
147
  | Ollama | `ollama` | `OLLAMA_API_KEY` |
147
148
 
148
149
  ## Next Steps
@@ -627,29 +627,6 @@ session working directory; pass an explicit `cwd=` to override.
627
627
 
628
628
  ---
629
629
 
630
- ## Cross-extension event bus
631
-
632
- Extensions can communicate with each other via `tau.events`:
633
-
634
- ```python
635
- # producer.py
636
- def register(tau):
637
- @tau.on("session_start")
638
- async def on_start(event, ctx):
639
- await tau.events.emit("producer:ready", {"version": "1.0"})
640
-
641
- # consumer.py
642
- def register(tau):
643
- @tau.events.on("producer:ready")
644
- async def on_ready(data):
645
- print(f"producer ready — version {data['version']}")
646
- ```
647
-
648
- This is separate from the hooks bus: `tau.events` is for extension-to-extension
649
- messages; `tau.on(...)` is for system lifecycle events.
650
-
651
- ---
652
-
653
630
  ## Editor autocomplete providers
654
631
 
655
632
  Extensions can inject custom autocomplete suggestions into the editor. When the user
@@ -742,7 +719,6 @@ def register(tau):
742
719
  | `tau.register_flag(name, type, env, default)` | Declare an env-backed flag |
743
720
  | `tau.get_flag(name)` | Read a registered flag's value |
744
721
  | `await tau.exec(cmd, args, cwd)` | Run a shell command |
745
- | `tau.events` | Cross-extension `EventBus` |
746
722
  | `tau.config` | Per-extension settings dict from `settings.json` |
747
723
  | `tau.cwd` | `Path` — working directory at session start |
748
724
  | `tau.model_id` | Active model identifier |
@@ -12,6 +12,7 @@ Tau supports the following inference providers:
12
12
  | OpenAI | API Key | No | [Link](#openai) |
13
13
  | Google Gemini | API Key | Yes | [Link](#google-gemini) |
14
14
  | Mistral AI | API Key | Limited | [Link](#mistral-ai) |
15
+ | Fireworks AI | API Key | No | [Link](#fireworks-ai) |
15
16
  | Ollama | None | Yes | [Link](#ollama-local) |
16
17
  | Azure OpenAI | API Key | No | [Link](#azure-openai) |
17
18
 
@@ -103,11 +104,51 @@ export MISTRAL_API_KEY=...
103
104
  tau --model mistral/mistral-large -p "Say hello"
104
105
  ```
105
106
 
107
+ ## Fireworks AI
108
+
109
+ Fireworks AI provides fast, cost-efficient inference for open-source models including Llama, DeepSeek, Qwen, and Mixtral — with OpenAI-compatible APIs.
110
+
111
+ **Text models**:
112
+
113
+ | Model | Context | Pricing (in/out per M tokens) |
114
+ |-------|---------|-------------------------------|
115
+ | `accounts/fireworks/models/llama-v3p3-70b-instruct` | 131K | $0.90 / $0.90 |
116
+ | `accounts/fireworks/models/llama-v3p1-405b-instruct` | 131K | $3.00 / $3.00 |
117
+ | `accounts/fireworks/models/deepseek-r1` *(thinking)* | 160K | $3.00 / $7.00 |
118
+ | `accounts/fireworks/models/deepseek-v3` | 131K | $0.90 / $0.90 |
119
+ | `accounts/fireworks/models/qwen3-235b-a22b` *(thinking)* | 131K | $0.22 / $0.88 |
120
+ | `accounts/fireworks/models/qwen3-30b-a3b` *(thinking)* | 131K | $0.15 / $0.60 |
121
+ | `accounts/fireworks/models/mixtral-8x22b-instruct` | 65K | $0.90 / $0.90 |
122
+ | `accounts/fireworks/models/gemma2-9b-it` | 8K | $0.20 / $0.20 |
123
+
124
+ **Image models**: Flux 1 Schnell FP8, Flux 1 Dev FP8
125
+
126
+ ### Setup
127
+
128
+ 1. Create an account at [Fireworks AI](https://fireworks.ai)
129
+ 2. Generate an API key in your account settings
130
+ 3. Set the environment variable:
131
+
132
+ ```bash
133
+ export FIREWORKS_API_KEY=fw_...
134
+ ```
135
+
136
+ ### Verify
137
+
138
+ ```bash
139
+ tau --model fireworks/accounts/fireworks/models/llama-v3p3-70b-instruct -p "Say hello"
140
+ ```
141
+
142
+ ### Notes
143
+
144
+ - Uses the OpenAI-compatible completions API under the hood
145
+ - Session affinity is maintained automatically via a per-request `x-session-affinity` header
146
+
106
147
  ## Ollama (Local)
107
148
 
108
149
  Run open-source models locally without API keys or internet.
109
150
 
110
- **Models**: `llama2`, `mistral`, `neural-chat`, and [others](https://ollama.ai/library)
151
+ **Models**: `llama2`, `mistral`, `neural-chat`, `qwen3.5:cloud` (262K context, thinking), and [others](https://ollama.ai/library)
111
152
 
112
153
  ### Setup
113
154
 
@@ -187,6 +187,10 @@ When your conversation grows long, tau automatically summarizes older messages t
187
187
  - **`reserve_tokens`**: How many tokens to keep available for the LLM's response (default 16,384 ≈ 4K-5K words)
188
188
  - **`keep_recent_tokens`**: How many recent message tokens to preserve word-for-word before summarization kicks in (default 20,000 ≈ 5K-6K words)
189
189
 
190
+ #### Mid-turn (threshold) compaction
191
+
192
+ In addition to compaction triggered at the start of a turn, tau can compact **mid-turn** when the context hits the configured limit while the agent is already running. When this happens the engine stops cleanly so you can review the compacted context and continue — no partial output is lost. Tool output lines are truncated before sending to the LLM to help prevent hitting the threshold in the first place.
193
+
190
194
  Example configurations:
191
195
 
192
196
  ```json
@@ -284,6 +288,10 @@ These settings are applied to the LLM client at startup:
284
288
 
285
289
  Changes take effect on the next session start or after `/reload`.
286
290
 
291
+ #### Adaptive retry delay
292
+
293
+ When a provider responds with a `Retry-After` or `Retry-After-Ms` header (common on rate-limit responses), tau uses that value as the retry delay instead of the configured `base_delay_ms`. The delay is capped at **60 seconds** so a provider that returns an extreme value (e.g. "retry in 16 days") doesn't stall the agent indefinitely. When no header is present, `base_delay_ms` is used.
294
+
287
295
  ```json
288
296
  {
289
297
  "retry": {
@@ -442,11 +450,11 @@ All retry settings are **fully implemented and wired to the LLM client at startu
442
450
  All thinking budget settings are **fully implemented and configurable**:
443
451
 
444
452
  - **`thinking_budgets.minimal`**: Token budget for "minimal" level (default: `1024`)
445
- - **`thinking_budgets.low`**: Token budget for "low" level (default: `2048`)
446
- - **`thinking_budgets.medium`**: Token budget for "medium" level (default: `4096`)
447
- - **`thinking_budgets.high`**: Token budget for "high" level (default: `8192`)
448
- - **`thinking_budgets.xhigh`**: Token budget for "xhigh" level (default: `16384`)
449
- - **`thinking_budgets.max`**: Token budget for "max" level (default: `32768`)
453
+ - **`thinking_budgets.low`**: Token budget for "low" level (default: `4096`)
454
+ - **`thinking_budgets.medium`**: Token budget for "medium" level (default: `8192`)
455
+ - **`thinking_budgets.high`**: Token budget for "high" level (default: `16384`)
456
+ - **`thinking_budgets.xhigh`**: Token budget for "xhigh" level (default: `32768`)
457
+ - **`thinking_budgets.max`**: Token budget for "max" level (default: `65536`)
450
458
 
451
459
  Override these to customize extended thinking token allocations for your workflow.
452
460
 
@@ -102,8 +102,8 @@ Prints session info inline in the chat. Shows:
102
102
 
103
103
  - **Session Info** — Name (if set), File path, ID
104
104
  - **Messages** — User, Assistant, Tool calls, Tool results, Total
105
- - **Tokens** — Input, Output, Cache read (if any), Cache write (if any), Total
106
- - **Cost** — Total USD cost (only shown if non-zero)
105
+ - **Tokens** — Input, Output, Cache read (if any), Cache write (if any), Total — counts use human-readable suffixes (e.g. `1.2K`, `3.4M`); each line shows an inline cost estimate in USD
106
+ - **Cost** — Total USD cost with inline estimate (only shown if non-zero)
107
107
 
108
108
  ### `/copy`
109
109
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tau-coding-agent"
7
- version = "0.3.5"
7
+ version = "0.3.9"
8
8
  description = "A self-extensible agent CLI with terminal UI, multi-provider LLM support, session management with branching, and a plugin system for tools and commands"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -68,6 +68,9 @@ tau = [
68
68
  [tool.pytest.ini_options]
69
69
  testpaths = ["tests"]
70
70
 
71
+ [project.optional-dependencies]
72
+ tools = ["ripgrep>=14.0.0"]
73
+
71
74
  [dependency-groups]
72
75
  dev = [
73
76
  "pytest>=9.1.1",
@@ -93,7 +93,8 @@ def load_project_context_files(cwd: Path) -> list[tuple[str, Path]]:
93
93
 
94
94
 
95
95
  _DEFAULT_IDENTITY = """\
96
- You are a coding agent operating inside Tau, a coding agent harness. You help users by reading files, executing commands, editing code, and writing new files.
96
+ You are a coding agent operating inside Tau, a coding agent harness. You help users by
97
+ reading files, executing commands, editing code, and writing new files.
97
98
 
98
99
  You have strong software engineering skills. You think carefully before making changes,
99
100
  and follow the existing style and conventions of the project.
@@ -101,10 +102,13 @@ and follow the existing style and conventions of the project.
101
102
 
102
103
  _GENERAL_GUIDELINES = [
103
104
  "If a task is ambiguous, ask a precise, clarifying question before proceeding.",
104
- "Do only what the task asks; don't add features, refactors, or abstractions beyond scope.",
105
+ ("Do only what the task asks; don't add features, refactors, or abstractions beyond scope."),
105
106
  "Write comments when the *why* is non-obvious — well-named code explains itself.",
106
107
  "Keep responses short, concise, and direct; don't summarize what you just did.",
107
- "Prioritize accuracy over agreement — investigate before confirming, and disagree when the evidence calls for it.",
108
+ (
109
+ "Prioritize accuracy over agreement — investigate before confirming, and "
110
+ "disagree when the evidence calls for it."
111
+ ),
108
112
  ]
109
113
 
110
114
 
@@ -231,7 +235,9 @@ class PromptBuilder:
231
235
  append = self._append()
232
236
  git = self._git_section()
233
237
  footer = self._footer()
234
- return identity + guidelines + tools + docs + project_context + skills + append + git + footer
238
+ return (
239
+ identity + guidelines + tools + docs + project_context + skills + append + git + footer
240
+ )
235
241
 
236
242
  # ------------------------------------------------------------------
237
243
  # Layers
@@ -267,7 +273,10 @@ class PromptBuilder:
267
273
  if guideline:
268
274
  guidelines.append(f"- **{t.name}**: {guideline.strip()}")
269
275
  section = "\n\n# Available Tools\n\n" + "\n".join(lines)
270
- section+="\nIn addition to the tools above, you may have access to other custom tools depending on the project."
276
+ section += (
277
+ "\nIn addition to the tools above, you may have access to other custom "
278
+ "tools depending on the project."
279
+ )
271
280
  if guidelines:
272
281
  section += "\n\n## Tool Guidelines\n\n" + "\n".join(guidelines)
273
282
  return section
@@ -297,9 +306,7 @@ class PromptBuilder:
297
306
  return (
298
307
  "\n\n# Project Instructions\n\n"
299
308
  "Project-specific guidelines (follow before general Tau guidelines):\n\n"
300
- "<project_context>\n\n"
301
- + blocks
302
- + "</project_context>"
309
+ "<project_context>\n\n" + blocks + "</project_context>"
303
310
  )
304
311
 
305
312
  def _docs_section(self) -> str:
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import asyncio
4
+ import logging
4
5
  from pathlib import Path
5
6
  from typing import TYPE_CHECKING
6
7
 
@@ -8,17 +9,33 @@ from tau.agent.types import AgentConfig, AgentContext, AgentPhase, ContextUsage,
8
9
  from tau.hooks.engine import MessageEndEvent, MessageRollbackEvent, SavePointEvent, SettledEvent
9
10
  from tau.hooks.service import Hooks
10
11
  from tau.message.types import (
11
- AgentMessage,
12
12
  AssistantMessage,
13
13
  LLMMessage,
14
- TerminalExecutionMessage,
15
- TextContent,
16
14
  ToolMessage,
17
15
  UserMessage,
18
16
  )
19
17
  from tau.message.utils import strip_unusable_trailing_assistant
18
+ from tau.session.utils import to_llm_messages as _to_llm_messages
20
19
  from tau.tool.types import ToolInvocation, ToolResult
21
20
 
21
+ _log = logging.getLogger(__name__)
22
+
23
+ _TOOL_CAP_BYTES = 50 * 1024 # 50 KB — DEFAULT_MAX_BYTES
24
+ _TOOL_CAP_LINES = 2000 # DEFAULT_MAX_LINES
25
+ _TOOL_LINE_CAP_BYTES = 2 * 1024 # 2 KB — max bytes for a single line
26
+
27
+
28
+ from tau.hooks.engine import CompactionReason as _CompactionReason
29
+ from tau.session.compaction import ThresholdCompactionStop as _ThresholdCompactionStop
30
+
31
+
32
+ def _fmt_size(n: int) -> str:
33
+ if n < 1024:
34
+ return f"{n}B"
35
+ if n < 1024 * 1024:
36
+ return f"{n / 1024:.1f}KB"
37
+ return f"{n / (1024 * 1024):.1f}MB"
38
+
22
39
  if TYPE_CHECKING:
23
40
  from tau.engine.service import Engine
24
41
  from tau.runtime.service import Runtime
@@ -26,37 +43,6 @@ if TYPE_CHECKING:
26
43
  from tau.session.manager import SessionManager
27
44
 
28
45
 
29
- def _to_llm_messages(messages: list[AgentMessage]) -> list[LLMMessage]:
30
- """Convert AgentMessages to LLM-compatible messages.
31
-
32
- TerminalExecutionMessage → UserMessage (Ran `cmd`\n```output```)
33
- CompactionSummaryMessage → UserMessage with summary wrapped in XML tags
34
- CustomMessage and other non-LLM types → skipped
35
- Empty AssistantMessages are visual-only markers (aborts, persisted API/credit
36
- errors) and are skipped — an assistant turn with neither content nor tool
37
- calls is invalid to send back and triggers provider 400s.
38
- """
39
- from tau.message.types import CompactionSummaryMessage, ThinkingContent, ToolCallContent
40
-
41
- result: list[LLMMessage] = []
42
- for msg in messages:
43
- if isinstance(msg, CompactionSummaryMessage):
44
- text = f"<context-summary>\n{msg.summary}\n</context-summary>"
45
- result.append(UserMessage.from_text(text))
46
- elif isinstance(msg, TerminalExecutionMessage):
47
- if not msg.exclude:
48
- result.append(msg.to_user_message())
49
- elif isinstance(msg, AssistantMessage):
50
- has_usable = any(
51
- isinstance(c, (TextContent, ToolCallContent, ThinkingContent)) for c in msg.contents
52
- )
53
- if has_usable:
54
- result.append(msg)
55
- elif isinstance(msg, (UserMessage, ToolMessage)):
56
- result.append(msg)
57
- return result
58
-
59
-
60
46
  class Agent:
61
47
  """
62
48
  High-level agent session tying together Engine and SessionManager.
@@ -87,6 +73,7 @@ class Agent:
87
73
  self._overflow_recovery_attempted: bool = False
88
74
  self._engine.options.before_tool_call = self._before_tool_call
89
75
  self._engine.options.after_tool_call = self._after_tool_call
76
+ self._engine.options.transform_context = self._transform_context
90
77
 
91
78
  # -------------------------------------------------------------------------
92
79
  # Public interface
@@ -179,6 +166,79 @@ class Agent:
179
166
  result: ToolResult,
180
167
  signal: asyncio.Event | None,
181
168
  ) -> ToolResult | None:
169
+ """Cap oversized tool output before it enters the context window.
170
+
171
+ Hard cap on tool output size 50 KB / 2000-line
172
+ Head-truncation keeps the first N lines/bytes; a trailing marker
173
+ reports how much was omitted and the total size.
174
+ """
175
+ content = result.content
176
+ raw = content.encode("utf-8", errors="replace")
177
+ total_bytes = len(raw)
178
+ lines = content.split("\n")
179
+ total_lines = len(lines)
180
+
181
+ if total_bytes <= _TOOL_CAP_BYTES and total_lines <= _TOOL_CAP_LINES:
182
+ return result
183
+
184
+ # Cap individual lines that would consume the entire budget on their own
185
+ # (e.g. minified JS). Truncate each line to _TOOL_LINE_CAP_BYTES.
186
+ capped_lines: list[str] = []
187
+ for line in lines:
188
+ lb = len(line.encode("utf-8", errors="replace"))
189
+ if lb > _TOOL_LINE_CAP_BYTES:
190
+ buf = line.encode("utf-8", errors="replace")[:_TOOL_LINE_CAP_BYTES]
191
+ # Walk back to a valid UTF-8 boundary
192
+ while buf and (buf[-1] & 0xC0) == 0x80:
193
+ buf = buf[:-1]
194
+ capped_lines.append(buf.decode("utf-8", errors="replace") + f" …[line truncated: {_fmt_size(lb)} → {_fmt_size(_TOOL_LINE_CAP_BYTES)}]")
195
+ else:
196
+ capped_lines.append(line)
197
+ lines = capped_lines
198
+
199
+ kept: list[str] = []
200
+ byte_count = 0
201
+ for i, line in enumerate(lines):
202
+ if i >= _TOOL_CAP_LINES:
203
+ break
204
+ enc = len(line.encode("utf-8", errors="replace")) + (1 if i > 0 else 0)
205
+ if byte_count + enc > _TOOL_CAP_BYTES:
206
+ break
207
+ kept.append(line)
208
+ byte_count += enc
209
+
210
+ omitted = total_bytes - byte_count
211
+ kept.append(
212
+ f"[truncated: {_fmt_size(omitted)} omitted"
213
+ f" — {_fmt_size(total_bytes)} total, showing first {len(kept)} lines / {_fmt_size(byte_count)}]"
214
+ )
215
+ return ToolResult(
216
+ id=result.id,
217
+ content="\n".join(kept),
218
+ is_error=result.is_error,
219
+ metadata=result.metadata,
220
+ terminate=result.terminate,
221
+ terminate_message=result.terminate_message,
222
+ )
223
+
224
+ async def _transform_context(
225
+ self,
226
+ messages: list[LLMMessage],
227
+ signal: asyncio.Event | None,
228
+ ) -> list[LLMMessage]:
229
+ """Called before every LLM inference in the engine loop.
230
+
231
+ Runs a compaction check so it can fire between tool iterations
232
+ (not only at invoke() boundaries), then rebuilds the message list
233
+ from the current session so the engine always sees up-to-date
234
+ compacted history.
235
+ """
236
+ threshold_stop = await self._check_compaction()
237
+ session_ctx = self._session_manager.build_session_context()
238
+ llm_messages = _to_llm_messages(session_ctx.messages)
239
+ result = strip_unusable_trailing_assistant(llm_messages, self._session_manager)
240
+ if threshold_stop:
241
+ raise _ThresholdCompactionStop()
182
242
  return result
183
243
 
184
244
  # -------------------------------------------------------------------------
@@ -225,7 +285,8 @@ class Agent:
225
285
  if preparation is None:
226
286
  return False
227
287
  await self._apply_compaction(
228
- preparation, entries, manual=True, custom_instructions=custom_instructions
288
+ preparation, entries, manual=True, custom_instructions=custom_instructions,
289
+ reason=_CompactionReason.Manual,
229
290
  )
230
291
  return True
231
292
 
@@ -235,12 +296,15 @@ class Agent:
235
296
  entries: list,
236
297
  manual: bool,
237
298
  custom_instructions: str | None = None,
299
+ reason: _CompactionReason = _CompactionReason.Manual,
238
300
  ) -> None:
239
301
  """Run a prepared compaction, persist the summary, and emit the end event."""
240
302
  from tau.hooks.engine import CompactionEndEvent
241
303
 
304
+ will_retry = reason == _CompactionReason.Overflow
242
305
  result, from_extension = await self._run_compaction(
243
- preparation, entries, manual=manual, custom_instructions=custom_instructions
306
+ preparation, entries, manual=manual, custom_instructions=custom_instructions,
307
+ reason=reason, will_retry=will_retry,
244
308
  )
245
309
  self._session_manager.append_compaction(
246
310
  summary=result.summary,
@@ -254,32 +318,40 @@ class Agent:
254
318
  tokens_before=result.tokens_before,
255
319
  summary_length=len(result.summary),
256
320
  from_extension=from_extension,
321
+ reason=reason,
322
+ will_retry=will_retry,
257
323
  )
258
324
  )
259
325
 
260
- def _latest_compaction_timestamp(self) -> float | None:
261
- """Timestamp of the most recent compaction in the active branch, if any."""
262
- from tau.session.types import CompactionEntry
326
+ def _latest_model_change_timestamp(self) -> float | None:
327
+ """Timestamp of the most recent model-change entry in the active branch, if any."""
328
+ from tau.session.types import ModelChangeEntry
263
329
 
264
330
  for entry in reversed(self._session_manager.get_branch()):
265
- if isinstance(entry, CompactionEntry):
331
+ if isinstance(entry, ModelChangeEntry):
266
332
  return entry.timestamp
267
333
  return None
268
334
 
269
- async def _check_compaction(self) -> None:
270
- """Auto-compact if context usage exceeds the threshold. Circuit-breaks after 3 failures."""
335
+ async def _check_compaction(self) -> bool:
336
+ """Auto-compact if context usage exceeds the threshold. Circuit-breaks after 3 failures.
337
+
338
+ Returns True if threshold compaction ran (caller should stop the current turn),
339
+ False otherwise (overflow-forced compaction or no compaction needed).
340
+ """
271
341
  from tau.session.compaction import (
272
342
  estimate_context_tokens,
343
+ is_silent_overflow,
344
+ latest_compaction_timestamp,
273
345
  prepare_compaction,
274
346
  should_compact,
275
347
  )
276
348
 
277
349
  if self._compaction_failures >= 3:
278
- return
350
+ return False
279
351
 
280
352
  settings = self._config.compaction
281
353
  if not settings.enabled:
282
- return
354
+ return False
283
355
 
284
356
  entries = self._session_manager.get_branch()
285
357
  session_ctx = self._session_manager.build_session_context()
@@ -292,48 +364,46 @@ class Agent:
292
364
  # (Xiaomi MiMo) instead of erroring. The threshold check can miss these, so
293
365
  # force compaction when the last response shows the symptom.
294
366
  last = self._session_manager.find_last_assistant_message()
295
- forced = last is not None and self._is_silent_overflow(last)
367
+
368
+ # Model-switch guard: if the last assistant message is older than the most recent
369
+ # model change, it came from a different model. Treating its usage/overflow data as
370
+ # a signal for the new model is unreliable (context windows differ), so skip.
371
+ model_change_ts = self._latest_model_change_timestamp()
372
+ if model_change_ts is not None and last is not None:
373
+ if last.timestamp <= model_change_ts:
374
+ return False
375
+
376
+ forced = last is not None and is_silent_overflow(last, self._context_window)
296
377
 
297
378
  if not forced:
298
379
  if not should_compact(usage.tokens, self._context_window, settings):
299
- return
380
+ return False
300
381
  # Stale-anchor guard: right after a compaction the kept messages still carry
301
382
  # pre-compaction usage on their anchor, which would re-trigger compaction every
302
383
  # turn. Skip if the usage anchor predates the latest compaction boundary.
303
384
  if usage.last_usage_index is not None:
304
385
  anchor = llm_messages[usage.last_usage_index]
305
- comp_ts = self._latest_compaction_timestamp()
386
+ comp_ts = latest_compaction_timestamp(entries)
306
387
  if comp_ts is not None and getattr(anchor, "timestamp", 0.0) <= comp_ts:
307
- return
388
+ return False
308
389
 
309
390
  preparation = prepare_compaction(entries, settings)
310
391
  if preparation is None:
311
- return
392
+ return False
312
393
 
313
394
  try:
314
- await self._apply_compaction(preparation, entries, manual=False)
395
+ await self._apply_compaction(
396
+ preparation, entries, manual=False,
397
+ reason=_CompactionReason.Overflow if forced else _CompactionReason.Threshold,
398
+ )
399
+ # Threshold compaction: caller should stop the turn; user resumes manually.
400
+ # Forced (silent overflow) compaction: caller should continue — the LLM
401
+ # never got a usable response, so there's nothing for the user to resume from.
402
+ return not forced
315
403
  except Exception:
316
404
  self._compaction_failures += 1
317
-
318
- def _is_silent_overflow(self, message: AssistantMessage) -> bool:
319
- """Detect overflow on a *successful* response (no error was raised).
320
-
321
- - Silent (z.ai): a normal stop whose input tokens exceed the window.
322
- - Length-stop (Xiaomi MiMo): server truncated the input to fill the window,
323
- leaving no room to generate, so it stops with zero output.
324
- """
325
- from tau.inference.types import StopReason
326
-
327
- cw = self._context_window
328
- if cw <= 0:
405
+ _log.exception("Auto-compaction failed")
329
406
  return False
330
- u = message.usage
331
- inp = u.input_tokens + u.cache_read_tokens
332
- if message.stop_reason == StopReason.Stop and inp > cw:
333
- return True
334
- return bool(
335
- message.stop_reason == StopReason.Length and u.output_tokens == 0 and inp >= cw * 0.99
336
- )
337
407
 
338
408
  async def _try_overflow_recovery(self) -> bool:
339
409
  """If the last turn died with a context-overflow error, compact once and signal a retry.
@@ -349,6 +419,13 @@ class Agent:
349
419
  if last is None or last.error_kind != ErrorKind.CONTEXT_OVERFLOW:
350
420
  return False
351
421
 
422
+ # Model-switch guard: the overflow error is from a different model if it predates
423
+ # the most recent model-change entry. Skip recovery — the new model may handle the
424
+ # context fine, and compacting based on a stale signal wastes history.
425
+ model_change_ts = self._latest_model_change_timestamp()
426
+ if model_change_ts is not None and last.timestamp <= model_change_ts:
427
+ return False
428
+
352
429
  if self._overflow_recovery_attempted:
353
430
  self._notify(
354
431
  "Context overflow recovery failed after compaction. "
@@ -366,9 +443,10 @@ class Agent:
366
443
  if preparation is None:
367
444
  return False
368
445
  try:
369
- await self._apply_compaction(preparation, entries, manual=False)
446
+ await self._apply_compaction(preparation, entries, manual=False, reason=_CompactionReason.Overflow)
370
447
  except Exception:
371
448
  self._compaction_failures += 1
449
+ _log.exception("Overflow-triggered compaction failed")
372
450
  return False
373
451
  return True
374
452
 
@@ -388,6 +466,8 @@ class Agent:
388
466
  entries: list,
389
467
  manual: bool,
390
468
  custom_instructions: str | None = None,
469
+ reason: _CompactionReason = _CompactionReason.Manual,
470
+ will_retry: bool = False,
391
471
  ) -> tuple:
392
472
  """Emit before_compaction (allowing interception), then run the default algorithm.
393
473
 
@@ -408,6 +488,8 @@ class Agent:
408
488
  preparation=preparation,
409
489
  entries=entries,
410
490
  manual=manual,
491
+ reason=reason,
492
+ will_retry=will_retry,
411
493
  )
412
494
  )
413
495
 
@@ -419,7 +501,7 @@ class Agent:
419
501
  if res.compaction is not None:
420
502
  return res.compaction, True
421
503
 
422
- await self.hooks.emit(CompactionStartEvent(manual=manual))
504
+ await self.hooks.emit(CompactionStartEvent(manual=manual, reason=reason, will_retry=will_retry))
423
505
  result = await _compact(
424
506
  preparation, self._engine.llm, custom_instructions=custom_instructions
425
507
  ) # type: ignore[arg-type]
@@ -438,10 +520,6 @@ class Agent:
438
520
 
439
521
  opts = options or PromptOptions()
440
522
 
441
- # Pre-flight: a resumed or already-oversized session can exceed the window on the
442
- # very first send. Compact before appending and shipping the new turn.
443
- await self._check_compaction()
444
-
445
523
  user_message = UserMessage.with_media(
446
524
  text,
447
525
  list(opts.images) if opts.images else None,
@@ -2,6 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import builtins
4
4
  import json
5
+ import logging
5
6
  import os
6
7
  from pathlib import Path
7
8
 
@@ -19,6 +20,8 @@ from tau.inference.provider.registry import ProviderRegistry
19
20
  from tau.settings.paths import get_auth_path
20
21
  from tau.utils.secrets import resolve_secret
21
22
 
23
+ _log = logging.getLogger(__name__)
24
+
22
25
 
23
26
  def _get_env_api_key(provider: str) -> str | None:
24
27
  """Get API key for a provider from environment variables."""
@@ -79,12 +82,12 @@ class AuthManager:
79
82
  return AuthManager(registry, storage)
80
83
 
81
84
  @staticmethod
82
- def in_memory(registry: ProviderRegistry, initial: dict = None) -> AuthManager:
85
+ def in_memory(registry: ProviderRegistry, initial: dict | None = None) -> AuthManager:
83
86
  """Create AuthManager with in-memory storage for testing."""
84
87
  if initial is None:
85
88
  initial = {}
86
89
  storage = InMemoryAuthStorage()
87
- storage.with_lock(lambda _: LockResult(result=None, next=json.dumps(initial, indent=2)))
90
+ storage.with_lock(lambda _: LockResult(result=initial, next=json.dumps(initial, indent=2))) # type: ignore[arg-type]
88
91
  return AuthManager.from_storage(registry, storage)
89
92
 
90
93
  def _record_error(self, error: Exception) -> None:
@@ -274,6 +277,7 @@ class AuthManager:
274
277
  result=refreshed_credential, next=json.dumps(serialized, indent=2)
275
278
  )
276
279
  except Exception as e:
280
+ _log.error("oauth token refresh failed for %s: %s", provider, e, exc_info=True)
277
281
  self._record_error(e)
278
282
  return LockResult(result=None)
279
283