tau-coding-agent 0.5.4__tar.gz → 0.5.6__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.5.4/tau_coding_agent.egg-info → tau_coding_agent-0.5.6}/PKG-INFO +2 -1
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/settings.md +8 -5
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/tui.md +5 -3
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/pyproject.toml +2 -1
- tau_coding_agent-0.5.6/tau/builtins/extensions/ask_user/__init__.py +16 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/ask_user/component.py +346 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/ask_user/manifest.json +18 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/ask_user/schema.py +41 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/ask_user/tool.py +129 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/extensions/watch/__init__.py +1 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/web/__init__.py +56 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/web/engines/__init__.py +107 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/web/engines/base.py +73 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/web/engines/ddgs_engine.py +117 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/web/engines/exa_engine.py +63 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/web/engines/jina_engine.py +65 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/web/engines/tavily_engine.py +61 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/web/manifest.json +115 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/web/tools/fetch.py +200 -0
- tau_coding_agent-0.5.6/tau/builtins/extensions/web/tools/search.py +178 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/ayu-dark.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/catppuccin.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/dracula.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/everforest.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/gruvbox.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/horizon.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/kanagawa.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/material-ocean.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/monokai.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/night-owl.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/nord.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/one-dark.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/rose-pine.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/solarized-dark.yaml +46 -0
- tau_coding_agent-0.5.6/tau/builtins/themes/tokyo-night.yaml +46 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/tools/utils.py +1 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/extensions/api.py +1 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/runtime/service.py +3 -1
- tau_coding_agent-0.5.6/tau/telemetry/__init__.py +9 -0
- tau_coding_agent-0.5.6/tau/telemetry/service.py +120 -0
- tau_coding_agent-0.5.6/tau/telemetry/types.py +24 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/tui.py +0 -1
- tau_coding_agent-0.5.6/tau/utils/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6/tau_coding_agent.egg-info}/PKG-INFO +2 -1
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau_coding_agent.egg-info/SOURCES.txt +34 -1
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau_coding_agent.egg-info/requires.txt +1 -0
- tau_coding_agent-0.5.6/tests/test_telemetry.py +73 -0
- tau_coding_agent-0.5.4/tau/utils/telemetry.py +0 -42
- tau_coding_agent-0.5.4/tests/test_telemetry.py +0 -75
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/LICENSE +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/MANIFEST.in +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/README.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/architecture.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/auth.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/cli-reference.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/creating-tools.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/development.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/docs.json +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/engine.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/extension-settings.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/extensions.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/http-proxy.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/index.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/inference-providers.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/inference.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/installation.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/keybindings.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/messages.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/project-context.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/project-structure.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/prompts.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/python-api.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/quickstart.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/sessions.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/skills.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/themes.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/tools.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/docs/usage.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/setup.cfg +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/agent/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/agent/prompt/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/agent/prompt/builder.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/agent/prompt/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/agent/service.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/agent/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/auth/manager.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/auth/storage.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/auth/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/commands/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/commands/clear.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/commands/compact.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/commands/reload.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/commands/session.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/extensions/btw/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/extensions/footer/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/extensions/footer/git.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/extensions/footer/model.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/extensions/footer/utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/extensions/header/__init__.py +0 -0
- {tau_coding_agent-0.5.4/tau/builtins/models → tau_coding_agent-0.5.6/tau/builtins/extensions/web/tools}/__init__.py +0 -0
- {tau_coding_agent-0.5.4/tau/builtins/providers → tau_coding_agent-0.5.6/tau/builtins/models}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/models/audio.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/models/image.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/models/text.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/models/video.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/prompts/commit.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/prompts/docs.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/prompts/explain.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/prompts/fix.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/prompts/refactor.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/prompts/review.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/prompts/test.md +0 -0
- {tau_coding_agent-0.5.4/tau/console → tau_coding_agent-0.5.6/tau/builtins/providers}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/providers/audio.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/providers/image.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/providers/text.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/providers/video.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/skills/code-review/SKILL.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/skills/debug/SKILL.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/skills/git-commit/SKILL.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/skills/skill-creator/LICENSE.txt +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/skills/skill-creator/SKILL.md +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/themes/dark.yaml +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/themes/light.yaml +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/tools/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/tools/edit.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/tools/glob.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/tools/grep.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/tools/ls.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/tools/read.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/tools/terminal.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/builtins/tools/write.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/commands/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/commands/registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/commands/types.py +0 -0
- {tau_coding_agent-0.5.4/tau/console/commands → tau_coding_agent-0.5.6/tau/console}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/console/cli.py +0 -0
- {tau_coding_agent-0.5.4/tau/core → tau_coding_agent-0.5.6/tau/console/commands}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/console/commands/auth.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/console/commands/packages.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/console/commands/update.py +0 -0
- {tau_coding_agent-0.5.4/tau/inference/api → tau_coding_agent-0.5.6/tau/core}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/core/registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/engine/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/engine/service.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/engine/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/extensions/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/extensions/context.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/extensions/loader.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/extensions/runtime.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/extensions/settings.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/hooks/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/hooks/engine.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/hooks/inference.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/hooks/runtime.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/hooks/service.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/hooks/session.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/hooks/tui.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/hooks/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/__init__.py +0 -0
- {tau_coding_agent-0.5.4/tau/inference/api/audio → tau_coding_agent-0.5.6/tau/inference/api}/__init__.py +0 -0
- {tau_coding_agent-0.5.4/tau/inference/api/image → tau_coding_agent-0.5.6/tau/inference/api/audio}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/audio/base.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/audio/builtins.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/audio/elevenlabs_audio.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/audio/gemini_audio.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/audio/openai_audio.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/audio/registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/audio/sarvam_audio.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/audio/service.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/audio/utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/availability.py +0 -0
- {tau_coding_agent-0.5.4/tau/inference/api/text → tau_coding_agent-0.5.6/tau/inference/api/image}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/image/base.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/image/builtins.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/image/gemini_image.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/image/openai_image.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/image/openrouter.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/image/registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/image/service.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/registry.py +0 -0
- {tau_coding_agent-0.5.4/tau/inference/api/video → tau_coding_agent-0.5.6/tau/inference/api/text}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/anthropic_claude_code.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/anthropic_messages.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/anthropic_vertex.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/base.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/builtins.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/dialect.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/gemini_generate.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/github_copilot_chat.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/google_antigravity.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/google_vertex.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/mistral_chat.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/ollama_chat.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/openai_codex_responses.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/openai_completions.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/openai_responses.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/openai_vertex.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/service.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/text/utils.py +0 -0
- {tau_coding_agent-0.5.4/tau/inference/model → tau_coding_agent-0.5.6/tau/inference/api/video}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/video/base.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/video/builtins.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/video/fal_video.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/video/openrouter_video.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/video/registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/video/service.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/api/video/zai_video.py +0 -0
- {tau_coding_agent-0.5.4/tau/inference/provider → tau_coding_agent-0.5.6/tau/inference/model}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/model/registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/model/types.py +0 -0
- {tau_coding_agent-0.5.4/tau/message → tau_coding_agent-0.5.6/tau/inference/provider}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/provider/oauth/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/provider/oauth/anthropic_claude_code.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/provider/oauth/github_copilot.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/provider/oauth/google_antigravity.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/provider/oauth/openai_codex.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/provider/oauth/pkce.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/provider/oauth/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/provider/oauth/utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/provider/registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/provider/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/inference/utils.py +0 -0
- {tau_coding_agent-0.5.4/tau/modes → tau_coding_agent-0.5.6/tau/message}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/message/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/message/utils.py +0 -0
- {tau_coding_agent-0.5.4/tau/modes/interactive → tau_coding_agent-0.5.6/tau/modes}/__init__.py +0 -0
- {tau_coding_agent-0.5.4/tau/modes/interactive/components → tau_coding_agent-0.5.6/tau/modes/interactive}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/agent_hooks.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/app.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/commands/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/commands/appearance.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/commands/auth.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/commands/context.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/commands/extensions.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/commands/misc.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/commands/model.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/commands/session.py +0 -0
- {tau_coding_agent-0.5.4/tau/modes/print → tau_coding_agent-0.5.6/tau/modes/interactive/components}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/command_palette.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/config_selector.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/extension_selector.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/file_picker.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/layout.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/message_list.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/model_selector.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/oauth_selector.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/overlays.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/selector_controller.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/session_selector.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/settings_selector.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/theme_selector.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/thinking_selector.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/tree_selector.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/trust_screen.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/components/voice_selector.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/input_handler.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/interactive/ui_context.py +0 -0
- {tau_coding_agent-0.5.4/tau/tui/components → tau_coding_agent-0.5.6/tau/modes/print}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/rpc/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/rpc/mode.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/modes/rpc/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/packages/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/packages/manager.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/packages/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/packages/utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/prompts/expand.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/prompts/loader.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/prompts/registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/prompts/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/resources/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/resources/loader.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/resources/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/runtime/dependencies.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/runtime/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/session/branch_summarization.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/session/compaction.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/session/manager.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/session/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/session/utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/settings/manager.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/settings/paths.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/settings/storage.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/settings/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/settings/utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/skills/loader.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/skills/registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/skills/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/themes/loader.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/themes/registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/themes/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tool/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tool/registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tool/render.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tool/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/trust/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/trust/manager.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/trust/types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/trust/utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/autocomplete.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/component.py +0 -0
- {tau_coding_agent-0.5.4/tau/utils → tau_coding_agent-0.5.6/tau/tui/components}/__init__.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/components/box.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/components/editor.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/components/image.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/components/select_list.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/components/spinner.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/components/text_input.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/input.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/keybinding_hints.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/markdown.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/terminal.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/theme.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/tui/utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/utils/http_proxy.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/utils/image_processing.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/utils/secrets.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau/utils/version_check.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau_coding_agent.egg-info/dependency_links.txt +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau_coding_agent.egg-info/entry_points.txt +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tau_coding_agent.egg-info/top_level.txt +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_agent_compaction.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_agent_prompt.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_agent_types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_ansi.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_ask_user_extension.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_auth_command.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_auth_manager.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_auth_storage.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_autocomplete_modifiers.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_branch_navigation.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_branch_summarization.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_builtin_tools.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_builtin_watch.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_cli_inputs.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_command_execution_policy.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_command_registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_compaction.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_diff.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_editor_protocol.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_engine_execution.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_engine_steering.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_engine_types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_escape_behavior.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_extension_api.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_extension_lifecycle.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_footer_model.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_footer_utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_fuzzy.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_http_proxy.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_image_processing.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_inference_api_text_utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_inference_dialect.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_inference_error_utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_inference_types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_inference_utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_keybindings.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_markdown.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_message_types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_message_utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_model_availability.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_model_command.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_model_registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_model_selector_modal.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_model_types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_oauth_utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_package_resources.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_packages_utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_peer_extension.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_pkce.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_prompts_expand.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_prompts_loader.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_prompts_registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_provider_registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_resource_loader.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_rpc_mode.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_runtime_sdk.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_secrets.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_selector_controller.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_session_manager.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_session_trust_persist.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_session_types.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_session_utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_settings_manager.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_settings_paths.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_settings_storage.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_settings_utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_skills_loader.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_skills_registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_subagents_extension.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_text_input.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_text_llm_invoke.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_theme_loader.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_themes_registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_thinking_render.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_tool_registry.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_tool_render.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_trust_manager.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_trust_utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_tui_capabilities.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_tui_input.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_tui_layout_sizing.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_tui_public_api.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_tui_renderer.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_tui_select_list.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_tui_theme.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_tui_utils.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_ui_context.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_version_check.py +0 -0
- {tau_coding_agent-0.5.4 → tau_coding_agent-0.5.6}/tests/test_voice_selector.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tau-coding-agent
|
|
3
|
-
Version: 0.5.
|
|
3
|
+
Version: 0.5.6
|
|
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
|
|
@@ -24,6 +24,7 @@ Requires-Dist: mistletoe==1.5.1
|
|
|
24
24
|
Requires-Dist: pyyaml==6.0.2
|
|
25
25
|
Requires-Dist: pygments==2.20.0
|
|
26
26
|
Requires-Dist: pathspec==1.1.1
|
|
27
|
+
Requires-Dist: posthog==7.21.3
|
|
27
28
|
Requires-Dist: gitpython==3.1.50
|
|
28
29
|
Requires-Dist: grapheme==0.6.0
|
|
29
30
|
Requires-Dist: arrow==1.4.0
|
|
@@ -149,11 +149,14 @@ Toggle during a session with `/effort` or the effort picker.
|
|
|
149
149
|
|-------|------|---------|-------------|
|
|
150
150
|
| `telemetry` | boolean | `true` | Send one anonymous version-only install/update count |
|
|
151
151
|
|
|
152
|
-
Telemetry sends only the installed Tau version to Tau's
|
|
153
|
-
per version
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
152
|
+
Telemetry sends only the installed Tau version to Tau's PostHog project once
|
|
153
|
+
per version, as a single `tau` event on a shared anonymous distinct ID. When
|
|
154
|
+
enabled, Tau also reports uncaught exceptions (type, message, and traceback)
|
|
155
|
+
to the same PostHog project so crashes can be diagnosed. Tau does not persist
|
|
156
|
+
per-user identifiers and does not send prompts, paths, models, authentication
|
|
157
|
+
state, session data, or tool activity. As with any HTTP request, PostHog
|
|
158
|
+
necessarily processes the source IP under its own privacy policy. Failed
|
|
159
|
+
requests are ignored and never block startup or shutdown.
|
|
157
160
|
|
|
158
161
|
This is a global preference: project settings cannot enable telemetry after it
|
|
159
162
|
has been disabled globally. Disable it in `/settings` or in
|
|
@@ -122,9 +122,11 @@ Input is normalized into typed events:
|
|
|
122
122
|
- `BgColorEvent`
|
|
123
123
|
|
|
124
124
|
Use `KeyEvent.matches()` instead of comparing raw escape sequences.
|
|
125
|
-
Mouse reporting is enabled
|
|
126
|
-
|
|
127
|
-
|
|
125
|
+
Mouse reporting is not enabled by the TUI — terminals only offer clicks and
|
|
126
|
+
wheel-scroll as a single reporting mode, so requesting it would take over the
|
|
127
|
+
terminal's native wheel-scroll and click-drag copy for the whole session.
|
|
128
|
+
`MouseEvent` remains available for embedders that want to opt into that
|
|
129
|
+
trade-off themselves via `Terminal.enable_mouse_tracking()`.
|
|
128
130
|
|
|
129
131
|
## Overlays
|
|
130
132
|
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "tau-coding-agent"
|
|
7
|
-
version = "0.5.
|
|
7
|
+
version = "0.5.6"
|
|
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"
|
|
@@ -28,6 +28,7 @@ dependencies = [
|
|
|
28
28
|
"pyyaml==6.0.2",
|
|
29
29
|
"pygments==2.20.0",
|
|
30
30
|
"pathspec==1.1.1",
|
|
31
|
+
"posthog==7.21.3",
|
|
31
32
|
"gitpython==3.1.50",
|
|
32
33
|
"grapheme==0.6.0",
|
|
33
34
|
"arrow==1.4.0",
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
# Add this directory to sys.path to allow easy resolution of schema, component, and tool.
|
|
7
|
+
sys.path.insert(0, str(Path(__file__).parent))
|
|
8
|
+
|
|
9
|
+
from tool import AskUserTool
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def register(tau) -> None:
|
|
13
|
+
config = tau.config or {}
|
|
14
|
+
if not config.get("enabled", True):
|
|
15
|
+
return
|
|
16
|
+
tau.register_tool(AskUserTool(tau._runtime_ref))
|
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from typing import Any
|
|
4
|
+
|
|
5
|
+
from schema import AskUserOption
|
|
6
|
+
|
|
7
|
+
from tau.tui.component import Component
|
|
8
|
+
from tau.tui.input import InputEvent, KeyEvent
|
|
9
|
+
|
|
10
|
+
FREEFORM_LABEL = "Type something…"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def _typed_char(event: KeyEvent) -> str | None:
|
|
14
|
+
"""Return the printable character a key event represents, or None.
|
|
15
|
+
|
|
16
|
+
``event.key`` is always lowercased by the parser (the original case lives
|
|
17
|
+
in ``event.char``), so text entry must read ``char`` to avoid silently
|
|
18
|
+
lowercasing everything the user types.
|
|
19
|
+
"""
|
|
20
|
+
if event.char is not None and len(event.char) >= 1 and event.char.isprintable():
|
|
21
|
+
return event.char
|
|
22
|
+
if len(event.key) == 1 and event.key.isprintable():
|
|
23
|
+
return event.key
|
|
24
|
+
return None
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class _AskUserComponent(Component):
|
|
28
|
+
"""Floating dialog: option list (single/multi-select) + optional freeform entry."""
|
|
29
|
+
|
|
30
|
+
ML_VISIBLE_ROWS = 8
|
|
31
|
+
ML_MIN_VISIBLE_ROWS = 4 # pad short buffers so the box visibly reads as multi-line
|
|
32
|
+
|
|
33
|
+
def __init__(
|
|
34
|
+
self,
|
|
35
|
+
question: str,
|
|
36
|
+
context: str | None,
|
|
37
|
+
options: list[AskUserOption],
|
|
38
|
+
allow_multiple: bool,
|
|
39
|
+
allow_freeform: bool,
|
|
40
|
+
multiline: bool,
|
|
41
|
+
on_done: Any,
|
|
42
|
+
) -> None:
|
|
43
|
+
self._question = question
|
|
44
|
+
self._context = context
|
|
45
|
+
self._options = options
|
|
46
|
+
self._allow_multiple = allow_multiple
|
|
47
|
+
self._allow_freeform = allow_freeform
|
|
48
|
+
self._multiline = multiline
|
|
49
|
+
self._on_done = on_done
|
|
50
|
+
|
|
51
|
+
self._cursor = 0
|
|
52
|
+
self._checked: set[int] = set()
|
|
53
|
+
self._mode = "list" # "list" | "freeform"
|
|
54
|
+
self._freeform_value = "" # single-line freeform buffer
|
|
55
|
+
|
|
56
|
+
# Multi-line freeform buffer (used only when self._multiline).
|
|
57
|
+
self._ml_lines: list[str] = [""]
|
|
58
|
+
self._ml_cursor_row = 0
|
|
59
|
+
self._ml_cursor_col = 0
|
|
60
|
+
self._ml_scroll_top = 0
|
|
61
|
+
|
|
62
|
+
# Index of the synthetic "Type something…" row, if present.
|
|
63
|
+
self._freeform_index = len(options) if allow_freeform else -1
|
|
64
|
+
self._row_count = len(options) + (1 if allow_freeform else 0)
|
|
65
|
+
|
|
66
|
+
# No real choices — freeform is the only path, so open straight into the
|
|
67
|
+
# editor with a live cursor instead of forcing an Enter on a single
|
|
68
|
+
# "Type something…" row first. Applies to both single- and multi-line.
|
|
69
|
+
if not self._options and self._allow_freeform:
|
|
70
|
+
self._enter_freeform()
|
|
71
|
+
|
|
72
|
+
def _enter_freeform(self, seed: str = "") -> None:
|
|
73
|
+
self._mode = "freeform"
|
|
74
|
+
if self._multiline:
|
|
75
|
+
self._ml_lines = [seed]
|
|
76
|
+
self._ml_cursor_row = 0
|
|
77
|
+
self._ml_cursor_col = len(seed)
|
|
78
|
+
self._ml_scroll_top = 0
|
|
79
|
+
else:
|
|
80
|
+
self._freeform_value = seed
|
|
81
|
+
|
|
82
|
+
# ── Render ────────────────────────────────────────────────────────────
|
|
83
|
+
|
|
84
|
+
def render(self, width: int) -> list[str]:
|
|
85
|
+
from tau.modes.interactive.components.overlays import _box
|
|
86
|
+
|
|
87
|
+
inner: list[str] = []
|
|
88
|
+
if self._context:
|
|
89
|
+
for line in self._context.splitlines():
|
|
90
|
+
inner.append(f" \x1b[2m{line}\x1b[0m")
|
|
91
|
+
inner.append("")
|
|
92
|
+
inner.append(f" \x1b[1m{self._question}\x1b[0m")
|
|
93
|
+
inner.append("")
|
|
94
|
+
|
|
95
|
+
if self._mode == "freeform" and self._multiline:
|
|
96
|
+
self._clamp_ml_scroll()
|
|
97
|
+
limit = self._ml_scroll_top + self.ML_VISIBLE_ROWS
|
|
98
|
+
visible = self._ml_lines[self._ml_scroll_top : limit]
|
|
99
|
+
for ri, line in enumerate(visible):
|
|
100
|
+
abs_row = self._ml_scroll_top + ri
|
|
101
|
+
if abs_row == self._ml_cursor_row:
|
|
102
|
+
before = line[: self._ml_cursor_col]
|
|
103
|
+
after = line[self._ml_cursor_col :]
|
|
104
|
+
inner.append(f" {before}█{after}")
|
|
105
|
+
else:
|
|
106
|
+
inner.append(f" {line}")
|
|
107
|
+
# Pad with blank rows (display-only, not part of the buffer) so an
|
|
108
|
+
# empty/short answer still shows several rows — a visible cue that
|
|
109
|
+
# this is a multi-line editor, not a single-line box.
|
|
110
|
+
for _ in range(self.ML_MIN_VISIBLE_ROWS - len(visible)):
|
|
111
|
+
inner.append("")
|
|
112
|
+
total = len(self._ml_lines)
|
|
113
|
+
if total > self.ML_VISIBLE_ROWS:
|
|
114
|
+
pct = int(self._ml_scroll_top / max(1, total - self.ML_VISIBLE_ROWS) * 100)
|
|
115
|
+
inner.append(f" \x1b[2m↕ {pct}%\x1b[0m")
|
|
116
|
+
else:
|
|
117
|
+
inner.append("")
|
|
118
|
+
back = "Esc to cancel" if not self._options else "Esc to go back"
|
|
119
|
+
inner.append(
|
|
120
|
+
" \x1b[2mEnter to submit · \\+Enter or Shift+Enter for newline · "
|
|
121
|
+
f"{back}\x1b[0m"
|
|
122
|
+
)
|
|
123
|
+
return _box(inner, "", width, bg="")
|
|
124
|
+
|
|
125
|
+
if self._mode == "freeform":
|
|
126
|
+
inner.append(f" {self._freeform_value}█")
|
|
127
|
+
inner.append("")
|
|
128
|
+
back = "Esc to cancel" if not self._options else "Esc to go back"
|
|
129
|
+
inner.append(f" \x1b[2mEnter to submit · {back}\x1b[0m")
|
|
130
|
+
return _box(inner, "", width, bg="")
|
|
131
|
+
|
|
132
|
+
for i in range(self._row_count):
|
|
133
|
+
is_freeform_row = i == self._freeform_index
|
|
134
|
+
title = FREEFORM_LABEL if is_freeform_row else self._options[i].title
|
|
135
|
+
desc = "" if is_freeform_row else (self._options[i].description or "")
|
|
136
|
+
is_cursor = i == self._cursor
|
|
137
|
+
cursor_mark = "›" if is_cursor else " "
|
|
138
|
+
|
|
139
|
+
if self._allow_multiple and not is_freeform_row:
|
|
140
|
+
# Same tick glyphs as the /extensions config panel. Cursor rows
|
|
141
|
+
# get wrapped in reverse-video below, so leave them uncolored
|
|
142
|
+
# there — an embedded reset would cut the highlight short.
|
|
143
|
+
if i in self._checked:
|
|
144
|
+
box = "✔" if is_cursor else "\x1b[32m✔\x1b[0m"
|
|
145
|
+
else:
|
|
146
|
+
box = "✖" if is_cursor else "\x1b[2m✖\x1b[0m"
|
|
147
|
+
elif not is_freeform_row:
|
|
148
|
+
# Radio-style circles: filled at the cursor position, hollow
|
|
149
|
+
# elsewhere. Same reverse-video caveat as the checkbox ticks
|
|
150
|
+
# above — leave the cursor row's glyph uncolored.
|
|
151
|
+
box = "●" if is_cursor else "\x1b[2m○\x1b[0m"
|
|
152
|
+
else:
|
|
153
|
+
box = " > "
|
|
154
|
+
|
|
155
|
+
row = f" {cursor_mark} {box} {title}"
|
|
156
|
+
if is_cursor:
|
|
157
|
+
row = f"\x1b[7m{row}\x1b[0m"
|
|
158
|
+
if desc:
|
|
159
|
+
row += f" \x1b[2m{desc}\x1b[0m"
|
|
160
|
+
inner.append(row)
|
|
161
|
+
|
|
162
|
+
inner.append("")
|
|
163
|
+
hints = ["↑/↓ move", "Enter confirm", "Esc cancel"]
|
|
164
|
+
if self._allow_multiple:
|
|
165
|
+
hints.insert(1, "Space toggle")
|
|
166
|
+
inner.append(" \x1b[2m" + " · ".join(hints) + "\x1b[0m")
|
|
167
|
+
return _box(inner, "", width)
|
|
168
|
+
|
|
169
|
+
# ── Input ─────────────────────────────────────────────────────────────
|
|
170
|
+
|
|
171
|
+
def handle_input(self, event: InputEvent) -> bool:
|
|
172
|
+
if not isinstance(event, KeyEvent):
|
|
173
|
+
return False
|
|
174
|
+
|
|
175
|
+
if self._mode == "freeform":
|
|
176
|
+
return self._handle_freeform_input(event)
|
|
177
|
+
return self._handle_list_input(event)
|
|
178
|
+
|
|
179
|
+
def _handle_list_input(self, event: KeyEvent) -> bool:
|
|
180
|
+
match event.key:
|
|
181
|
+
case "up":
|
|
182
|
+
self._cursor = (self._cursor - 1) % max(1, self._row_count)
|
|
183
|
+
case "down":
|
|
184
|
+
self._cursor = (self._cursor + 1) % max(1, self._row_count)
|
|
185
|
+
case " " | "space" if self._allow_multiple and self._cursor != self._freeform_index:
|
|
186
|
+
if self._cursor in self._checked:
|
|
187
|
+
self._checked.discard(self._cursor)
|
|
188
|
+
else:
|
|
189
|
+
self._checked.add(self._cursor)
|
|
190
|
+
case "enter":
|
|
191
|
+
if self._cursor == self._freeform_index:
|
|
192
|
+
self._enter_freeform()
|
|
193
|
+
elif self._allow_multiple:
|
|
194
|
+
chosen = self._checked or {self._cursor}
|
|
195
|
+
self._on_done(
|
|
196
|
+
{
|
|
197
|
+
"kind": "selection",
|
|
198
|
+
"selections": [self._options[i].title for i in sorted(chosen)],
|
|
199
|
+
}
|
|
200
|
+
)
|
|
201
|
+
else:
|
|
202
|
+
self._on_done(
|
|
203
|
+
{"kind": "selection", "selections": [self._options[self._cursor].title]}
|
|
204
|
+
)
|
|
205
|
+
case "escape":
|
|
206
|
+
self._on_done(None)
|
|
207
|
+
case _ if self._allow_freeform and _typed_char(event) is not None:
|
|
208
|
+
# Typing directly on the list view jumps straight into freeform
|
|
209
|
+
# entry instead of requiring the user to navigate to and Enter
|
|
210
|
+
# the "Type something…" row first.
|
|
211
|
+
self._enter_freeform(seed=_typed_char(event) or "")
|
|
212
|
+
case _:
|
|
213
|
+
return False
|
|
214
|
+
return True
|
|
215
|
+
|
|
216
|
+
def _handle_freeform_input(self, event: KeyEvent) -> bool:
|
|
217
|
+
if self._multiline:
|
|
218
|
+
return self._handle_multiline_input(event)
|
|
219
|
+
|
|
220
|
+
match event.key:
|
|
221
|
+
case "enter":
|
|
222
|
+
self._on_done({"kind": "freeform", "text": self._freeform_value})
|
|
223
|
+
case "escape":
|
|
224
|
+
# With no real choices there's no list to fall back to — Esc
|
|
225
|
+
# cancels the whole prompt (mirrors the multi-line editor).
|
|
226
|
+
if not self._options:
|
|
227
|
+
self._on_done(None)
|
|
228
|
+
else:
|
|
229
|
+
self._mode = "list"
|
|
230
|
+
self._freeform_value = ""
|
|
231
|
+
case "backspace":
|
|
232
|
+
self._freeform_value = self._freeform_value[:-1]
|
|
233
|
+
case _ if _typed_char(event) is not None:
|
|
234
|
+
self._freeform_value += _typed_char(event) or ""
|
|
235
|
+
case _:
|
|
236
|
+
return False
|
|
237
|
+
return True
|
|
238
|
+
|
|
239
|
+
def _ml_insert_newline(self) -> None:
|
|
240
|
+
line = self._ml_lines[self._ml_cursor_row]
|
|
241
|
+
before, after = line[: self._ml_cursor_col], line[self._ml_cursor_col :]
|
|
242
|
+
self._ml_lines[self._ml_cursor_row] = before
|
|
243
|
+
self._ml_lines.insert(self._ml_cursor_row + 1, after)
|
|
244
|
+
self._ml_cursor_row += 1
|
|
245
|
+
self._ml_cursor_col = 0
|
|
246
|
+
|
|
247
|
+
def _handle_multiline_input(self, event: KeyEvent) -> bool:
|
|
248
|
+
k = event.key
|
|
249
|
+
|
|
250
|
+
if k == "escape":
|
|
251
|
+
if not self._options:
|
|
252
|
+
self._on_done(None)
|
|
253
|
+
else:
|
|
254
|
+
self._mode = "list"
|
|
255
|
+
return True
|
|
256
|
+
if k == "enter":
|
|
257
|
+
# Shift+Enter always inserts a newline. Ctrl+S/Ctrl+Enter aren't
|
|
258
|
+
# reliable across terminals (Ctrl+S is XOFF flow control in many),
|
|
259
|
+
# so plain Enter submits — unless the line ends with a trailing
|
|
260
|
+
# "\", a shell-style continuation marker meaning "newline, please".
|
|
261
|
+
if event.shift:
|
|
262
|
+
self._ml_insert_newline()
|
|
263
|
+
return True
|
|
264
|
+
line = self._ml_lines[self._ml_cursor_row]
|
|
265
|
+
if self._ml_cursor_col > 0 and line[self._ml_cursor_col - 1] == "\\":
|
|
266
|
+
self._ml_lines[self._ml_cursor_row] = (
|
|
267
|
+
line[: self._ml_cursor_col - 1] + line[self._ml_cursor_col :]
|
|
268
|
+
)
|
|
269
|
+
self._ml_cursor_col -= 1
|
|
270
|
+
self._ml_insert_newline()
|
|
271
|
+
return True
|
|
272
|
+
self._on_done({"kind": "freeform", "text": "\n".join(self._ml_lines)})
|
|
273
|
+
return True
|
|
274
|
+
if k == "backspace":
|
|
275
|
+
if self._ml_cursor_col > 0:
|
|
276
|
+
line = self._ml_lines[self._ml_cursor_row]
|
|
277
|
+
self._ml_lines[self._ml_cursor_row] = (
|
|
278
|
+
line[: self._ml_cursor_col - 1] + line[self._ml_cursor_col :]
|
|
279
|
+
)
|
|
280
|
+
self._ml_cursor_col -= 1
|
|
281
|
+
elif self._ml_cursor_row > 0:
|
|
282
|
+
prev = self._ml_lines[self._ml_cursor_row - 1]
|
|
283
|
+
merged = prev + self._ml_lines.pop(self._ml_cursor_row)
|
|
284
|
+
self._ml_cursor_row -= 1
|
|
285
|
+
self._ml_cursor_col = len(prev)
|
|
286
|
+
self._ml_lines[self._ml_cursor_row] = merged
|
|
287
|
+
return True
|
|
288
|
+
if k == "up":
|
|
289
|
+
if self._ml_cursor_row > 0:
|
|
290
|
+
self._ml_cursor_row -= 1
|
|
291
|
+
row_len = len(self._ml_lines[self._ml_cursor_row])
|
|
292
|
+
self._ml_cursor_col = min(self._ml_cursor_col, row_len)
|
|
293
|
+
return True
|
|
294
|
+
if k == "down":
|
|
295
|
+
if self._ml_cursor_row < len(self._ml_lines) - 1:
|
|
296
|
+
self._ml_cursor_row += 1
|
|
297
|
+
row_len = len(self._ml_lines[self._ml_cursor_row])
|
|
298
|
+
self._ml_cursor_col = min(self._ml_cursor_col, row_len)
|
|
299
|
+
return True
|
|
300
|
+
if k == "left":
|
|
301
|
+
if self._ml_cursor_col > 0:
|
|
302
|
+
self._ml_cursor_col -= 1
|
|
303
|
+
elif self._ml_cursor_row > 0:
|
|
304
|
+
self._ml_cursor_row -= 1
|
|
305
|
+
self._ml_cursor_col = len(self._ml_lines[self._ml_cursor_row])
|
|
306
|
+
return True
|
|
307
|
+
if k == "right":
|
|
308
|
+
line = self._ml_lines[self._ml_cursor_row]
|
|
309
|
+
if self._ml_cursor_col < len(line):
|
|
310
|
+
self._ml_cursor_col += 1
|
|
311
|
+
elif self._ml_cursor_row < len(self._ml_lines) - 1:
|
|
312
|
+
self._ml_cursor_row += 1
|
|
313
|
+
self._ml_cursor_col = 0
|
|
314
|
+
return True
|
|
315
|
+
if k == "home":
|
|
316
|
+
self._ml_cursor_col = 0
|
|
317
|
+
return True
|
|
318
|
+
if k == "end":
|
|
319
|
+
self._ml_cursor_col = len(self._ml_lines[self._ml_cursor_row])
|
|
320
|
+
return True
|
|
321
|
+
ch = _typed_char(event)
|
|
322
|
+
if ch is not None:
|
|
323
|
+
line = self._ml_lines[self._ml_cursor_row]
|
|
324
|
+
self._ml_lines[self._ml_cursor_row] = (
|
|
325
|
+
line[: self._ml_cursor_col] + ch + line[self._ml_cursor_col :]
|
|
326
|
+
)
|
|
327
|
+
self._ml_cursor_col += len(ch)
|
|
328
|
+
return True
|
|
329
|
+
return False
|
|
330
|
+
|
|
331
|
+
def _clamp_ml_scroll(self) -> None:
|
|
332
|
+
if self._ml_cursor_row < self._ml_scroll_top:
|
|
333
|
+
self._ml_scroll_top = self._ml_cursor_row
|
|
334
|
+
elif self._ml_cursor_row >= self._ml_scroll_top + self.ML_VISIBLE_ROWS:
|
|
335
|
+
self._ml_scroll_top = self._ml_cursor_row - self.ML_VISIBLE_ROWS + 1
|
|
336
|
+
# Pull the window back down when lines below it are deleted (e.g. via
|
|
337
|
+
# backspace-merge) — otherwise the visible slice shrinks below
|
|
338
|
+
# ML_VISIBLE_ROWS even while there's still enough content to fill it.
|
|
339
|
+
max_scroll_top = max(0, len(self._ml_lines) - self.ML_VISIBLE_ROWS)
|
|
340
|
+
self._ml_scroll_top = max(0, min(self._ml_scroll_top, max_scroll_top))
|
|
341
|
+
|
|
342
|
+
def invalidate(self) -> None:
|
|
343
|
+
pass
|
|
344
|
+
|
|
345
|
+
def set_theme(self, theme: Any) -> None:
|
|
346
|
+
pass
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"tau": {
|
|
3
|
+
"name": "Ask User",
|
|
4
|
+
"author": "jeomon",
|
|
5
|
+
"settings": {
|
|
6
|
+
"title": "Ask User",
|
|
7
|
+
"fields": [
|
|
8
|
+
{
|
|
9
|
+
"key": "enabled",
|
|
10
|
+
"label": "Enabled",
|
|
11
|
+
"type": "bool",
|
|
12
|
+
"default": true,
|
|
13
|
+
"description": "Register the ask_user tool."
|
|
14
|
+
}
|
|
15
|
+
]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from pydantic import BaseModel, Field
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class AskUserOption(BaseModel):
|
|
7
|
+
title: str
|
|
8
|
+
description: str | None = None
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class AskUserParams(BaseModel):
|
|
12
|
+
question: str = Field(..., description="The question to ask the user")
|
|
13
|
+
context: str | None = Field(
|
|
14
|
+
default=None, description="Relevant context summary shown before the question"
|
|
15
|
+
)
|
|
16
|
+
options: list[str | AskUserOption] | None = Field(
|
|
17
|
+
default=None, description="Multiple-choice options"
|
|
18
|
+
)
|
|
19
|
+
allow_multiple: bool = Field(default=False, description="Allow selecting more than one option")
|
|
20
|
+
allow_freeform: bool = Field(
|
|
21
|
+
default=True, description="Offer a 'Type something' freeform option"
|
|
22
|
+
)
|
|
23
|
+
multiline: bool = Field(
|
|
24
|
+
default=False,
|
|
25
|
+
description=(
|
|
26
|
+
"Use a multi-line text editor for the freeform answer instead of a single "
|
|
27
|
+
"line — set this for open-ended, long-form answers (e.g. 'write your bio', "
|
|
28
|
+
"'describe the requirements'). Supports arrow-key navigation between lines, "
|
|
29
|
+
"Enter for a newline, Ctrl+S/Ctrl+Enter to submit."
|
|
30
|
+
),
|
|
31
|
+
)
|
|
32
|
+
timeout: int | None = Field(
|
|
33
|
+
default=None, description="Auto-dismiss after N ms and cancel if the prompt times out"
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
AskUserParams.model_rebuild()
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def normalize_options(raw: list[str | AskUserOption] | None) -> list[AskUserOption]:
|
|
41
|
+
return [AskUserOption(title=o) if isinstance(o, str) else o for o in (raw or [])]
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import asyncio
|
|
4
|
+
from typing import Any
|
|
5
|
+
|
|
6
|
+
from component import _AskUserComponent
|
|
7
|
+
from schema import AskUserParams, normalize_options
|
|
8
|
+
|
|
9
|
+
from tau.tool.render import call_line
|
|
10
|
+
from tau.tool.types import (
|
|
11
|
+
Tool,
|
|
12
|
+
ToolContext,
|
|
13
|
+
ToolExecutionMode,
|
|
14
|
+
ToolInvocation,
|
|
15
|
+
ToolKind,
|
|
16
|
+
ToolResult,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _render_call(args: dict, _streaming: bool = False) -> list[str]:
|
|
21
|
+
return call_line("ask_user", args.get("question", ""))
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def _render_result(content: str, opts: Any) -> list[str]:
|
|
25
|
+
return content.splitlines() or [content]
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class AskUserTool(Tool):
|
|
29
|
+
def __init__(self, runtime_ref: Any) -> None:
|
|
30
|
+
self._runtime_ref = runtime_ref
|
|
31
|
+
super().__init__(
|
|
32
|
+
name="ask_user",
|
|
33
|
+
description=(
|
|
34
|
+
"Ask the human a focused question and wait for their decision before "
|
|
35
|
+
"proceeding. Use for high-impact architectural trade-offs, ambiguous or "
|
|
36
|
+
"conflicting requirements, or assumptions that would materially change "
|
|
37
|
+
"the implementation. Supports single-select, multi-select, and freeform "
|
|
38
|
+
"text answers. Only available in an interactive TUI session."
|
|
39
|
+
),
|
|
40
|
+
schema=AskUserParams,
|
|
41
|
+
kind=ToolKind.Read,
|
|
42
|
+
execution_mode=ToolExecutionMode.Sequential,
|
|
43
|
+
render_call=_render_call,
|
|
44
|
+
render_result=_render_result,
|
|
45
|
+
render_shell="default",
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
async def execute(
|
|
49
|
+
self,
|
|
50
|
+
invocation: ToolInvocation,
|
|
51
|
+
tool_execution_update_callback=None,
|
|
52
|
+
signal=None,
|
|
53
|
+
context: ToolContext | None = None,
|
|
54
|
+
) -> ToolResult:
|
|
55
|
+
params = AskUserParams.model_validate(invocation.params)
|
|
56
|
+
options = normalize_options(params.options)
|
|
57
|
+
|
|
58
|
+
runtime = self._runtime_ref.runtime if self._runtime_ref is not None else None
|
|
59
|
+
if runtime is None:
|
|
60
|
+
return ToolResult.error(invocation.id, "ask_user unavailable: runtime not ready")
|
|
61
|
+
|
|
62
|
+
from tau.extensions.context import ExtensionContext
|
|
63
|
+
|
|
64
|
+
ext_ctx = ExtensionContext.from_runtime(runtime)
|
|
65
|
+
ui = ext_ctx.ui
|
|
66
|
+
if ui is None:
|
|
67
|
+
return ToolResult.error(
|
|
68
|
+
invocation.id,
|
|
69
|
+
"ask_user requires an interactive TUI session and is "
|
|
70
|
+
"unavailable in headless/RPC mode",
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
from tau.tui.tui import CustomOptions, OverlayOptions
|
|
74
|
+
|
|
75
|
+
loop = asyncio.get_running_loop()
|
|
76
|
+
fut: asyncio.Future[dict | None] = loop.create_future()
|
|
77
|
+
timeout_task_ref: list[asyncio.Task | None] = [None]
|
|
78
|
+
|
|
79
|
+
def _on_done(value: dict | None) -> None:
|
|
80
|
+
t = timeout_task_ref[0]
|
|
81
|
+
if t is not None and not t.done():
|
|
82
|
+
t.cancel()
|
|
83
|
+
if not fut.done():
|
|
84
|
+
fut.set_result(value)
|
|
85
|
+
|
|
86
|
+
def _factory(_tui, _theme, _kb, done):
|
|
87
|
+
component = _AskUserComponent(
|
|
88
|
+
question=params.question,
|
|
89
|
+
context=params.context,
|
|
90
|
+
options=options,
|
|
91
|
+
allow_multiple=params.allow_multiple,
|
|
92
|
+
allow_freeform=params.allow_freeform,
|
|
93
|
+
multiline=params.multiline,
|
|
94
|
+
on_done=lambda v: (_on_done(v), done(v)),
|
|
95
|
+
)
|
|
96
|
+
timeout_ms = params.timeout
|
|
97
|
+
if timeout_ms:
|
|
98
|
+
|
|
99
|
+
async def _auto_dismiss() -> None:
|
|
100
|
+
await asyncio.sleep(timeout_ms / 1000)
|
|
101
|
+
_on_done(None)
|
|
102
|
+
done(None)
|
|
103
|
+
|
|
104
|
+
timeout_task_ref[0] = asyncio.ensure_future(_auto_dismiss())
|
|
105
|
+
return component
|
|
106
|
+
|
|
107
|
+
await ui.custom(
|
|
108
|
+
_factory,
|
|
109
|
+
CustomOptions(overlay_options=OverlayOptions(width="70%", anchor="center", margin=1)),
|
|
110
|
+
)
|
|
111
|
+
response = await fut
|
|
112
|
+
|
|
113
|
+
if response is None:
|
|
114
|
+
return ToolResult.ok(
|
|
115
|
+
invocation.id,
|
|
116
|
+
"The user cancelled the question without answering.",
|
|
117
|
+
metadata={"cancelled": True, "question": params.question},
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
if response["kind"] == "freeform":
|
|
121
|
+
content = response["text"]
|
|
122
|
+
else:
|
|
123
|
+
content = ", ".join(response["selections"])
|
|
124
|
+
|
|
125
|
+
return ToolResult.ok(
|
|
126
|
+
invocation.id,
|
|
127
|
+
content,
|
|
128
|
+
metadata={"cancelled": False, "question": params.question, "response": response},
|
|
129
|
+
)
|