Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
5a8b899
[tau] Start on the coding agent demo
msullivan May 12, 2026
1e57908
[tau] Queue user input while a turn is streaming
msullivan May 12, 2026
08d1fa6
[tau] Extract chat_loop into a standalone function
msullivan May 12, 2026
e677362
[tau] Don't yank scrolled-up readers down, and hide the scrollbar
msullivan May 12, 2026
8451df9
[tau] Implement pi's seven tools with approval-gated mutations
msullivan May 12, 2026
c366aff
[tau] Approval prompt as a focusable widget above the composer
msullivan May 13, 2026
77aa291
[tau] Stop gating write and edit behind approval
msullivan May 13, 2026
15ea035
[tau] Add TAU_ADVERTISE=1 flag to include co-author trailer in commit…
msullivan May 13, 2026
288dd7c
[tau] Add session history with persist/resume support
msullivan May 13, 2026
a630470
[tau] Show cumulative token usage in footer bar
msullivan May 13, 2026
77d685a
[tau] Show approximate context size in usage footer
msullivan May 13, 2026
b4c0e7e
[tau] Enable gateway caching and improve usage display
msullivan May 13, 2026
b6b76fb
[tau] Refactor chat_loop: extract _run_turn for single-turn logic
msullivan May 13, 2026
99c57ee
[tau] Add ApprovalTracker with per-command and global auto-approve
msullivan May 13, 2026
e7a1842
[tau] Auto-approve file tools under cwd, prompt for external paths
msullivan May 13, 2026
4b73595
[tau] Ring terminal bell on turn completion and approval prompts
msullivan May 13, 2026
e3ce80a
[tau] Render assistant messages as markdown via Rich
msullivan May 13, 2026
c7068f9
[tau] ESC to interrupt running turn
msullivan May 13, 2026
da6acfc
[tau] Remove ctrl+d quit binding
msullivan May 13, 2026
fd5236d
[tau] Consistent scroll-follow behavior for all event types
msullivan May 13, 2026
095527d
[tau] Make bash tool a StreamingTextTool
msullivan May 13, 2026
91be672
[tau] Unwrap ExceptionGroup errors for readable error bubbles
msullivan May 15, 2026
9c073d1
[tau] Only send gateway providerOptions when using gateway provider
msullivan May 15, 2026
e5a85b1
[tau] Display thinking/reasoning blocks in dim italic bubbles
msullivan May 15, 2026
b97676e
[tau] Enable adaptive thinking for Anthropic models via gateway
msullivan May 16, 2026
3b2e850
[tau] Fix crash when tool kwargs contain Pydantic models
msullivan May 16, 2026
fa14b1b
[tau] Default auto_scroll=False for add_bubble
msullivan May 16, 2026
c1c0f88
[tau] Move ApprovalTracker to agent-loop section of tau.py
msullivan May 16, 2026
ebd54a1
[tau] Update uv.lock?
msullivan May 19, 2026
0077aaa
[tau] Move tau-agent to a proper Python package
msullivan May 19, 2026
0a69a80
[tau] Extract SessionManager from TauApp
msullivan May 19, 2026
9a2b23e
[tau] Remove stale comment about ai library usage
msullivan May 19, 2026
c0d3415
[tau] Move bubble management out of the agent loop into TauApp methods
msullivan May 20, 2026
a3c9169
[tau] Use show_tool_result in session replay
msullivan May 20, 2026
6dbb489
[tau] Extract _replay_session from TauApp._restore_session
msullivan May 20, 2026
300a25c
[tau] Use isinstance instead of hasattr for ToolResultPart check
msullivan May 20, 2026
4e50306
[tau] Consolidate approval decision handling into ApprovalTracker.rem…
msullivan May 20, 2026
baf4ed0
[tau] Move hook resolution into ApprovalTracker.resolve
msullivan May 20, 2026
ca154f5
[tau] Introduce Hook dataclass to decouple UI from ai.messages.HookPart
msullivan May 20, 2026
dccd46a
[tau] Extract _resolve_hook helper for resolve + show_system
msullivan May 20, 2026
0b578f1
[tau] Move prompt option logic from HookPrompt into ApprovalTracker
msullivan May 20, 2026
a3d6265
[tau] Fix _format_tool_result leading blank line
msullivan May 20, 2026
0acb1b6
[tau] Minor cleanups: _bell, on_text_area_changed, require_approval c…
msullivan May 20, 2026
a32c6ed
[tau] Stream tool call outputs via PartialToolCallResult
msullivan May 20, 2026
bc9eae3
[tau] Set stdin=DEVNULL for bash subprocess
msullivan May 20, 2026
f733d7e
[tau] Replay thinking blocks and tool calls on session restore
msullivan May 20, 2026
c62608b
[tau] Add AGENTS.md support
msullivan May 20, 2026
b5aa7e5
[tau] Add image support to the read tool
msullivan May 20, 2026
6460775
[tau] Replace manual scroll management with Textual's anchor system
msullivan May 20, 2026
bdacecd
[tau] Support image reads
msullivan May 20, 2026
5850e84
[tau] Use ansi-dark theme for native terminal colors
msullivan May 20, 2026
b0912a0
[tau] Run formatting, make line length match the toplevel project
msullivan May 21, 2026
02d4887
[tau] Add multi-line input to composer
msullivan May 21, 2026
173b199
[tau] Add provider web search tool based on model backend
msullivan May 21, 2026
f228cd5
[tau] Mention web_search in system prompt when available
msullivan May 21, 2026
c917086
[tau] Show builtin tool events in transcript
msullivan May 21, 2026
15ab19f
[tau] use raw model name in Co-authored-by trailer
msullivan May 22, 2026
0ffcadc
[tau] ruff
msullivan May 22, 2026
8770181
[tau] fix mypy type errors
msullivan May 22, 2026
05fd908
[tau] show tool results in a shaded block
msullivan May 22, 2026
6317db2
[tau] render edit tool calls as pi-style diffs
msullivan May 23, 2026
bedbc4c
[tau] fix: reset bubble state at start of each chat turn
msullivan May 23, 2026
8426bc8
[tau] add AGENTS.md for coding agents
msullivan May 23, 2026
c587a55
[tau] fix: handle legacy str results in _EditAggregator.to_model_input
msullivan May 23, 2026
d04ff69
WIP: Support FilePart in tool results across all providers
msullivan May 20, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -216,3 +216,4 @@ __marimo__/

