tau-coding-agent 0.2.0__tar.gz → 0.3.1__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.
- {tau_coding_agent-0.2.0/tau_coding_agent.egg-info → tau_coding_agent-0.3.1}/PKG-INFO +3 -2
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/architecture.md +1 -1
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/extensions.md +3 -2
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/sessions.md +16 -4
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/themes.md +32 -1
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/pyproject.toml +4 -3
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/agent/service.py +143 -42
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/auth/manager.py +82 -0
- tau_coding_agent-0.3.1/tau/builtins/themes/dark.yaml +50 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/themes/light.yaml +3 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/console/cli.py +3 -5
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/engine/service.py +2 -1
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/extensions/context.py +13 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/service.py +55 -8
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/types.py +3 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/message/types.py +38 -4
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/session/manager.py +8 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/themes/loader.py +78 -8
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/agent_hooks.py +18 -5
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/app.py +1 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/autocomplete_picker.py +3 -4
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/command_palette.py +3 -4
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/file_picker.py +3 -4
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/layout.py +26 -6
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/message_list.py +15 -9
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/spinner.py +47 -11
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/text_input.py +209 -52
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/input.py +164 -25
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/input_handler.py +138 -23
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/keybindings.py +6 -3
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/markdown.py +59 -4
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/overlay.py +1 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/theme.py +3 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/tui.py +6 -10
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1/tau_coding_agent.egg-info}/PKG-INFO +3 -2
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau_coding_agent.egg-info/requires.txt +1 -0
- tau_coding_agent-0.2.0/tau/builtins/themes/dark.yaml +0 -1
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/LICENSE +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/MANIFEST.in +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/README.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/IMPLEMENTATION_SUMMARY.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/auth.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/cli-reference.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/development.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/docs.json +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/extension-settings.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/http-proxy.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/index.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/inference-providers.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/installation.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/keybindings.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/messages.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/project-context.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/project-structure.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/prompts.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/python-api.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/quickstart.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/settings.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/skills.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/tools.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/docs/usage.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/setup.cfg +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/agent/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/agent/prompt/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/agent/prompt/builder.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/agent/prompt/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/agent/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/auth/storage.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/auth/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/__pycache__/__init__.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/__pycache__/__init__.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/__pycache__/__init__.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/__pycache__/__init__.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/__pycache__/clear.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/__pycache__/clear.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/__pycache__/compact.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/__pycache__/compact.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/__pycache__/reload.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/__pycache__/reload.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/__pycache__/session.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/__pycache__/session.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/clear.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/compact.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/reload.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/commands/session.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/extensions/footer/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/extensions/footer/__pycache__/__init__.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/extensions/footer/__pycache__/git.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/extensions/footer/__pycache__/model.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/extensions/footer/__pycache__/utils.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/extensions/footer/git.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/extensions/footer/model.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/extensions/footer/utils.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/extensions/header/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/extensions/header/__pycache__/__init__.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/models/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/models/__pycache__/__init__.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/models/__pycache__/text.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/models/audio.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/models/image.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/models/text.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/models/video.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/prompts/commit.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/prompts/docs.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/prompts/explain.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/prompts/fix.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/prompts/refactor.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/prompts/review.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/prompts/test.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/providers/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/providers/__pycache__/__init__.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/providers/__pycache__/text.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/providers/audio.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/providers/image.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/providers/text.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/providers/video.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/skills/code-review/SKILL.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/skills/debug/SKILL.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/skills/git-commit/SKILL.md +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/__init__.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/__init__.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/bash.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/bash.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/edit.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/edit.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/glob.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/glob.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/grep.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/grep.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/ls.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/ls.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/read.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/read.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/terminal.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/terminal.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/write.cpython-313.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/__pycache__/write.cpython-314.pyc +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/edit.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/glob.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/grep.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/ls.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/read.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/terminal.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/builtins/tools/write.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/commands/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/commands/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/commands/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/console/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/console/commands/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/console/commands/auth.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/console/commands/packages.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/console/commands/update.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/core/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/core/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/engine/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/engine/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/extensions/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/extensions/api.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/extensions/events.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/extensions/loader.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/extensions/runtime.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/extensions/settings.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/hooks/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/hooks/engine.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/hooks/inference.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/hooks/runtime.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/hooks/service.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/hooks/session.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/hooks/tui.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/hooks/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/audio/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/audio/base.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/audio/builtins.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/audio/elevenlabs_audio.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/audio/gemini_audio.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/audio/openai_audio.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/audio/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/audio/sarvam_audio.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/audio/service.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/audio/utils.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/image/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/image/base.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/image/builtins.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/image/gemini_image.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/image/openai_image.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/image/openrouter.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/image/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/image/service.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/anthropic_claude_code.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/anthropic_messages.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/base.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/builtins.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/gemini_generate.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/github_copilot_chat.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/google_antigravity.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/mistral_chat.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/ollama_chat.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/openai_codex_responses.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/openai_completions.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/openai_responses.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/text/utils.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/video/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/video/base.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/video/builtins.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/video/fal_video.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/video/openrouter_video.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/video/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/api/video/service.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/model/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/model/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/model/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/provider/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/provider/oauth/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/provider/oauth/anthropic_claude_code.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/provider/oauth/github_copilot.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/provider/oauth/google_antigravity.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/provider/oauth/openai_codex.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/provider/oauth/pkce.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/provider/oauth/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/provider/oauth/utils.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/provider/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/provider/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/inference/utils.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/message/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/message/utils.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/packages/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/packages/manager.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/packages/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/packages/utils.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/prompts/expand.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/prompts/loader.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/prompts/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/prompts/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/rpc/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/rpc/mode.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/rpc/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/runtime/service.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/runtime/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/session/branch_summarization.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/session/compaction.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/session/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/session/utils.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/settings/manager.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/settings/paths.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/settings/storage.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/settings/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/settings/utils.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/skills/loader.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/skills/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/skills/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/themes/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/themes/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tool/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tool/registry.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tool/render.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tool/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/trust/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/trust/manager.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/trust/types.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/trust/utils.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/ansi.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/autocomplete.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/capabilities.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/commands/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/commands/appearance.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/commands/auth.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/commands/context.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/commands/misc.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/commands/model.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/commands/session.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/component.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/autocomplete_manager.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/box.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/dynamic_border.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/image.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/inline_selector.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/modal.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/model_palette.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/picker_overlay.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/prompt_overlay.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/resume_modal.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/select_list.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/settings_modal.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/settings_schema.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/text_prompt.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/tree_select_list.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/components/trust_screen.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/diff.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/fuzzy.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/message_renderers.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/renderer.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/terminal.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/ui_context.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/tui/utils.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/utils/__init__.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/utils/http_proxy.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/utils/image_processing.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/utils/secrets.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau/utils/version_check.py +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau_coding_agent.egg-info/SOURCES.txt +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau_coding_agent.egg-info/dependency_links.txt +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau_coding_agent.egg-info/entry_points.txt +0 -0
- {tau_coding_agent-0.2.0 → tau_coding_agent-0.3.1}/tau_coding_agent.egg-info/top_level.txt +0 -0
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tau-coding-agent
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.1
|
|
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
|
-
Requires-Python:
|
|
5
|
+
Requires-Python: >=3.12
|
|
6
6
|
Description-Content-Type: text/markdown
|
|
7
7
|
License-File: LICENSE
|
|
8
8
|
Requires-Dist: anthropic==0.109.1
|
|
@@ -25,6 +25,7 @@ Requires-Dist: pyyaml==6.0.2
|
|
|
25
25
|
Requires-Dist: pygments==2.20.0
|
|
26
26
|
Requires-Dist: pathspec==1.1.1
|
|
27
27
|
Requires-Dist: gitpython==3.1.50
|
|
28
|
+
Requires-Dist: grapheme==0.6.0
|
|
28
29
|
Dynamic: license-file
|
|
29
30
|
|
|
30
31
|
# Tau (τ)
|
|
@@ -161,7 +161,7 @@ Before each inference call, the runtime builds the context:
|
|
|
161
161
|
8. Count tokens
|
|
162
162
|
```
|
|
163
163
|
|
|
164
|
-
|
|
164
|
+
Automatic compaction summarizes older messages when context approaches the limit. It is checked before sending a turn (pre-flight) and after each turn, and — as a reactive backstop — a request that still fails with a provider context-overflow error triggers a compact-and-retry (bounded to one attempt). See [Context Compaction](sessions.md#context-compaction).
|
|
165
165
|
|
|
166
166
|
## Hook & Event System
|
|
167
167
|
|
|
@@ -200,6 +200,7 @@ def register(tau):
|
|
|
200
200
|
| `ctx.cwd` | `Path` | Working directory |
|
|
201
201
|
| `ctx.model_id` | `str` | Active model, e.g. `"claude-sonnet-4-6"` |
|
|
202
202
|
| `ctx.provider_id` | `str` | Active provider, e.g. `"anthropic"` |
|
|
203
|
+
| `ctx.llm` | `TextLLM \| None` | Active text LLM for running your own model calls (`await ctx.llm.invoke(LLMContext(...))`); `None` outside a live session |
|
|
203
204
|
| `ctx.settings` | `SettingsManager \| None` | Full settings access |
|
|
204
205
|
| `ctx.mode` | `str` | `"tui"` when running in the interactive terminal, `"headless"` otherwise |
|
|
205
206
|
| `ctx.has_ui` | `bool` | True when dialog-capable UI is available — guards TUI-only calls |
|
|
@@ -459,7 +460,7 @@ the default algorithm runs.
|
|
|
459
460
|
### Example — use a different model for summarisation
|
|
460
461
|
|
|
461
462
|
```python
|
|
462
|
-
from tau.hooks
|
|
463
|
+
from tau.hooks import BeforeCompactionResult
|
|
463
464
|
from tau.session.compaction import CompactionResult
|
|
464
465
|
|
|
465
466
|
def register(tau):
|
|
@@ -489,7 +490,7 @@ def register(tau):
|
|
|
489
490
|
### Example — block automatic compaction
|
|
490
491
|
|
|
491
492
|
```python
|
|
492
|
-
from tau.hooks
|
|
493
|
+
from tau.hooks import BeforeCompactionResult
|
|
493
494
|
|
|
494
495
|
def register(tau):
|
|
495
496
|
@tau.on("before_compaction")
|
|
@@ -246,10 +246,22 @@ Long sessions eventually fill the model's context window. Tau handles this autom
|
|
|
246
246
|
|
|
247
247
|
### How It Works
|
|
248
248
|
|
|
249
|
-
1. **
|
|
250
|
-
2. **
|
|
251
|
-
3. **
|
|
252
|
-
|
|
249
|
+
1. **Cut-point detection** — Tau walks backwards from the most recent message, accumulating token estimates, until it has identified the `keep_recent_tokens` worth of messages to preserve. It never cuts in the middle of a tool call/result pair; if the cut would land inside a turn, the turn's prefix is summarised separately.
|
|
250
|
+
2. **Summarisation** — the messages before the cut point are sent to the model with a structured summarisation prompt (Goal / Progress / Decisions / Next Steps / Critical Context). The resulting summary is stored in the session file as a `compaction` entry and prepended to the context (wrapped in `<context-summary>` tags) on the next turn.
|
|
251
|
+
3. **Iterative merging** — if compaction has happened before, the new summary prompt includes the previous summary so history is never lost.
|
|
252
|
+
|
|
253
|
+
### When Compaction Runs
|
|
254
|
+
|
|
255
|
+
Token usage is estimated from the **last successful response's reported usage** plus a chars/4 estimate of anything after it, so the trigger reflects real provider accounting rather than a pure guess. The threshold is `context_tokens > context_window - reserve_tokens`. Tau checks this at three points so context is trimmed before it can overflow:
|
|
256
|
+
|
|
257
|
+
1. **Pre-flight** — before sending a new turn. Catches resumed or already-oversized sessions that would otherwise fail on the very first request.
|
|
258
|
+
2. **Post-turn** — after each agent turn completes, the normal proactive path.
|
|
259
|
+
3. **Overflow recovery (reactive backstop)** — if a request still fails with a provider *context-overflow* error, Tau catches it, drops the failed response, compacts, and **retries the turn once** automatically. This is bounded to a single attempt per turn — if it overflows again, Tau surfaces a message asking you to reduce context or switch to a larger-context model rather than looping.
|
|
260
|
+
|
|
261
|
+
Two guards keep this stable:
|
|
262
|
+
|
|
263
|
+
- **Stale-anchor guard** — immediately after a compaction, the kept messages still carry their pre-compaction (large) usage numbers. Tau skips re-triggering when the usage anchor predates the latest compaction, so it won't compact on every subsequent turn.
|
|
264
|
+
- **Circuit breaker** — if automatic compaction fails repeatedly (3×), Tau stops auto-compacting for the session and surfaces a notice instead of failing silently. You can still run `/compact` manually.
|
|
253
265
|
|
|
254
266
|
### Manual Compaction
|
|
255
267
|
|
|
@@ -73,6 +73,34 @@ The `name` field in the file determines the theme name used in settings and `--t
|
|
|
73
73
|
|
|
74
74
|
> **Formats**: `.yaml` and `.yml` are recommended. `.json` is also accepted for backwards compatibility.
|
|
75
75
|
|
|
76
|
+
### Color values
|
|
77
|
+
|
|
78
|
+
Every color token accepts three forms, and you can mix them freely in one theme:
|
|
79
|
+
|
|
80
|
+
| Form | Example | Renders as |
|
|
81
|
+
|------|---------|------------|
|
|
82
|
+
| **Hex** (24-bit truecolor) | `"#a78bfa"` | exact RGB, identical on every terminal |
|
|
83
|
+
| **Named ANSI** | `bright_cyan` | the terminal's own palette color (adapts to the user's terminal theme) |
|
|
84
|
+
| **With attributes** | `{ color: "#a78bfa", bold: true, italic: true, dim: true }` | either hex or named, plus styling |
|
|
85
|
+
|
|
86
|
+
Valid names: `black`, `red`, `green`, `yellow`, `blue`, `magenta`, `cyan`, `white`, `default`, and their `bright_` variants (e.g. `bright_black`).
|
|
87
|
+
|
|
88
|
+
**Which to use?**
|
|
89
|
+
- **Named ANSI** for a theme that should *blend into the user's terminal* (the built-in `dark` theme uses these, so its colors match whatever palette the user has set). Best for a default/adaptive theme.
|
|
90
|
+
- **Hex** for a theme with an *exact, branded look* that should appear the same on every machine (the built-in `light` theme uses hex). Best for a distinctive, designed theme.
|
|
91
|
+
|
|
92
|
+
An unrecognized value (a typo, or malformed hex like `#fff`) silently falls back to that token's built-in default rather than erroring. Hex must be full `#rrggbb`.
|
|
93
|
+
|
|
94
|
+
### Syntax highlighting
|
|
95
|
+
|
|
96
|
+
Fenced code blocks are syntax-highlighted with [Pygments](https://pygments.org/styles/). Choose the style with a top-level `code_syntax_style` key:
|
|
97
|
+
|
|
98
|
+
```yaml
|
|
99
|
+
code_syntax_style: monokai # any Pygments style name; "" disables highlighting
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Pick a dark style (`monokai`, `dracula`, `nord`, `gruvbox-dark`, …) for dark themes and a light style (`friendly`, `default`, `xcode`, `solarized-light`, …) for light backgrounds. Setting it to `""` falls back to the flat `code_block` color.
|
|
103
|
+
|
|
76
104
|
### Theme YAML format
|
|
77
105
|
|
|
78
106
|
```yaml
|
|
@@ -82,8 +110,11 @@ name: my_theme
|
|
|
82
110
|
show_thinking: true # show/hide the model's thinking blocks
|
|
83
111
|
show_tool_calls: true # show/hide tool call output
|
|
84
112
|
|
|
113
|
+
# Syntax highlighting for fenced code blocks (Pygments style; "" to disable)
|
|
114
|
+
code_syntax_style: monokai
|
|
115
|
+
|
|
85
116
|
colors:
|
|
86
|
-
# UI chrome
|
|
117
|
+
# UI chrome — hex for exact colors, or names like `bright_black` to use the terminal palette
|
|
87
118
|
divider: "#374151"
|
|
88
119
|
spinner_frame: "#0ea5e9"
|
|
89
120
|
spinner_label: "#6b7280"
|
|
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tau-coding-agent"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.1"
|
|
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
|
-
requires-python = "
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
11
|
dependencies = [
|
|
12
12
|
"anthropic==0.109.1",
|
|
13
13
|
"certifi==2026.5.20",
|
|
@@ -29,6 +29,7 @@ dependencies = [
|
|
|
29
29
|
"pygments==2.20.0",
|
|
30
30
|
"pathspec==1.1.1",
|
|
31
31
|
"gitpython==3.1.50",
|
|
32
|
+
"grapheme==0.6.0",
|
|
32
33
|
]
|
|
33
34
|
|
|
34
35
|
[project.scripts]
|
|
@@ -40,7 +41,7 @@ tau = "tau.console.cli:main"
|
|
|
40
41
|
resolution = "highest"
|
|
41
42
|
|
|
42
43
|
[tool.ruff]
|
|
43
|
-
target-version = "
|
|
44
|
+
target-version = "py312"
|
|
44
45
|
line-length = 100
|
|
45
46
|
|
|
46
47
|
[tool.ruff.lint]
|
|
@@ -77,6 +77,7 @@ class Agent:
|
|
|
77
77
|
self._phase: AgentPhase = AgentPhase.IDLE
|
|
78
78
|
self._signal: asyncio.Event = asyncio.Event()
|
|
79
79
|
self._compaction_failures: int = 0
|
|
80
|
+
self._overflow_recovery_attempted: bool = False
|
|
80
81
|
self._engine.options.before_tool_call = self._before_tool_call
|
|
81
82
|
self._engine.options.after_tool_call = self._after_tool_call
|
|
82
83
|
|
|
@@ -208,12 +209,25 @@ class Agent:
|
|
|
208
209
|
async def compact(self, custom_instructions: str | None = None) -> bool:
|
|
209
210
|
"""Manually trigger context compaction. Returns True if compaction ran."""
|
|
210
211
|
from tau.session.compaction import prepare_compaction
|
|
211
|
-
from tau.hooks.engine import CompactionEndEvent
|
|
212
212
|
entries = self._session_manager.get_branch()
|
|
213
213
|
preparation = prepare_compaction(entries, self._config.compaction)
|
|
214
214
|
if preparation is None:
|
|
215
215
|
return False
|
|
216
|
-
|
|
216
|
+
await self._apply_compaction(preparation, entries, manual=True, custom_instructions=custom_instructions)
|
|
217
|
+
return True
|
|
218
|
+
|
|
219
|
+
async def _apply_compaction(
|
|
220
|
+
self,
|
|
221
|
+
preparation: "CompactionPreparation",
|
|
222
|
+
entries: list,
|
|
223
|
+
manual: bool,
|
|
224
|
+
custom_instructions: str | None = None,
|
|
225
|
+
) -> None:
|
|
226
|
+
"""Run a prepared compaction, persist the summary, and emit the end event."""
|
|
227
|
+
from tau.hooks.engine import CompactionEndEvent
|
|
228
|
+
result, from_extension = await self._run_compaction(
|
|
229
|
+
preparation, entries, manual=manual, custom_instructions=custom_instructions
|
|
230
|
+
)
|
|
217
231
|
self._session_manager.append_compaction(
|
|
218
232
|
summary=result.summary,
|
|
219
233
|
first_kept_entry_id=result.first_kept_entry_id,
|
|
@@ -221,12 +235,19 @@ class Agent:
|
|
|
221
235
|
)
|
|
222
236
|
self._compaction_failures = 0
|
|
223
237
|
await self.hooks.emit(CompactionEndEvent(
|
|
224
|
-
manual=
|
|
238
|
+
manual=manual,
|
|
225
239
|
tokens_before=result.tokens_before,
|
|
226
240
|
summary_length=len(result.summary),
|
|
227
241
|
from_extension=from_extension,
|
|
228
242
|
))
|
|
229
|
-
|
|
243
|
+
|
|
244
|
+
def _latest_compaction_timestamp(self) -> float | None:
|
|
245
|
+
"""Timestamp of the most recent compaction in the active branch, if any."""
|
|
246
|
+
from tau.session.types import CompactionEntry
|
|
247
|
+
for entry in reversed(self._session_manager.get_branch()):
|
|
248
|
+
if isinstance(entry, CompactionEntry):
|
|
249
|
+
return entry.timestamp
|
|
250
|
+
return None
|
|
230
251
|
|
|
231
252
|
async def _check_compaction(self) -> None:
|
|
232
253
|
"""Auto-compact if context usage exceeds the threshold. Circuit-breaks after 3 failures."""
|
|
@@ -234,7 +255,6 @@ class Agent:
|
|
|
234
255
|
estimate_context_tokens, should_compact,
|
|
235
256
|
prepare_compaction,
|
|
236
257
|
)
|
|
237
|
-
from tau.hooks.engine import CompactionEndEvent
|
|
238
258
|
|
|
239
259
|
if self._compaction_failures >= 3:
|
|
240
260
|
return
|
|
@@ -248,29 +268,99 @@ class Agent:
|
|
|
248
268
|
llm_messages = _to_llm_messages(session_ctx.messages)
|
|
249
269
|
|
|
250
270
|
usage = estimate_context_tokens(llm_messages)
|
|
251
|
-
|
|
252
|
-
|
|
271
|
+
|
|
272
|
+
# "Silent" overflow: some providers accept an over-limit prompt and return a
|
|
273
|
+
# successful response (z.ai) or truncate the input and stop with no output
|
|
274
|
+
# (Xiaomi MiMo) instead of erroring. The threshold check can miss these, so
|
|
275
|
+
# force compaction when the last response shows the symptom.
|
|
276
|
+
last = self._session_manager.find_last_assistant_message()
|
|
277
|
+
forced = last is not None and self._is_silent_overflow(last)
|
|
278
|
+
|
|
279
|
+
if not forced:
|
|
280
|
+
if not should_compact(usage.tokens, self._context_window, settings):
|
|
281
|
+
return
|
|
282
|
+
# Stale-anchor guard: right after a compaction the kept messages still carry
|
|
283
|
+
# pre-compaction usage on their anchor, which would re-trigger compaction every
|
|
284
|
+
# turn. Skip if the usage anchor predates the latest compaction boundary.
|
|
285
|
+
if usage.last_usage_index is not None:
|
|
286
|
+
anchor = llm_messages[usage.last_usage_index]
|
|
287
|
+
comp_ts = self._latest_compaction_timestamp()
|
|
288
|
+
if comp_ts is not None and getattr(anchor, "timestamp", 0.0) <= comp_ts:
|
|
289
|
+
return
|
|
253
290
|
|
|
254
291
|
preparation = prepare_compaction(entries, settings)
|
|
255
292
|
if preparation is None:
|
|
256
293
|
return
|
|
257
294
|
|
|
258
295
|
try:
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
296
|
+
await self._apply_compaction(preparation, entries, manual=False)
|
|
297
|
+
except Exception:
|
|
298
|
+
self._compaction_failures += 1
|
|
299
|
+
|
|
300
|
+
def _is_silent_overflow(self, message: AssistantMessage) -> bool:
|
|
301
|
+
"""Detect overflow on a *successful* response (no error was raised).
|
|
302
|
+
|
|
303
|
+
- Silent (z.ai): a normal stop whose input tokens exceed the window.
|
|
304
|
+
- Length-stop (Xiaomi MiMo): server truncated the input to fill the window,
|
|
305
|
+
leaving no room to generate, so it stops with zero output.
|
|
306
|
+
"""
|
|
307
|
+
from tau.inference.types import StopReason
|
|
308
|
+
cw = self._context_window
|
|
309
|
+
if cw <= 0:
|
|
310
|
+
return False
|
|
311
|
+
u = message.usage
|
|
312
|
+
inp = u.input_tokens + u.cache_read_tokens
|
|
313
|
+
if message.stop_reason == StopReason.Stop and inp > cw:
|
|
314
|
+
return True
|
|
315
|
+
if message.stop_reason == StopReason.Length and u.output_tokens == 0 and inp >= cw * 0.99:
|
|
316
|
+
return True
|
|
317
|
+
return False
|
|
318
|
+
|
|
319
|
+
async def _try_overflow_recovery(self) -> bool:
|
|
320
|
+
"""If the last turn died with a context-overflow error, compact once and signal a retry.
|
|
321
|
+
|
|
322
|
+
Drops the error message so it isn't kept or used as a stale anchor, compacts the
|
|
323
|
+
history, and lets the caller re-run the turn. Bounded to one attempt per turn so a
|
|
324
|
+
session that overflows even after compaction fails cleanly.
|
|
325
|
+
"""
|
|
326
|
+
from tau.inference.utils import ErrorKind
|
|
327
|
+
from tau.session.compaction import prepare_compaction
|
|
328
|
+
|
|
329
|
+
last = self._session_manager.find_last_assistant_message()
|
|
330
|
+
if last is None or last.error_kind != ErrorKind.CONTEXT_OVERFLOW:
|
|
331
|
+
return False
|
|
332
|
+
|
|
333
|
+
if self._overflow_recovery_attempted:
|
|
334
|
+
self._notify(
|
|
335
|
+
"Context overflow recovery failed after compaction. "
|
|
336
|
+
"Reduce context or switch to a larger-context model."
|
|
264
337
|
)
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
338
|
+
return False
|
|
339
|
+
self._overflow_recovery_attempted = True
|
|
340
|
+
|
|
341
|
+
# Drop the error assistant message — it has no usable content and would otherwise
|
|
342
|
+
# anchor stale usage / be re-sent on retry.
|
|
343
|
+
self._session_manager.remove_last_message()
|
|
344
|
+
|
|
345
|
+
entries = self._session_manager.get_branch()
|
|
346
|
+
preparation = prepare_compaction(entries, self._config.compaction)
|
|
347
|
+
if preparation is None:
|
|
348
|
+
return False
|
|
349
|
+
try:
|
|
350
|
+
await self._apply_compaction(preparation, entries, manual=False)
|
|
272
351
|
except Exception:
|
|
273
352
|
self._compaction_failures += 1
|
|
353
|
+
return False
|
|
354
|
+
return True
|
|
355
|
+
|
|
356
|
+
def _notify(self, message: str) -> None:
|
|
357
|
+
"""Surface a message to the UI if a runtime/UI is wired up."""
|
|
358
|
+
if self._runtime is None:
|
|
359
|
+
return
|
|
360
|
+
from tau.extensions.context import ExtensionContext
|
|
361
|
+
ctx = ExtensionContext.from_runtime(self._runtime)
|
|
362
|
+
if ctx.ui is not None:
|
|
363
|
+
ctx.ui.notify(message)
|
|
274
364
|
|
|
275
365
|
async def _run_compaction(self, preparation: "CompactionPreparation", entries: list, manual: bool, custom_instructions: str | None = None) -> tuple:
|
|
276
366
|
"""Emit before_compaction (allowing interception), then run the default algorithm.
|
|
@@ -281,7 +371,7 @@ class Agent:
|
|
|
281
371
|
consistent with error-fallthrough behaviour.
|
|
282
372
|
"""
|
|
283
373
|
from tau.session.compaction import compact as _compact
|
|
284
|
-
from tau.hooks.
|
|
374
|
+
from tau.hooks.engine import BeforeCompactionEvent, BeforeCompactionResult, CompactionStartEvent
|
|
285
375
|
|
|
286
376
|
before_results = await self.hooks.emit(BeforeCompactionEvent(
|
|
287
377
|
preparation=preparation,
|
|
@@ -312,33 +402,33 @@ class Agent:
|
|
|
312
402
|
|
|
313
403
|
opts = options or PromptOptions()
|
|
314
404
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
if opts.images:
|
|
320
|
-
user_message = UserMessage.with_images(text, list(opts.images))
|
|
321
|
-
elif opts.audio:
|
|
322
|
-
user_message = UserMessage.with_audio(text, list(opts.audio))
|
|
323
|
-
elif opts.video:
|
|
324
|
-
user_message = UserMessage.with_video(text, list(opts.video))
|
|
325
|
-
else:
|
|
326
|
-
user_message = UserMessage.from_text(text)
|
|
327
|
-
self._session_manager.append_message(user_message, meta=opts.meta)
|
|
328
|
-
llm_messages.append(user_message)
|
|
405
|
+
# Pre-flight: a resumed or already-oversized session can exceed the window on the
|
|
406
|
+
# very first send. Compact before appending and shipping the new turn.
|
|
407
|
+
await self._check_compaction()
|
|
329
408
|
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
409
|
+
user_message = UserMessage.with_media(
|
|
410
|
+
text,
|
|
411
|
+
list(opts.images) if opts.images else None,
|
|
412
|
+
list(opts.audio) if opts.audio else None,
|
|
413
|
+
list(opts.video) if opts.video else None,
|
|
334
414
|
)
|
|
415
|
+
self._session_manager.append_message(user_message, meta=opts.meta)
|
|
335
416
|
|
|
336
|
-
self.
|
|
337
|
-
self._engine.llm.api.options.signal = self._signal
|
|
338
|
-
|
|
417
|
+
self._overflow_recovery_attempted = False
|
|
339
418
|
self._phase = AgentPhase.TURN
|
|
340
419
|
try:
|
|
341
|
-
|
|
420
|
+
while True:
|
|
421
|
+
ctx = self._build_turn_context()
|
|
422
|
+
self._signal = asyncio.Event()
|
|
423
|
+
self._engine.llm.api.options.signal = self._signal
|
|
424
|
+
try:
|
|
425
|
+
await self._run(ctx)
|
|
426
|
+
break
|
|
427
|
+
except RuntimeError:
|
|
428
|
+
# On a context-overflow error, compact and retry the turn once.
|
|
429
|
+
if await self._try_overflow_recovery():
|
|
430
|
+
continue
|
|
431
|
+
raise
|
|
342
432
|
finally:
|
|
343
433
|
self._phase = AgentPhase.IDLE
|
|
344
434
|
|
|
@@ -349,6 +439,17 @@ class Agent:
|
|
|
349
439
|
if not self._engine.has_pending_messages():
|
|
350
440
|
await self.hooks.emit(SettledEvent())
|
|
351
441
|
|
|
442
|
+
def _build_turn_context(self) -> AgentContext:
|
|
443
|
+
"""Build the LLM context for a turn from the current (possibly compacted) session."""
|
|
444
|
+
session_ctx = self._session_manager.build_session_context()
|
|
445
|
+
llm_messages = _to_llm_messages(session_ctx.messages)
|
|
446
|
+
llm_messages = strip_unusable_trailing_assistant(llm_messages, self._session_manager)
|
|
447
|
+
return AgentContext(
|
|
448
|
+
system_prompt=self._system_prompt,
|
|
449
|
+
messages=llm_messages,
|
|
450
|
+
tools=self._engine.tools,
|
|
451
|
+
)
|
|
452
|
+
|
|
352
453
|
async def _run(self, ctx: AgentContext) -> None:
|
|
353
454
|
unsubscribe = self.hooks.register(
|
|
354
455
|
'message_end',
|
|
@@ -16,6 +16,28 @@ def _get_env_api_key(provider: str) -> str | None:
|
|
|
16
16
|
return os.environ.get(f"{provider.upper()}_API_KEY")
|
|
17
17
|
|
|
18
18
|
|
|
19
|
+
def _is_unrecoverable_refresh_error(error: Exception) -> bool:
|
|
20
|
+
"""Return True when a failed token refresh means the refresh token itself is
|
|
21
|
+
dead (so the user must log in again), rather than a transient network/5xx blip.
|
|
22
|
+
|
|
23
|
+
Defers to the shared inference error classifier for the cases it understands
|
|
24
|
+
(auth → unrecoverable; rate-limit/overloaded/server/timeout → transient). OAuth
|
|
25
|
+
token endpoints, however, report a dead refresh token as ``invalid_grant`` /
|
|
26
|
+
HTTP 400 — which the inference-oriented classifier leaves as UNKNOWN — and the
|
|
27
|
+
provider wrappers raise these as ``RuntimeError("Request failed (<code>): ...")``
|
|
28
|
+
without a status_code attribute, so we match those markers explicitly.
|
|
29
|
+
"""
|
|
30
|
+
from tau.inference.utils import classify_error, ErrorKind
|
|
31
|
+
|
|
32
|
+
kind = classify_error(error).kind
|
|
33
|
+
if kind in (ErrorKind.AUTH, ErrorKind.AUTH_PERMANENT):
|
|
34
|
+
return True
|
|
35
|
+
if kind in (ErrorKind.RATE_LIMIT, ErrorKind.OVERLOADED, ErrorKind.SERVER_ERROR, ErrorKind.TIMEOUT):
|
|
36
|
+
return False
|
|
37
|
+
text = str(error).lower()
|
|
38
|
+
return any(m in text for m in ("invalid_grant", "invalid_request", "invalid_token", "(400)", "(401)", "(403)"))
|
|
39
|
+
|
|
40
|
+
|
|
19
41
|
class AuthManager:
|
|
20
42
|
"""Credential storage with pluggable backends."""
|
|
21
43
|
|
|
@@ -231,6 +253,66 @@ class AuthManager:
|
|
|
231
253
|
result = await self.storage.with_lock_async(refresh_fn)
|
|
232
254
|
return result.result
|
|
233
255
|
|
|
256
|
+
def is_oauth(self, provider: str) -> bool:
|
|
257
|
+
"""Return True if the stored credential for a provider is an OAuth credential."""
|
|
258
|
+
return isinstance(self.get(provider), OAuthCredential)
|
|
259
|
+
|
|
260
|
+
async def force_refresh(self, provider: str, stale_access: str | None = None) -> OAuthCredential | None:
|
|
261
|
+
"""Force-refresh an OAuth credential whose access token was rejected (e.g. a
|
|
262
|
+
mid-request 401) even though it is not yet time-expired.
|
|
263
|
+
|
|
264
|
+
Returns the new credential on success. Returns None if the provider isn't
|
|
265
|
+
OAuth or the refresh failed; on an *unrecoverable* failure (dead refresh
|
|
266
|
+
token) the stored credential is removed so the caller can prompt re-login,
|
|
267
|
+
whereas a transient failure leaves it untouched.
|
|
268
|
+
|
|
269
|
+
``stale_access`` is the access token that was just rejected: if another
|
|
270
|
+
instance has already refreshed it under the lock, we adopt that result
|
|
271
|
+
instead of rotating the refresh token a second time.
|
|
272
|
+
"""
|
|
273
|
+
oauth_provider = self.registry.text.get_oauth_provider(provider=provider)
|
|
274
|
+
if not oauth_provider:
|
|
275
|
+
return None
|
|
276
|
+
|
|
277
|
+
async def refresh_fn(current: str | None) -> LockResult:
|
|
278
|
+
"""Refresh (unconditionally) the OAuth token in storage under the lock."""
|
|
279
|
+
current_data = self._parse_storage_data(current)
|
|
280
|
+
credential = current_data.get(provider)
|
|
281
|
+
|
|
282
|
+
if not isinstance(credential, OAuthCredential):
|
|
283
|
+
return LockResult(result=None)
|
|
284
|
+
|
|
285
|
+
# Another instance already refreshed after our token was rejected.
|
|
286
|
+
if stale_access is not None and credential.access != stale_access:
|
|
287
|
+
self.data = current_data
|
|
288
|
+
return LockResult(result=credential)
|
|
289
|
+
|
|
290
|
+
try:
|
|
291
|
+
refreshed_credential = await oauth_provider.refresh_token(credential=credential)
|
|
292
|
+
if credential.extra:
|
|
293
|
+
merged_extra = dict(credential.extra)
|
|
294
|
+
merged_extra.update(refreshed_credential.extra)
|
|
295
|
+
refreshed_credential.extra = merged_extra
|
|
296
|
+
current_data[provider] = refreshed_credential
|
|
297
|
+
self.data = current_data
|
|
298
|
+
serialized = {k: self._serialize_credential(v) for k, v in current_data.items()}
|
|
299
|
+
return LockResult(result=refreshed_credential, next=json.dumps(serialized, indent=2))
|
|
300
|
+
except Exception as e:
|
|
301
|
+
self._record_error(e)
|
|
302
|
+
if _is_unrecoverable_refresh_error(e):
|
|
303
|
+
# Refresh token is dead — drop the credential so the user is
|
|
304
|
+
# prompted to log in again rather than retrying a broken token.
|
|
305
|
+
current_data.pop(provider, None)
|
|
306
|
+
self.data = current_data
|
|
307
|
+
serialized = {k: self._serialize_credential(v) for k, v in current_data.items()}
|
|
308
|
+
return LockResult(result=None, next=json.dumps(serialized, indent=2))
|
|
309
|
+
# Transient failure — keep the credential for a later retry.
|
|
310
|
+
self.data = current_data
|
|
311
|
+
return LockResult(result=None)
|
|
312
|
+
|
|
313
|
+
result = await self.storage.with_lock_async(refresh_fn)
|
|
314
|
+
return result.result
|
|
315
|
+
|
|
234
316
|
async def login(self, provider: str, callbacks: OAuthLoginCallbacks):
|
|
235
317
|
"""Perform OAuth login flow for a provider and store the resulting credential."""
|
|
236
318
|
if oauth_provider := self.registry.text.get_oauth_provider(provider):
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
name: dark
|
|
2
|
+
|
|
3
|
+
# The default theme. Colours use named ANSI values (not hex), so they map to the
|
|
4
|
+
# terminal's own 16-colour palette and adapt to the user's terminal theme.
|
|
5
|
+
# Per-token bold/italic is applied by the loader, so only the colour is listed here.
|
|
6
|
+
# Purely structural tokens (bold/italic/strikethrough/dim/reverse, the plain
|
|
7
|
+
# "tool result", spinner label) carry no colour and inherit the code defaults.
|
|
8
|
+
|
|
9
|
+
# Pygments style for fenced code blocks (dark background).
|
|
10
|
+
code_syntax_style: monokai
|
|
11
|
+
|
|
12
|
+
colors:
|
|
13
|
+
# Chrome
|
|
14
|
+
divider: bright_black
|
|
15
|
+
|
|
16
|
+
# Spinner
|
|
17
|
+
spinner_frame: bright_cyan
|
|
18
|
+
|
|
19
|
+
# Markdown
|
|
20
|
+
heading: bright_cyan
|
|
21
|
+
code_inline: bright_yellow
|
|
22
|
+
code_block: bright_green
|
|
23
|
+
code_block_border: bright_black
|
|
24
|
+
quote_border: bright_black
|
|
25
|
+
hr: bright_black
|
|
26
|
+
list_bullet: bright_cyan
|
|
27
|
+
link_text: bright_cyan
|
|
28
|
+
link_url: bright_black
|
|
29
|
+
|
|
30
|
+
# Messages
|
|
31
|
+
you_label: bright_cyan
|
|
32
|
+
assistant_label: bright_green
|
|
33
|
+
tool_arrow: bright_yellow
|
|
34
|
+
tool_result_err: bright_red
|
|
35
|
+
error_label: bright_red
|
|
36
|
+
stream_cursor: bright_white
|
|
37
|
+
|
|
38
|
+
# Diffs
|
|
39
|
+
diff_added: bright_green
|
|
40
|
+
diff_removed: bright_red
|
|
41
|
+
diff_context: bright_black
|
|
42
|
+
diff_hunk: bright_yellow
|
|
43
|
+
|
|
44
|
+
# Select list / palette
|
|
45
|
+
selected_label: bright_white
|
|
46
|
+
selected_desc: bright_black
|
|
47
|
+
normal_label: bright_black
|
|
48
|
+
normal_desc: bright_black
|
|
49
|
+
indicator: bright_black
|
|
50
|
+
empty: bright_black
|
|
@@ -36,7 +36,6 @@ def resolve_model(model: str | None, provider: str | None) -> tuple[str | None,
|
|
|
36
36
|
|
|
37
37
|
|
|
38
38
|
@click.group(invoke_without_command=True, context_settings={"help_option_names": ["-h", "--help"]})
|
|
39
|
-
@click.argument("message", required=False, default=None)
|
|
40
39
|
@click.option("--version", "-v", is_flag=True, default=False, help="Print version and exit.")
|
|
41
40
|
@click.option("--debug", "-d", is_flag=True, default=False, help="Enable debug logging.")
|
|
42
41
|
@click.option("--cwd", "-c", default=None, metavar="PATH", help="Set the working directory.")
|
|
@@ -71,7 +70,6 @@ def resolve_model(model: str | None, provider: str | None) -> tuple[str | None,
|
|
|
71
70
|
@click.pass_context
|
|
72
71
|
def cli(
|
|
73
72
|
ctx: click.Context,
|
|
74
|
-
message: str | None,
|
|
75
73
|
version: bool,
|
|
76
74
|
debug: bool,
|
|
77
75
|
cwd: str | None,
|
|
@@ -103,7 +101,7 @@ def cli(
|
|
|
103
101
|
os.chdir(cwd)
|
|
104
102
|
|
|
105
103
|
ctx.ensure_object(dict)
|
|
106
|
-
ctx.obj["
|
|
104
|
+
ctx.obj["prompt"] = prompt
|
|
107
105
|
ctx.obj["provider"] = provider
|
|
108
106
|
ctx.obj["model"] = model
|
|
109
107
|
ctx.obj["theme"] = theme
|
|
@@ -156,9 +154,9 @@ async def _start(opts: dict) -> None:
|
|
|
156
154
|
case "interactive":
|
|
157
155
|
await _run_interactive(runtime, opts["theme"])
|
|
158
156
|
case "print":
|
|
159
|
-
await _run_print(runtime, opts["
|
|
157
|
+
await _run_print(runtime, opts["prompt"], quiet=opts.get("quiet", False))
|
|
160
158
|
case "json":
|
|
161
|
-
await _run_json(runtime, opts["
|
|
159
|
+
await _run_json(runtime, opts["prompt"], quiet=opts.get("quiet", False))
|
|
162
160
|
case "rpc":
|
|
163
161
|
from tau.rpc.mode import run_rpc_mode
|
|
164
162
|
await run_rpc_mode(runtime)
|
|
@@ -564,9 +564,10 @@ class Engine:
|
|
|
564
564
|
_streaming_thinking = None
|
|
565
565
|
else:
|
|
566
566
|
message.contents.append(thinking)
|
|
567
|
-
case ErrorEvent(reason=reason, error=error):
|
|
567
|
+
case ErrorEvent(reason=reason, error=error, kind=kind):
|
|
568
568
|
message.stop_reason = reason
|
|
569
569
|
message.error = error
|
|
570
|
+
message.error_kind = kind
|
|
570
571
|
case EndEvent() as ev:
|
|
571
572
|
message.stop_reason = ev.reason
|
|
572
573
|
message.usage = Usage(
|