@markusylisiurunen/tau 0.3.50 → 0.3.52

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/dist/code_mode/command.js +26 -14
  2. package/dist/code_mode/command.js.map +1 -1
  3. package/dist/code_mode/index.d.ts +2 -1
  4. package/dist/code_mode/index.js +1 -0
  5. package/dist/code_mode/index.js.map +1 -1
  6. package/dist/core/cli.js +0 -11
  7. package/dist/core/cli.js.map +1 -1
  8. package/dist/core/client_tools/command_client_tools.js +236 -151
  9. package/dist/core/client_tools/command_client_tools.js.map +1 -1
  10. package/dist/core/config/schema.js +8 -2
  11. package/dist/core/config/schema.js.map +1 -1
  12. package/dist/core/history/history_manager.js +73 -7
  13. package/dist/core/history/history_manager.js.map +1 -1
  14. package/dist/core/history/local_history_store.js +73 -2
  15. package/dist/core/history/local_history_store.js.map +1 -1
  16. package/dist/core/history/remote_history_client.js +36 -6
  17. package/dist/core/history/remote_history_client.js.map +1 -1
  18. package/dist/core/modes/index.js +0 -1
  19. package/dist/core/modes/index.js.map +1 -1
  20. package/dist/core/static/tau_docs/client-tools.md +212 -12
  21. package/dist/core/static/tau_docs/config-reference.md +1 -1
  22. package/dist/core/static/tau_docs/configuration.md +1 -1
  23. package/dist/core/static/tau_docs/credentials.md +4 -4
  24. package/dist/core/static/tau_docs/history.md +6 -4
  25. package/dist/core/static/tau_docs/index.md +1 -1
  26. package/dist/core/static/tau_docs/node-sdk.md +33 -26
  27. package/dist/core/static/tau_docs/ownership-and-scope.md +3 -4
  28. package/dist/core/static/tau_docs/prompts-and-project-context.md +2 -2
  29. package/dist/core/static/tau_docs/remote-sessions.md +4 -47
  30. package/dist/core/static/tau_docs/security.md +2 -6
  31. package/dist/core/static/tau_docs/session-protocol-methods.md +48 -7
  32. package/dist/core/static/tau_docs/session-protocol.md +18 -18
  33. package/dist/core/static/tau_docs/sessions.md +6 -5
  34. package/dist/core/static/tau_docs/telegram.md +8 -4
  35. package/dist/core/static/tau_docs/tools.md +1 -1
  36. package/dist/core/static/tau_docs/troubleshooting.md +3 -5
  37. package/dist/core/static/tau_docs/tui.md +4 -6
  38. package/dist/core/telegram/adapter.js +226 -18
  39. package/dist/core/telegram/adapter.js.map +1 -1
  40. package/dist/core/telegram/config.js +1 -1
  41. package/dist/core/telegram/config.js.map +1 -1
  42. package/dist/core/telegram/project_preferences.js +42 -12
  43. package/dist/core/telegram/project_preferences.js.map +1 -1
  44. package/dist/core/telegram/runtime.js +6 -1
  45. package/dist/core/telegram/runtime.js.map +1 -1
  46. package/dist/core/telegram/session_manager.js +50 -4
  47. package/dist/core/telegram/session_manager.js.map +1 -1
  48. package/dist/core/telegram/tts.js +137 -0
  49. package/dist/core/telegram/tts.js.map +1 -0
  50. package/dist/core/tools/execution_backend.js +13 -3
  51. package/dist/core/tools/execution_backend.js.map +1 -1
  52. package/dist/core/tools/presentation.js +55 -17
  53. package/dist/core/tools/presentation.js.map +1 -1
  54. package/dist/core/utils/gemini_speech.js +123 -42
  55. package/dist/core/utils/gemini_speech.js.map +1 -1
  56. package/dist/core/utils/gemini_transcription.js +1 -1
  57. package/dist/core/version.js +1 -1
  58. package/dist/execution/cloudflare_sandbox_execution_environment.js +2 -2
  59. package/dist/execution/cloudflare_sandbox_execution_environment.js.map +1 -1
  60. package/dist/execution/fly_sprite_execution_environment.js +2 -2
  61. package/dist/execution/fly_sprite_execution_environment.js.map +1 -1
  62. package/dist/host/client_tool_broker.js +71 -17
  63. package/dist/host/client_tool_broker.js.map +1 -1
  64. package/dist/host/local_session_host.js +2 -2
  65. package/dist/host/local_session_host.js.map +1 -1
  66. package/dist/host/session_host.js.map +1 -1
  67. package/dist/host/session_protocol_handler.js +17 -6
  68. package/dist/host/session_protocol_handler.js.map +1 -1
  69. package/dist/main.js +18 -92
  70. package/dist/main.js.map +1 -1
  71. package/dist/protocol/session_protocol.d.ts +22 -2
  72. package/dist/protocol/session_protocol.js +47 -3
  73. package/dist/protocol/session_protocol.js.map +1 -1
  74. package/dist/sdk/client_tool_command.d.ts +41 -13
  75. package/dist/sdk/client_tool_command.js +157 -39
  76. package/dist/sdk/client_tool_command.js.map +1 -1
  77. package/dist/sdk/client_tool_presentation.d.ts +17 -0
  78. package/dist/sdk/client_tool_presentation.js +9 -0
  79. package/dist/sdk/client_tool_presentation.js.map +1 -0
  80. package/dist/sdk/code_mode.js +10 -1
  81. package/dist/sdk/code_mode.js.map +1 -1
  82. package/dist/sdk/index.d.ts +5 -4
  83. package/dist/sdk/index.js +2 -1
  84. package/dist/sdk/index.js.map +1 -1
  85. package/dist/sdk/session.js +28 -9
  86. package/dist/sdk/session.js.map +1 -1
  87. package/dist/sdk/types.d.ts +11 -1
  88. package/dist/transport/errors.d.ts +0 -11
  89. package/dist/transport/errors.js +0 -12
  90. package/dist/transport/errors.js.map +1 -1
  91. package/dist/transport/index.d.ts +1 -3
  92. package/dist/transport/index.js +1 -2
  93. package/dist/transport/index.js.map +1 -1
  94. package/dist/tui/session_chat_app.js +28 -15
  95. package/dist/tui/session_chat_app.js.map +1 -1
  96. package/dist/tui/session_chat_controller.js +0 -51
  97. package/dist/tui/session_chat_controller.js.map +1 -1
  98. package/dist/tui/speech_playback.js +3 -3
  99. package/dist/tui/speech_playback.js.map +1 -1
  100. package/package.json +2 -2
  101. package/dist/core/modes/rpc_server.js +0 -105
  102. package/dist/core/modes/rpc_server.js.map +0 -1
  103. package/dist/transport/stdio_session_transport.d.ts +0 -48
  104. package/dist/transport/stdio_session_transport.js +0 -338
  105. package/dist/transport/stdio_session_transport.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  # Remote sessions