.claude/
.codex
.tau/
6 changes: 6 additions & 0 deletions examples/.test_scripts/check-examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,12 @@
["fastapi", "textual", "websockets"],
["."],
),
(
"tau-agent",
REPO / "examples" / "tau-agent",
["textual"],
["."],
),
(
"temporal-direct",
REPO / "examples" / "temporal-direct",
Expand Down
13 changes: 13 additions & 0 deletions examples/tau-agent/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Python
__pycache__/
*.py[cod]
*.egg-info/
.venv/
dist/

# Environment
.env
.env*.local

# Tau session history
.tau/
49 changes: 49 additions & 0 deletions examples/tau-agent/AGENTS.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# AGENTS.md — tau-agent

## Overview

`tau` is a single-process coding-agent TUI built on the `ai` library and
Textual. It gives the model seven filesystem/shell tools (read, write,
edit, bash, grep, find, ls) with an approval gate for mutating
operations.

## Project layout

```
tau/
app.py — Textual app, chat loop, approval flow
tools.py — tool definitions (mirrors pi's seven built-ins)
session.py — JSONL session persistence and resume
pyproject.toml — project metadata, dependencies, ruff/mypy config
```

## TODO list

There may be a task list in `.tau/TODO` — check it for current
priorities and open items.

## Running

```bash
uv sync # install deps
uv run tau # launch the TUI
```

## Linting & type-checking

```bash
uv run ruff check . # lint
uv run ruff format --check # format check
uv run mypy tau # type-check
```

## Conventions

- Python ≥ 3.12.
- Line length: 80 (`ruff` and project style).
- Lint rule set: E, F, I, UP, B, SIM (see `pyproject.toml`).
- No workspace jail — the approval gate is the safety mechanism.
- Approval-gated tools (`write`, `edit`, `bash`) require operator
confirmation; reads are auto-approved.
- Sessions persist as JSONL under `.tau/sessions/`.
- Commit messages for this subdirectory should be prefixed with `[tau]`.
41 changes: 41 additions & 0 deletions examples/tau-agent/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
# tau-agent

`tau` is a coding-agent demo built on the `ai` library. Single
process, Textual TUI, streaming replies, pi-style tool surface:

- **`read`** — read files; offset/limit pagination with continuation hints
- **`write`** — create / overwrite a file
- **`edit`** — exact-match str_replace, multiple disjoint edits per call
- **`bash`** — run a shell command in cwd, output truncated to the last 50KB / 2000 lines *(requires approval)*
- **`grep`** — regex search (skips `.git`, `node_modules`, etc.)
- **`find`** — glob match
- **`ls`** — directory listing

Approval-gated tools fire a `ToolApproval` hook; the composer turns
into a `[y/n]` prompt mid-turn. Unrelated text typed during a
pending approval falls through to the message queue — the hook stays
pending until you give it a y or n.

No workspace jail. The approval gate is the safety mechanism;
everything else relies on you watching the prompts.

## Setup

```bash
uv sync
```

## Running

```bash
uv run tau
```

Type a message, hit enter. `ctrl+c` to quit.

## Environment

| Variable | Description | Default |
|----------|-------------|---------|
| `AI_GATEWAY_API_KEY` | Vercel AI Gateway API key | — |
| `TAU_MODEL` | Model id passed to `ai.ai_gateway(...)` | `anthropic/claude-sonnet-4.5` |
35 changes: 35 additions & 0 deletions examples/tau-agent/pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
[project]
name = "tau-agent"
version = "0.1.0"
description = "Tau — a coding-agent chat bot demo built with the ai library and Textual"
requires-python = ">=3.12"
dependencies = [
"ai",
"textual>=3.0",
]

[project.scripts]
tau = "tau.app:main"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.hatch.build.targets.wheel]
packages = ["tau"]

[tool.uv.sources]
ai = { path = "../..", editable = true }

[tool.ruff]
line-length = 80
target-version = "py312"

[tool.ruff.lint]
select = ["E", "F", "I", "UP", "B", "SIM"]

[dependency-groups]
dev = [
"mypy~=2.1.0",
"ruff>=0.15.12",
]
1 change: 1 addition & 0 deletions examples/tau-agent/tau/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""tau — a coding-agent chat bot built on the `ai` library and Textual."""
5 changes: 5 additions & 0 deletions examples/tau-agent/tau/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
"""Entry point for ``python -m tau``."""

from tau.app import main

main()
Loading
Loading