2
2
 
3
- Remote sessions let the terminal stay close to the user while the session host and execution environment run elsewhere. Tau does not turn remote work into a second product mode: `tau attach` uses the same TUI over a WebSocket or stdio transport. The important choice is which process should stay alive, who owns credentials and persistence, and where agent-visible commands run.
3
+ Remote sessions let the terminal stay close to the user while the session host and execution environment run elsewhere. Tau does not turn remote work into a second product mode: `tau attach` uses the same TUI over WebSocket. The important boundaries are who owns credentials and persistence and where agent-visible commands run.
4
4
 
5
5
  ## Choose the connection shape
6
6
 
@@ -9,12 +9,10 @@ Use the smallest shape that matches the lifecycle you need.
9
9
  | Shape | Best for | Lifetime and ownership |
10
10
  | --- | --- | --- |
11
11
  | `tau serve` plus WebSocket attach | Long-running hosts, reconnects, and multiple observers | The server owns the host independently of any one TUI. |
12
- | `tau attach -- ssh … tau rpc` | Ad hoc access through SSH without exposing a listener | The attachment owns one remote RPC process. Closing it shuts that host down. |
13
- | `tau rpc` directly | Editors, automation, and custom protocol clients over NDJSON | The parent process owns the RPC host and its stdin/stdout. |
14
12
  | Node SDK with its default client | Applications that want an in-process host | The SDK client owns the host and closes it with the client. |
15
13
  | Node SDK over WebSocket | Applications sharing a long-running `tau serve` host | The server owns sessions; the SDK observes them remotely. |
16
14
 
17
- Use `tau serve` when a turn should continue after a laptop disconnects. Use stdio/SSH when SSH is already the desired security and process boundary and it is acceptable for closing the TUI to stop remote work. The [session protocol](session-protocol.md) and [Node SDK](node-sdk.md) cover developer APIs and wire details; this page stays at the operational level.
15
+ Use `tau serve` for remote TUI and SDK connections. Keep it bound to loopback behind an SSH tunnel when SSH is the desired security boundary. The [session protocol](session-protocol.md) and [Node SDK](node-sdk.md) cover developer APIs and wire details; this page stays at the operational level.
18
16
 
19
17
  ## Host sessions over WebSocket
20
18
 
@@ -58,24 +56,6 @@ Then attach locally:
58
56
  tau attach ws://127.0.0.1:8787
59
57
  ```
60
58
 
61
- ## Attach through stdio and SSH
62
-
63
- Anything after `--` is launched as a local child process and must speak Tau’s session protocol over stdin and stdout. SSH makes that child a remote `tau rpc` process:
64
-
65
- ```sh
66
- tau attach -- ssh dev@buildbox.example tau rpc
67
- ```
68
-
69
- A login shell or project-specific host configuration can be selected in the remote command:
70
-
71
- ```sh
72
- tau attach -- ssh dev@buildbox.example 'cd /srv/tau-host && tau rpc'
73
- ```
74
-
75
- The remote process’s stdin and stdout are protocol traffic. Shell startup files and wrapper scripts must not print banners to stdout. Put diagnostics on stderr.
76
-
77
- This is a one-shot host. When the TUI exits or the transport fails, the local child is terminated, `tau rpc` shuts down its host, active work is interrupted, and durable state is recovered on the next process. Do not use this shape when work must continue through client disconnects; run `tau serve` instead.
78
-
79
59
  ## List, select, create, or attach
80
60
 
81
61
  Without `--session` or `--new`, `tau attach` asks the host for its session list and opens an interactive selector:
@@ -94,14 +74,6 @@ tau attach \
94
74
  ws://127.0.0.1:8787
95
75
  ```
96
76
 
97
- The equivalent SSH form is:
98
-
99
- ```sh
100
- tau attach \
101
- --session 0195d6e4-4cf9-7f44-a2d8-f8f7f49ee9d3 \
102
- -- ssh dev@buildbox.example tau rpc
103
- ```
104
-
105
77
  Create a new session with an absolute cwd in the selected execution environment:
106
78
 
107
79
  ```sh
@@ -111,15 +83,6 @@ tau attach \
111
83
  ws://127.0.0.1:8787
112
84
  ```
113
85
 
114
- For stdio/SSH:
115
-
116
- ```sh
117
- tau attach \
118
- --new \
119
- --cwd /srv/workspaces/tau \
120
- -- ssh dev@buildbox.example tau rpc
121
- ```
122
-
123
86
  For the default `local` execution kind, this path is on the host machine, not the attaching machine. It must already be a usable directory with the desired repository or workspace. Tau creates the session, not the directory or repository.
124
87
 
125
88
  Remote `--new` supplies the conventional creation attribute `source: "tui"`. It does not infer repository metadata by inspecting the remote cwd. Clients that need repository provenance should create through the SDK or protocol and provide complete immutable attributes. See [sessions](sessions.md).
@@ -215,7 +178,7 @@ Different changes have different owners:
215
178
  | Effective model `apiKeys` in execution-environment or session configuration | Wait for idle, then run `/reload`; new sessions also resolve the current values. |
216
179
  | Managed Codex auth changed with `tau auth` | No host restart; auth storage is read again on later credential resolutions. |
217
180
  | Attaching themes, diff launcher, speech config, or configured client tools | Restart `tau attach`. |
218
- | Host process environment variables, history target, WebSocket listener, Cloudflare bridge, Fly API target, or host startup flags | Restart `tau serve` or the `tau rpc` process. |
181
+ | Host process environment variables, history target, WebSocket listener, Cloudflare bridge, Fly API target, or host startup flags | Restart `tau serve`. |
219
182
  | Host Tau package, built-in tools, protocol, session recovery code, or built-in documentation | Upgrade and restart the host. |
220
183
  | TUI package, keybindings, rendering, local speech, or client-tool implementation | Upgrade and restart the attaching client. |
221
184
 
@@ -227,8 +190,6 @@ A WebSocket connection observes a hosted session; it does not own or delete it.
227
190
 
228
191
  A clean `tau serve` shutdown interrupts active work, persists live sessions, and closes clients. On restart, the host lists sessions whose execution environments it can restore. Recovery returns sessions idle, drops pending queued and steering messages, discards live subagents, and changes an active persistent goal to blocked. Use `/goal resume` only after checking why the host stopped.
229
192
 
230
- A stdio/SSH connection is different because its RPC process is the host. Closing the connection ends that process. The session remains stored under the remote host user’s `~/.config/tau/sessions` and can be observed by a later `tau rpc` process using the same home and compatible resolver configuration.
231
-
232
193
  ## Use multiple observers carefully
233
194
 
234
195
  Multiple WebSocket clients can observe the same live session and receive the same committed updates and pending-message state. They can also submit, queue, steer, interrupt, or mutate that session, so coordinate human or automation ownership rather than treating observers as read-only.
@@ -265,10 +226,6 @@ Do not edit the session JSON to change environment identity. Restore the owning
265
226
 
266
227
  Verify that server and client use the same token and that a reverse proxy preserves the WebSocket request path and query string. `TAU_WS_AUTH_TOKEN` can silently supply either side, so inspect the environment as well as command-line flags. Do not print the token in shared logs.
267
228
 
268
- ### SSH attachment fails before the TUI opens
269
-
270
- Run the remote command directly and confirm that `tau rpc` is installed and can start. Protocol stdout must contain only NDJSON. Login banners, shell startup output, or wrapper diagnostics on stdout corrupt the transport; redirect them to stderr or remove them.
271
-
272
229
  ### A reconnect shows an interrupted turn
273
230
 
274
- A client disconnect alone does not stop a WebSocket-hosted turn, but server shutdown does. Stdio/SSH attachment shutdown also ends its host. Review the last assistant and tool states, verify the execution environment with `!!pwd` and `!!git status --short`, then retry or resume a blocked goal intentionally. [Sessions](sessions.md) explains recovery and safe verification.
231
+ A client disconnect alone does not stop a WebSocket-hosted turn, but server shutdown does. Review the last assistant and tool states, verify the execution environment with `!!pwd` and `!!git status --short`, then retry or resume a blocked goal intentionally. [Sessions](sessions.md) explains recovery and safe verification.
@@ -41,7 +41,7 @@ Prompt templates are inserted into the editor for review rather than submitted a
41
41
 
42
42
  ## Keep secrets with the process that needs them
43
43
 
44
- Most model and service credentials belong to the host because the host performs model calls, web search, history replication, and host-tool Nook requests. TUI speech credentials and command client-tool credentials belong to the client. Telegram bot and transcription credentials belong to the Telegram runner. Hosted-environment bridge and API credentials belong to host startup.
44
+ Most model and service credentials belong to the host because the host performs model calls, web search, history replication, and host-tool Nook requests. TUI speech credentials and command client-tool credentials belong to the client. Telegram bot, transcription, and voice-response credentials belong to the Telegram runner. Hosted-environment bridge and API credentials belong to host startup.
45
45
 
46
46
  In a remote attachment, a credential exported on the laptop does not authenticate the remote host. Conversely, putting a host credential into the execution target's shell environment unnecessarily exposes it to target processes. Follow [credentials](credentials.md) for exact resolution precedence.
47
47
 
@@ -77,12 +77,10 @@ Do not rely on sanitization as a secret store or authorization boundary. Avoid b
77
77
 
78
78
  Tau command execution uses a fresh non-interactive login Bash. The execution environment's `HOME` controls login startup discovery. Bash can read `/etc/profile`, the first available user login file, and `BASH_ENV`; a login file may also source `.bashrc`.
79
79
 
80
- These files execute with the same operating-system authority as every tool command. A compromised or overly broad startup file can change `PATH`, run commands, disclose data, terminate the shell, or corrupt protocol output. Review startup files in each execution environment, especially targets created from shared images or user homes.
80
+ These files execute with the same operating-system authority as every tool command. A compromised or overly broad startup file can change `PATH`, run commands, disclose data, terminate the shell, or produce unexpected output. Review startup files in each execution environment, especially targets created from shared images or user homes.
81
81
 
82
82
  Startup files must not print banners, prompt for input, read stdin, require a TTY, launch an editor, or exit the shell unexpectedly. Tau does not suppress their output. There is no TTY, and ordinary agent Bash calls have no stdin, so interactive authentication and terminal prompts fail or wait until timeout. Configure Git, SSH, package managers, and cloud CLIs for deliberate noninteractive use.
83
83
 
84
- `tau rpc` has an additional constraint: stdout is the NDJSON protocol. Shell banners and wrapper diagnostics on stdout break the transport. Send diagnostics to stderr.
85
-
86
84
  ## Trust command client tools as local programs
87
85
 
88
86
  Command client tools are defined only in user-owned global configuration, then selected for a project. Tau starts the configured executable directly, without a shell, and validates model arguments against its configured object schema. The command still runs as trusted local code with the client's full inherited environment and filesystem permissions.
@@ -124,8 +122,6 @@ Tau's listener is plain WebSocket and has no certificate configuration. Across a
124
122
 
125
123
  A reverse proxy must preserve WebSocket upgrade behavior and the request query string while protecting both. Restrict who can reach the listener even when a token is configured. Multiple observers are active participants, not read-only viewers: they can submit, steer, interrupt, rewind, and advertise client tools. See [remote sessions](remote-sessions.md).
126
124
 
127
- Stdio attachment relies on the security of the launched command, commonly SSH. Closing that transport also closes its one-shot host. Use a long-running authenticated WebSocket host when work must survive client disconnects.
128
-
129
125
  ## Secure Telegram access and workspaces
130
126
 
131
127
  A Telegram runner is both a network-facing client and a local Tau host. Its bot configuration determines who can create turns that may execute tools in configured workspaces.
@@ -1,6 +1,6 @@
1
1
  # Session protocol method reference
2
2
 
3
- This page defines every request method in protocol version 12. It is the compact wire reference for clients that already understand connection, observation, and delta application from the [session protocol](session-protocol.md).
3
+ This page defines every request method in protocol version 13. It is the compact wire reference for clients that already understand connection, observation, and delta application from the [session protocol](session-protocol.md).
4
4
 
5
5
  Every request uses `{ version, type: "request", id, method, params }`. Every successful response uses `{ version, type: "response", id, ok: true, result }`. `params` is required even when empty, and unknown object fields are stripped.
6
6
 
@@ -47,7 +47,7 @@ params: {
47
47
  }
48
48
 
49
49
  result: {
50
- protocolVersion: 12;
50
+ protocolVersion: 13;
51
51
  methods: string[];
52
52
  alreadyInitialized: boolean;
53
53
  }
@@ -557,21 +557,62 @@ Acknowledges a `session.clientTool.call` before its deadline.
557
557
  params: {
558
558
  sessionId: string;
559
559
  callId: string;
560
+ presentation?: {
561
+ subject?: string;
562
+ subjectWrap?: "word" | "character";
563
+ details?: Array<{
564
+ text: string;
565
+ tone?: "added" | "removed";
566
+ wrap?: "word" | "character";
567
+ }>;
568
+ metadata?: string[];
569
+ };
560
570
  }
561
571
  result: {
562
572
  accepted: boolean;
563
573
  }
564
574
  ```
565
575
 
576
+ The optional presentation is a partial running-state override. When present, `subject` must be non-empty and may contain line feeds but not carriage returns. Each detail text and metadata value is one line. Presentation objects are limited to 1 MiB; subjects and detail values to 256 KiB each; metadata values to 16 KiB each; and detail and metadata collections to 1,024 entries each.
577
+
578
+ The host preserves explicit fields within those safety limits and supplies canonical display-truncated defaults for omitted fields. It owns the action and operation and records the resolved presentation. Empty detail or metadata arrays suppress those default fields. An accepted acknowledgement authorizes the client to begin execution.
579
+
566
580
  ### `session.clientTool.result`
567
581
 
568
- Completes an acknowledged call with model-visible content or an error.
582
+ Completes a call with model-visible content or an error.
569
583
 
570
584
  ```ts
585
+ type PresentationOverride = {
586
+ subject?: string;
587
+ subjectWrap?: "word" | "character";
588
+ details?: Array<{
589
+ text: string;
590
+ tone?: "added" | "removed";
591
+ wrap?: "word" | "character";
592
+ }>;
593
+ metadata?: string[];
594
+ };
595
+
571
596
  params:
572
- | { sessionId: string; callId: string; ok: true; content: string }
573
- | { sessionId: string; callId: string; ok: false; error: string }
574
- result: { accepted: boolean }
597
+ | {
598
+ sessionId: string;
599
+ callId: string;
600
+ ok: true;
601
+ content: string;
602
+ presentation?: PresentationOverride;
603
+ }
604
+ | {
605
+ sessionId: string;
606
+ callId: string;
607
+ ok: false;
608
+ error: string;
609
+ presentation?: PresentationOverride;
610
+ };
611
+ result: { accepted: boolean };
575
612
  ```
576
613
 
577
- `accepted: false` means the call was cancelled, timed out, detached, unknown, or already completed. Do not retry or send additional results for that call.
614
+ The optional result presentation applies only to the reported terminal state and is resolved independently from the running presentation. The host preserves explicit fields unchanged after safety validation and supplies canonical display-truncated defaults for omitted fields. If no client result arrives, the host uses a complete fallback for timeout, cancellation, detach, or another terminal outcome.
615
+
616
+ A successful result is accepted only after the host has accepted the acknowledgement. An error sent before acknowledgement records a preparation failure, such as an error from `describe`, without authorizing execution. An error sent afterward records an execution failure.
617
+
618
+ `accepted: false` means the successful call was not yet authorized, or the call was cancelled, timed out, detached, unknown, or already completed. Do not retry or send additional results for that call.
@@ -1,16 +1,14 @@
1
1
  # Session protocol
2
2
 
3
- Tau's session protocol is the public wire contract for clients that create, observe, and control hosted sessions. Use it when an integration needs to speak directly to `tau rpc` or `tau serve`. Node applications can usually use the typed [Node SDK](node-sdk.md) instead.
3
+ Tau's session protocol is the public wire contract for clients that create, observe, and control hosted sessions through `tau serve`. Node applications can usually use the typed [Node SDK](node-sdk.md) instead.
4
4
 
5
- The protocol carries the same semantics over stdio and WebSocket. It is request and response based, with separate server messages for observed state, pending input, subagent activity, ephemeral feedback, and delegated client tools. The complete method surface is in the [session protocol method reference](session-protocol-methods.md).
5
+ The protocol is transport-neutral and request and response based, with separate server messages for observed state, pending input, subagent activity, ephemeral feedback, and delegated client tools. Tau currently exposes it over WebSocket. The complete method surface is in the [session protocol method reference](session-protocol-methods.md).
6
6
 
7
- ## Choose a transport
7
+ ## Connect over WebSocket
8
8
 
9
- `tau rpc` uses UTF-8 NDJSON. The client writes one JSON request per stdin line and reads one JSON server message per stdout line. Stdout is protocol-only. Process diagnostics and login-shell output must go to stderr.
9
+ `tau serve` uses one UTF-8 JSON object per text WebSocket message. Binary messages are not supported. Authentication, TLS, listener setup, SSH tunneling, and host lifetime belong to [remote sessions](remote-sessions.md).
10
10
 
11
- `tau serve` uses one UTF-8 JSON object per text WebSocket message. Binary messages are not supported. Authentication, TLS, listener setup, SSH attachment, and host lifetime belong to [remote sessions](remote-sessions.md).
12
-
13
- Both transports expose one host. Starting either server does not create or select a session. A client lists, creates, or observes sessions explicitly.
11
+ The server exposes one host. Starting it does not create or select a session. A client lists, creates, or observes sessions explicitly.
14
12
 
15
13
  The client, host, and execution environment remain separate logical machines even when they share a process or filesystem. Session paths and commands belong to the execution environment. Persistence, credentials, model work, and protocol coordination belong to the host. Client tools and local UI belong to the connected client. See [ownership and scope](ownership-and-scope.md) before passing paths or credentials across this boundary.
16
14
 
@@ -20,7 +18,7 @@ The server sends `ready` as its first message:
20
18
 
21
19
  ```json
22
20
  {
23
- "version": 12,
21
+ "version": 13,
24
22
  "type": "ready",
25
23
  "methods": ["initialize", "session.create", "session.list"]
26
24
  }
@@ -32,7 +30,7 @@ After `ready`, send `initialize` with non-empty client metadata:
32
30
 
33
31
  ```json
34
32
  {
35
- "version": 12,
33
+ "version": 13,
36
34
  "type": "request",
37
35
  "id": "init-1",
38
36
  "method": "initialize",
@@ -52,7 +50,7 @@ Every request has the same envelope:
52
50
 
53
51
  ```json
54
52
  {
55
- "version": 12,
53
+ "version": 13,
56
54
  "type": "request",
57
55
  "id": "req-42",
58
56
  "method": "session.snapshot",
@@ -66,7 +64,7 @@ Successful responses echo the request id:
66
64
 
67
65
  ```json
68
66
  {
69
- "version": 12,
67
+ "version": 13,
70
68
  "type": "response",
71
69
  "id": "req-42",
72
70
  "ok": true,
@@ -126,7 +124,7 @@ Observed snapshot changes arrive as `session.delta`:
126
124
 
127
125
  ```json
128
126
  {
129
- "version": 12,
127
+ "version": 13,
130
128
  "type": "session.delta",
131
129
  "sessionId": "0195d6e4-4cf9-7f44-a2d8-f8f7f49ee9d3",
132
130
  "fromRevision": 8,
@@ -164,7 +162,7 @@ Not all observed state belongs in the recoverable snapshot. Each live channel ha
164
162
 
165
163
  ```json
166
164
  {
167
- "version": 12,
165
+ "version": 13,
168
166
  "type": "session.pendingUserMessages",
169
167
  "sessionId": "...",
170
168
  "state": {
@@ -201,7 +199,7 @@ An initialized client that advertised a tool can receive:
201
199
 
202
200
  ```json
203
201
  {
204
- "version": 12,
202
+ "version": 13,
205
203
  "type": "session.clientTool.call",
206
204
  "sessionId": "...",
207
205
  "agentId": "main",
@@ -213,9 +211,11 @@ An initialized client that advertised a tool can receive:
213
211
  }
214
212
  ```
215
213
 
216
- Acknowledge promptly with `session.clientTool.ack`, then send exactly one `session.clientTool.result` with either `{ ok: true, content }` or `{ ok: false, error }`. The result methods return `{ accepted: boolean }`; `false` means the call is no longer waiting for that message.
214
+ Acknowledge promptly with `session.clientTool.ack`, optionally including a bounded partial running presentation. Begin execution only after the acknowledgement returns `{ accepted: true }`, then send exactly one `session.clientTool.result` with either `{ ok: true, content }` or `{ ok: false, error }` and an optional independent terminal presentation. Both presentation objects may contain `subject`, `subjectWrap`, `details`, and `metadata`; the host owns action and operation and supplies every omitted field. Explicit fields are preserved unchanged after protocol safety validation, while generated defaults use Tau's canonical display truncation. Empty detail or metadata arrays suppress those defaults.
215
+
216
+ A successful result is rejected until acknowledgement has completed. If preparation itself fails, send an error result before acknowledgement; the host records it as a preparation failure without authorizing execution. If no result arrives because of timeout, cancellation, detach, or another failure, the host renders a complete fallback terminal presentation. The result method returns `{ accepted: boolean }`; `false` means the message is invalid for the call's current state or the call is no longer waiting for it.
217
217
 
218
- `session.clientTool.cancel` names the session and call with reason `aborted`, `timeout`, or `client-detached`. Abort local work and do not send a late result. The SDK implements this lifecycle automatically. Tool execution authority and the execution-environment facade are covered in [client tools](client-tools.md).
218
+ `session.clientTool.cancel` names the session and call with reason `aborted`, `timeout`, `client-detached`, or `host-failed`. Abort local work and do not send a late result. The SDK implements this lifecycle automatically. Tool execution authority and the execution-environment facade are covered in [client tools](client-tools.md).
219
219
 
220
220
  ## Handle errors and terminal transport failure
221
221
 
@@ -223,7 +223,7 @@ Error responses use `ok: false`:
223
223
 
224
224
  ```json
225
225
  {
226
- "version": 12,
226
+ "version": 13,
227
227
  "type": "response",
228
228
  "id": "req-42",
229
229
  "ok": false,
@@ -249,7 +249,7 @@ The supported codes are:
249
249
 
250
250
  When no valid request id can be recovered, an error response uses `id: null`. Error `message` and optional `data` are diagnostic. Branch on `code`, not message text.
251
251
 
252
- A closed stdio stream, process exit, WebSocket close, malformed server payload, unsupported version, or other terminal transport failure rejects all outstanding requests. Stop sending, cancel client-local delegated tools, and reconnect or create a new transport deliberately. A WebSocket disconnect detaches from a long-running host; closing a stdio RPC process shuts down the host it owns.
252
+ A WebSocket close, malformed server payload, unsupported version, or other terminal transport failure rejects all outstanding requests. Stop sending, cancel client-local delegated tools, and reconnect or create a new transport deliberately. A WebSocket disconnect detaches from the long-running host.
253
253
 
254
254
  ## Coordinate concurrent work
255
255
 
@@ -48,7 +48,7 @@ Retry runs another assistant turn from the current session history. It does not
48
48
 
49
49
  Retry is unavailable when there is no prior user turn. It is also unavailable for goal-controlled turns because a blocked goal has an explicit resume operation.
50
50
 
51
- Detaching is not the same as interrupting. Closing one observer of a long-running host leaves the hosted turn running. By contrast, a local TUI owns its in-process host, and a stdio attachment owns its `tau rpc` process; closing either causes that host to shut down and interrupt active work. See [remote sessions](remote-sessions.md).
51
+ Detaching is not the same as interrupting. Closing one observer of a long-running host leaves the hosted turn running. By contrast, a local TUI owns its in-process host, so closing it causes that host to shut down and interrupt active work. See [remote sessions](remote-sessions.md).
52
52
 
53
53
  ## Change persona and reasoning safely
54
54
 
@@ -189,14 +189,14 @@ Filters can be combined:
189
189
  tau usage --since 2026-08-01 --provider openai-codex --group-by model
190
190
  ```
191
191
 
192
- There is no `--until`, `--session`, or `--agent` filter. For a remote session, run `tau usage` on the host under the same user as `tau serve` or `tau rpc`; running it on an attaching client reads that client user’s logs instead. The command is read-only, but the raw files still reveal timestamps, session identifiers, model choices, token volume, and cost activity. Prefer the filtered aggregate output over copying raw JSONL into a shared transcript, and treat Tau-recorded costs as operational estimates rather than a provider invoice.
192
+ There is no `--until`, `--session`, or `--agent` filter. For a remote session, run `tau usage` on the host under the same user as `tau serve`; running it on an attaching client reads that client user’s logs instead. The command is read-only, but the raw files still reveal timestamps, session identifiers, model choices, token volume, and cost activity. Prefer the filtered aggregate output over copying raw JSONL into a shared transcript, and treat Tau-recorded costs as operational estimates rather than a provider invoice.
193
193
 
194
194
  ## What survives each boundary
195
195
 
196
196
  | Event | Durable session state | Pending input | Active turns and subagents | Client-local state |
197
197
  | --- | --- | --- | --- | --- |
198
198
  | Another client detaches from a live WebSocket host | Preserved | Preserved in host memory | Continue | Detached client tools, themes, drafts, and local tasks are lost |
199
- | Local TUI or stdio/RPC attachment exits | Persisted by owned-host shutdown | Cancelled | Interrupted and settled where possible | Lost |
199
+ | Local TUI exits | Persisted by owned-host shutdown | Cancelled | Interrupted and settled where possible | Lost |
200
200
  | WebSocket host restarts | Recovered from storage | Lost | Returns idle; subagents are not restored | Each client reconnects separately |
201
201
  | TUI restarts while host stays live | Preserved | Preserved in host memory | Continue | Reloaded from the new client process |
202
202
  | `/new` | Old session remains stored | Not copied | New idle session | Same TUI process continues |
@@ -214,10 +214,11 @@ Use normal Tau operations rather than opening or editing session files.
214
214
  5. Run non-contextual environment checks with `!!`, for example `!!pwd` and `!!git status --short`.
215
215
  6. Submit a small read-only request before resuming destructive work.
216
216
 
217
- For a local stored session, a one-shot local RPC attachment exercises the same recovery path:
217
+ For a local stored session, start a WebSocket host under the same user and attach from another terminal:
218
218
 
219
219
  ```sh
220
- tau attach --session 0195d6e4-4cf9-7f44-a2d8-f8f7f49ee9d3 -- tau rpc
220
+ tau serve
221
+ tau attach --session 0195d6e4-4cf9-7f44-a2d8-f8f7f49ee9d3 ws://127.0.0.1:8787
221
222
  ```
222
223
 
223
224
  If recovery fails, verify the host version, execution-environment resolver configuration, target availability, and credentials before assuming the stored session is damaged. [Remote sessions](remote-sessions.md) covers those checks.
@@ -58,7 +58,7 @@ Unknown object fields are stripped, so a misspelled field can have no effect wit
58
58
  | `maxSessions` | No | Positive integer cap on active sessions across the whole runner. |
59
59
  | `systemMessage` | No | Non-empty model-facing instruction prepended to every Telegram turn. |
60
60
 
61
- A relative top-level `workspaceRoot` resolves from the Telegram config file's directory. Tau persists runner session records at `<workspaceRoot>-sessions.json` and per-chat project preferences at `<workspaceRoot>-project-preferences.json`. These are runner-owned state files, not operator editing surfaces. Session snapshots remain in the normal host store under the runner user's Tau home.
61
+ A relative top-level `workspaceRoot` resolves from the Telegram config file's directory. Tau persists runner session records at `<workspaceRoot>-sessions.json` and per-chat preferences at `<workspaceRoot>-project-preferences.json`. These are runner-owned state files, not operator editing surfaces. Session snapshots remain in the normal host store under the runner user's Tau home.
62
62
 
63
63
  `maxSessions` counts queued, preparing, running, and waiting sessions across all configured bots. Failed records do not consume the active cap, but they remain visible to their owning chat until replaced or closed.
64
64
 
@@ -83,7 +83,7 @@ Use both lists for a private bot. `allowedUserIds` controls who can trigger work
83
83
 
84
84
  A bot sees only `allowedProjectIds`. If that field is omitted, it sees every configured project. A sole allowed project is selected automatically; otherwise a chat needs `defaultProjectId` or an explicit `/use_<project>` preference before `/new`.
85
85
 
86
- Tau registers eight built-in commands plus one `/use_<projectId>` command per visible project. A bot may expose at most 92 projects under Telegram's 100-command limit.
86
+ Tau registers ten built-in commands plus one `/use_<projectId>` command per visible project. A bot may expose at most 90 projects under Telegram's 100-command limit.
87
87
 
88
88
  ## Project IDs and common fields
89
89
 
@@ -236,8 +236,10 @@ The runner's speech-to-text provider is loaded from normal Tau config at runner
236
236
  | `/effort_xhigh` | Selects xhigh reasoning for later independent turns. |
237
237
  | `/compact` | Runs summary-only manual compaction while the session is idle. |
238
238
  | `/interrupt` | Interrupts the active Tau turn. |
239
+ | `/tts_on` | Enables a Gemini-generated voice note after each final assistant response. |
240
+ | `/tts_off` | Disables voice responses. |
239
241
 
240
- Project preferences are scoped to one bot and chat and survive restarts. A changed preference does not switch the active session; `/status` reports the difference.
242
+ Preferences are scoped to one bot and chat and survive restarts, projects, and sessions. A new project choice does not switch the active session; `/status` reports the difference.
241
243
 
242
244
  In groups, commands must explicitly mention the bot. Accepted forms include:
243
245
 
@@ -284,6 +286,8 @@ Mistral is the default provider. Configure credentials in the runner's normal Ta
284
286
 
285
287
  The environment variable wins for each speech provider. Audio without a usable key produces a user-facing error instead of entering a turn. See [credentials](credentials.md).
286
288
 
289
+ `/tts_on` uses `gemini-3.7-flash`, `gemini-3.1-flash-tts-preview`, Despina, the Google key, and runner `ffmpeg` with Opus. Source and rewritten text each allow 10,000 Unicode characters; audio allows 32 MiB. Rewrite and job timeouts are one and five minutes. Jobs are ephemeral. Failure sends `voice response failed. please try again.` without affecting text; details stay in logs.
290
+
287
291
  ## Command client tools
288
292
 
289
293
  Each Telegram session advertises the configured command client tools selected by normal Tau configuration for its prepared workspace. Global `clientTools` definitions provide executable behavior, while the workspace's most-specific `enabledClientTools` value selects an exact subset. An empty list disables all configured client tools for that workspace.
@@ -300,7 +304,7 @@ If a referenced repository workspace is missing, Tau reconstructs it from the ca
300
304
 
301
305
  If the connection is lost after Telegram submits a message, startup checks whether Tau accepted and completed it. Running work remains interruptible until it settles. A confirmed unaccepted message prompts the user to resend it; failed or blocked outcomes remain queued until delivery succeeds.
302
306
 
303
- Tau does not resend earlier assistant messages, notices, or unrelated old outcomes just because the runner restarted. New warning and error notices are delivered after recovery. A restart clears short-lived network retries, but notifications waiting to be delivered remain pending.
307
+ Restart does not replay responses. It clears voice jobs and short-lived retries, but pending notifications remain.
304
308
 
305
309
  If a failed session still has unresolved submitted work, Tau can reconnect to determine the outcome. Other failed sessions remain visible with their original diagnostic until the owning chat replaces or closes them. Do not edit runner state files to force recovery.
306
310
 
@@ -91,7 +91,7 @@ Tau starts Bash with `-lc` and the execution environment's `HOME`. A login shell
91
91
 
92
92
  There is no TTY and assistant `bash` calls have no stdin. Commands that prompt, open an interactive editor, or require terminal control will hang until timeout or fail. Use non-interactive flags and pass a `workingDirectory` rather than relying on a previous `cd`.
93
93
 
94
- Tau forces Git into non-interactive mode: terminal prompts and askpass interaction are disabled, editors are replaced, pagers are disabled, and SSH uses batch mode. Authentication therefore needs to be available non-interactively.
94
+ Tau sets `NO_COLOR=1`, `FORCE_COLOR=0`, `TERM=dumb`, and `PAGER=cat` for predictable non-interactive command output. It also forces Git into non-interactive mode: terminal prompts and askpass interaction are disabled, editors are replaced, pagers are disabled, and SSH uses batch mode. These fixed values override inherited and execution-environment values after login startup. A command can still assign its own environment explicitly. Authentication therefore needs to be available non-interactively.
95
95
 
96
96
  The default timeout is 60 seconds. Tau captures at most 1 MiB of merged stdout and stderr, preserving the tail when raw capture overflows. The default model-facing result limit is roughly 8,192 estimated tokens. When output exceeds it, Tau returns a roughly 2,048-token middle preview and a gating notice. The command has already run and its side effects have already happened.
97
97
 
@@ -189,8 +189,6 @@ Every Tau command uses a fresh non-interactive login Bash in the execution envir
189
189
 
190
190
  Use automation-safe command flags. Configure credentials before invocation, set Git and SSH up for noninteractive access, and avoid editors or tools that require terminal control. Shell aliases, variables, `cd`, and functions do not persist between calls, so pass `workingDirectory` or use a complete command each time.
191
191
 
192
- For stdio or SSH attachment, stdout from `tau rpc` is protocol-only. A login banner or wrapper message on stdout can look like malformed JSON, an unsupported message, or a timeout waiting for the ready message. Remove it or send diagnostics to stderr. Running the remote command directly can reveal startup diagnostics, but do not copy protocol output or secrets into reports.
193
-
194
192
  Local command sanitization removes inherited credential-shaped variable names. If a target command needs authentication, use the tool's own secure noninteractive credential mechanism rather than broad environment forwarding. Hosted targets use their own environment.
195
193
 
196
194
  ## WebSocket attachment is unauthorized or unsafe
@@ -219,15 +217,13 @@ Changing a resolver definition or credential requires a host restart. `/reload`
219
217
 
220
218
  Without `--session` or `--new`, attach needs a TTY for its selector. In automation, pass one explicitly. Normal local startup `--persona` flags are not attach options; choose the host default for new sessions or switch the attached session with `/persona:<id>` while idle.
221
219
 
222
- If an SSH attach closes when the TUI exits, that is expected: the attachment owns its one-shot `tau rpc` host. Use `tau serve` when work must continue after disconnect. See [remote sessions](remote-sessions.md).
223
-
224
220
  ## A session is missing, interrupted, or will not recover
225
221
 
226
222
  A selector shows only sessions this host can load and restore. Confirm its machine, OS user, home, Tau version, resolver configuration, and target still match the creator. Another user's `~/.config/tau/sessions` is a different store. Restore missing bridge/API definitions, credentials, local directory, sandbox, or Sprite. Never edit session JSON to substitute a target or `cwd`.
227
223
 
228
224
  Recovery returns idle, aborts unfinished turns, cancels running maintenance, removes live subagents, and blocks an active goal. Review the last assistant and tools, then safely check `!!pwd` and `!!git status --short`. Resume a goal only after understanding the stop. Retry continues current history without rerunning completed tools automatically.
229
225
 
230
- A WebSocket client disconnect does not interrupt the long-running host; server shutdown does. Closing a local TUI or stdio attachment shuts down its owned host, so interrupted recovery is expected.
226
+ A WebSocket client disconnect does not interrupt the long-running host; server shutdown does. Closing a local TUI shuts down its owned host, so interrupted recovery is expected.
231
227
 
232
228
  A newer storage version requires that Tau version or later. For invalid JSON, snapshot, or ID errors, preserve the file and exact error, stop competing hosts, and investigate normal recovery. Do not edit or delete it first. Newer Tau migrates supported older documents automatically.
233
229
 
@@ -283,6 +279,8 @@ Distinguish download, materialization, format, and transcription errors. The rep
283
279
 
284
280
  Successful audio turns echo `transcribed: …` before submission. In groups, non-triggering audio can be buffered for later mentioned context. If that is inappropriate for the chat, narrow `allowedChatIds` or avoid enabling the group.
285
281
 
282
+ Outgoing `/tts_on` voice responses always need `GEMINI_API_KEY` or `apiKeys.google`, even when incoming audio uses Mistral. They also require runner-side `ffmpeg` with Opus support. A generation or delivery failure sends `voice response failed. please try again.` while detailed diagnostics remain in runner logs. The original text response remains delivered.
283
+
286
284
  ## Telegram replies or notifications are delayed or missing
287
285
 
288
286
  Each outbound chunk has a deadline and retries retryable failures twice. Telegram `retry_after` is honored, and per-chat ordering holds later notifications. Large replies are split, so only a later chunk may have failed.
@@ -17,7 +17,7 @@ Tau creates a local execution environment rooted at that directory. A startup pe
17
17
  tau --persona gpt-5.6-sol-coder:high
18
18
  ```
19
19
 
20
- `-p` is the short form. `--no-agent-context-files` omits `AGENTS.md` and explicitly configured context files, and `--no-client-tools` prevents the TUI from advertising its built-in and configured [client tools](client-tools.md). On macOS, `--caffeinated` runs `caffeinate -i` while assistant turns are active. It is a no-op on Linux and is not an option for `tau attach`.
20
+ `-p` is the short form. `--no-agent-context-files` omits `AGENTS.md` and explicitly configured context files, and `--no-client-tools` prevents the TUI from advertising its built-in and configured [client tools](client-tools.md).
21
21
 
22
22
  Piped stdin becomes the first message in a local TUI session:
23
23
 
@@ -191,7 +191,7 @@ The session host supplies ephemeral review agents, while the local tool owns its
191
191
 
192
192
  The TUI also advertises diff review as a client tool unless `--no-client-tools` is set. Manual `/diff` remains a TUI command even when model-facing client tools are disabled. See [client tools](client-tools.md) for attachment and multiple-client implications.
193
193
 
194
- ## Use speech and keep-awake support
194
+ ## Use speech
195
195
 
196
196
  `/listen` and Ctrl+Y are currently macOS-only. Recording uses local `ffmpeg` with the AVFoundation audio input and stops when Ctrl+Y is pressed again, when Escape is pressed, or after five minutes. The transcript is inserted at the cursor for review and is not submitted automatically.
197
197
 
@@ -203,9 +203,7 @@ brew install ffmpeg
203
203
 
204
204
  Mistral is the default and needs `MISTRAL_API_KEY` or `apiKeys.mistral`. Set `speechToText.provider` to `gemini` to use `GEMINI_API_KEY` or `apiKeys.google` instead. These settings and credentials are read by the TUI process, including during remote attachment.
205
205
 
206
- `/speak` is also macOS-only. It rewrites the last assistant response for speech, generates audio with Gemini, and plays it through the local `afplay` command. It requires `GEMINI_API_KEY` or `apiKeys.google`, runs only while the session is idle, and can be stopped with Escape.
207
-
208
- `tau --caffeinated` keeps macOS awake only during active assistant turns in that local TUI. It does not keep a remote host awake, and it is not accepted by `tau attach`.
206
+ `/speak` is also macOS-only. It rewrites the last assistant response for speech, generates audio with Gemini, and plays it through the local `afplay` command. It requires `GEMINI_API_KEY` or `apiKeys.google`, runs only while the session is idle, and can be stopped with Escape. Speech source and rewritten text are limited to 10,000 Unicode characters, and generation stops after 32 MiB of raw audio.
209
207
 
210
208
  ## Reload the right component
211
209
 
@@ -221,4 +219,4 @@ Restart the TUI instead after changing client-owned themes, the diff launcher, s
221
219
  - `/prompt:<id>` fills the editor but does not submit it.
222
220
  - `/diff` records returned feedback but does not automatically ask the assistant to act on it.
223
221
  - `/reload` does not reload client themes or client tools.
224
- - Exiting a WebSocket attachment does not delete or necessarily stop the hosted session. Exiting a local TUI or one-shot stdio attachment also shuts down its owned host, so active work is interrupted and persisted before recovery where possible.
222
+ - Exiting a WebSocket attachment does not delete or necessarily stop the hosted session. Exiting a local TUI shuts down its owned host, so active work is interrupted and persisted before recovery where possible.