@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.
- package/dist/code_mode/command.js +26 -14
- package/dist/code_mode/command.js.map +1 -1
- package/dist/code_mode/index.d.ts +2 -1
- package/dist/code_mode/index.js +1 -0
- package/dist/code_mode/index.js.map +1 -1
- package/dist/core/cli.js +0 -11
- package/dist/core/cli.js.map +1 -1
- package/dist/core/client_tools/command_client_tools.js +236 -151
- package/dist/core/client_tools/command_client_tools.js.map +1 -1
- package/dist/core/config/schema.js +8 -2
- package/dist/core/config/schema.js.map +1 -1
- package/dist/core/history/history_manager.js +73 -7
- package/dist/core/history/history_manager.js.map +1 -1
- package/dist/core/history/local_history_store.js +73 -2
- package/dist/core/history/local_history_store.js.map +1 -1
- package/dist/core/history/remote_history_client.js +36 -6
- package/dist/core/history/remote_history_client.js.map +1 -1
- package/dist/core/modes/index.js +0 -1
- package/dist/core/modes/index.js.map +1 -1
- package/dist/core/static/tau_docs/client-tools.md +212 -12
- package/dist/core/static/tau_docs/config-reference.md +1 -1
- package/dist/core/static/tau_docs/configuration.md +1 -1
- package/dist/core/static/tau_docs/credentials.md +4 -4
- package/dist/core/static/tau_docs/history.md +6 -4
- package/dist/core/static/tau_docs/index.md +1 -1
- package/dist/core/static/tau_docs/node-sdk.md +33 -26
- package/dist/core/static/tau_docs/ownership-and-scope.md +3 -4
- package/dist/core/static/tau_docs/prompts-and-project-context.md +2 -2
- package/dist/core/static/tau_docs/remote-sessions.md +4 -47
- package/dist/core/static/tau_docs/security.md +2 -6
- package/dist/core/static/tau_docs/session-protocol-methods.md +48 -7
- package/dist/core/static/tau_docs/session-protocol.md +18 -18
- package/dist/core/static/tau_docs/sessions.md +6 -5
- package/dist/core/static/tau_docs/telegram.md +8 -4
- package/dist/core/static/tau_docs/tools.md +1 -1
- package/dist/core/static/tau_docs/troubleshooting.md +3 -5
- package/dist/core/static/tau_docs/tui.md +4 -6
- package/dist/core/telegram/adapter.js +226 -18
- package/dist/core/telegram/adapter.js.map +1 -1
- package/dist/core/telegram/config.js +1 -1
- package/dist/core/telegram/config.js.map +1 -1
- package/dist/core/telegram/project_preferences.js +42 -12
- package/dist/core/telegram/project_preferences.js.map +1 -1
- package/dist/core/telegram/runtime.js +6 -1
- package/dist/core/telegram/runtime.js.map +1 -1
- package/dist/core/telegram/session_manager.js +50 -4
- package/dist/core/telegram/session_manager.js.map +1 -1
- package/dist/core/telegram/tts.js +137 -0
- package/dist/core/telegram/tts.js.map +1 -0
- package/dist/core/tools/execution_backend.js +13 -3
- package/dist/core/tools/execution_backend.js.map +1 -1
- package/dist/core/tools/presentation.js +55 -17
- package/dist/core/tools/presentation.js.map +1 -1
- package/dist/core/utils/gemini_speech.js +123 -42
- package/dist/core/utils/gemini_speech.js.map +1 -1
- package/dist/core/utils/gemini_transcription.js +1 -1
- package/dist/core/version.js +1 -1
- package/dist/execution/cloudflare_sandbox_execution_environment.js +2 -2
- package/dist/execution/cloudflare_sandbox_execution_environment.js.map +1 -1
- package/dist/execution/fly_sprite_execution_environment.js +2 -2
- package/dist/execution/fly_sprite_execution_environment.js.map +1 -1
- package/dist/host/client_tool_broker.js +71 -17
- package/dist/host/client_tool_broker.js.map +1 -1
- package/dist/host/local_session_host.js +2 -2
- package/dist/host/local_session_host.js.map +1 -1
- package/dist/host/session_host.js.map +1 -1
- package/dist/host/session_protocol_handler.js +17 -6
- package/dist/host/session_protocol_handler.js.map +1 -1
- package/dist/main.js +18 -92
- package/dist/main.js.map +1 -1
- package/dist/protocol/session_protocol.d.ts +22 -2
- package/dist/protocol/session_protocol.js +47 -3
- package/dist/protocol/session_protocol.js.map +1 -1
- package/dist/sdk/client_tool_command.d.ts +41 -13
- package/dist/sdk/client_tool_command.js +157 -39
- package/dist/sdk/client_tool_command.js.map +1 -1
- package/dist/sdk/client_tool_presentation.d.ts +17 -0
- package/dist/sdk/client_tool_presentation.js +9 -0
- package/dist/sdk/client_tool_presentation.js.map +1 -0
- package/dist/sdk/code_mode.js +10 -1
- package/dist/sdk/code_mode.js.map +1 -1
- package/dist/sdk/index.d.ts +5 -4
- package/dist/sdk/index.js +2 -1
- package/dist/sdk/index.js.map +1 -1
- package/dist/sdk/session.js +28 -9
- package/dist/sdk/session.js.map +1 -1
- package/dist/sdk/types.d.ts +11 -1
- package/dist/transport/errors.d.ts +0 -11
- package/dist/transport/errors.js +0 -12
- package/dist/transport/errors.js.map +1 -1
- package/dist/transport/index.d.ts +1 -3
- package/dist/transport/index.js +1 -2
- package/dist/transport/index.js.map +1 -1
- package/dist/tui/session_chat_app.js +28 -15
- package/dist/tui/session_chat_app.js.map +1 -1
- package/dist/tui/session_chat_controller.js +0 -51
- package/dist/tui/session_chat_controller.js.map +1 -1
- package/dist/tui/speech_playback.js +3 -3
- package/dist/tui/speech_playback.js.map +1 -1
- package/package.json +2 -2
- package/dist/core/modes/rpc_server.js +0 -105
- package/dist/core/modes/rpc_server.js.map +0 -1
- package/dist/transport/stdio_session_transport.d.ts +0 -48
- package/dist/transport/stdio_session_transport.js +0 -338
- package/dist/transport/stdio_session_transport.js.map +0 -1
|
@@ -117,23 +117,222 @@ Diff-tool launcher settings are separate from command client-tool definitions. T
|
|
|
117
117
|
|
|
118
118
|
## Implement a command tool with Tau's helper
|
|
119
119
|
|
|
120
|
-
Command client tools use Tau's version
|
|
120
|
+
Command client tools use Tau's version 4 bidirectional NDJSON protocol over stdin and stdout. Use the exported helper instead of implementing framing manually:
|
|
121
121
|
|
|
122
122
|
```ts
|
|
123
|
-
import {
|
|
123
|
+
import {
|
|
124
|
+
runTauClientToolCommand,
|
|
125
|
+
truncateTauClientToolText,
|
|
126
|
+
} from "@markusylisiurunen/tau/code-mode";
|
|
127
|
+
|
|
128
|
+
await runTauClientToolCommand({
|
|
129
|
+
name: "notify_desktop",
|
|
130
|
+
describe(args) {
|
|
131
|
+
const input = args as { title: string; message: string };
|
|
132
|
+
return {
|
|
133
|
+
subject: truncateTauClientToolText(input.title),
|
|
134
|
+
};
|
|
135
|
+
},
|
|
136
|
+
async execute(args, context) {
|
|
137
|
+
const input = args as { title: string; message: string };
|
|
138
|
+
context.signal.throwIfAborted();
|
|
139
|
+
|
|
140
|
+
await showNotification(input.title, input.message, context.signal);
|
|
141
|
+
return {
|
|
142
|
+
content: "Notification displayed.",
|
|
143
|
+
presentation: {
|
|
144
|
+
subject: truncateTauClientToolText(input.title),
|
|
145
|
+
},
|
|
146
|
+
};
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
`describe` is optional. When present, it runs before acknowledgement and may return a partial running presentation containing `subject`, `subjectWrap`, `details`, or `metadata`. The execution result may independently include the same partial shape for the terminal card. Tau supplies every omitted field, owns lifecycle actions and the operation derived from the registered tool name, and renders a complete fallback when execution ends without a result.
|
|
152
|
+
|
|
153
|
+
Tau preserves every explicit presentation field up to the protocol safety limits; it does not apply display truncation or normalize client text. `truncateTauClientToolText` provides optional caller-controlled `maxLines`, `maxLineChars`, and `head` or `middle` truncation. Its defaults match Tau's concise subject policy, but callers may select larger or smaller positive limits.
|
|
154
|
+
|
|
155
|
+
For a subject, use the returned string directly. For a block of detail text, split the returned string on `\n` and map each line to one `details` entry:
|
|
156
|
+
|
|
157
|
+
```ts
|
|
158
|
+
const details = truncateTauClientToolText(output, {
|
|
159
|
+
maxLines: 7,
|
|
160
|
+
maxLineChars: 512,
|
|
161
|
+
strategy: "middle",
|
|
162
|
+
})
|
|
163
|
+
.split("\n")
|
|
164
|
+
.map((text) => ({ text }));
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Each detail or metadata entry is a single protocol line, so use `maxLines: 1` when assigning the helper's result directly to one entry. The helper shapes text for presentation; the protocol byte and collection limits still apply. Empty detail or metadata arrays explicitly suppress that phase's defaults.
|
|
168
|
+
|
|
169
|
+
`runTauClientToolCommand` reads the preparation, writes readiness and any running presentation, waits until the host accepts the call, then provides the standard execution context and writes the final result. It handles execution-environment request and cancellation framing and reacts to `SIGINT`, `SIGTERM`, and protocol input closure by aborting the handler.
|
|
170
|
+
|
|
171
|
+
Reserve stdout for the helper's protocol. Write diagnostics to stderr. Return a string or `{ content, presentation? }` for success. Return `{ ok: false, error, presentation? }` for a structured tool failure. Successful content and failure text become model-visible tool results.
|
|
172
|
+
|
|
173
|
+
### Version 4 frame reference
|
|
174
|
+
|
|
175
|
+
The shapes below use TypeScript notation. Serialize each frame as one exact JSON object followed by a newline; unknown fields are invalid.
|
|
124
176
|
|
|
125
|
-
|
|
126
|
-
const input = args as { title: string; message: string };
|
|
127
|
-
context.signal.throwIfAborted();
|
|
177
|
+
Tau starts the exchange by writing:
|
|
128
178
|
|
|
129
|
-
|
|
130
|
-
|
|
179
|
+
- `{ version: 4, type: "prepare", sessionId, agentId, callId, toolName, arguments }` exactly once. The identity fields are non-empty strings and `arguments` is the validated model input.
|
|
180
|
+
- `{ version: 4, type: "execute" }` after accepting the command's ready frame. This authorizes execution.
|
|
181
|
+
|
|
182
|
+
The command writes:
|
|
183
|
+
|
|
184
|
+
- `{ version: 4, type: "ready", presentation?: PresentationOverride }` exactly once after preparation.
|
|
185
|
+
- `{ version: 4, type: "result", ok: true, content, presentation?: PresentationOverride }` or `{ version: 4, type: "result", ok: false, error, presentation?: PresentationOverride }` exactly once after authorization. `content` and `error` are strings.
|
|
186
|
+
|
|
187
|
+
During authorized execution, the command may write `{ version: 4, type: "exec", requestId, command, options }`. The non-empty `command` string runs in the session execution environment. `options` is required and may contain `args: string[]`, `env: Record<string, string>`, base64-encoded string `stdinBase64`, string `cwd`, positive integer `timeoutMs`, and positive integer `maxCaptureBytes`.
|
|
188
|
+
|
|
189
|
+
Tau answers with the same `requestId` and either:
|
|
190
|
+
|
|
191
|
+
- `{ version: 4, type: "exec.result", requestId, ok: true, result: ExecResult }`
|
|
192
|
+
- `{ version: 4, type: "exec.result", requestId, ok: false, error: string }`
|
|
193
|
+
|
|
194
|
+
`ExecResult` contains string `output`, `stdout`, and `stderr`; nullable `exitCode` and `closeSignal`; and boolean `truncated`, `timedOut`, and `aborted`. A command may cancel one unresolved request with `{ version: 4, type: "exec.cancel", requestId }`. Request IDs must be non-empty strings and cannot be reused within a call.
|
|
195
|
+
|
|
196
|
+
### Implement the protocol directly in JavaScript
|
|
197
|
+
|
|
198
|
+
A JavaScript command can implement the version 4 handshake using only Node.js built-ins, without importing Tau or the code-mode package:
|
|
199
|
+
|
|
200
|
+
```js
|
|
201
|
+
#!/usr/bin/env node
|
|
202
|
+
|
|
203
|
+
import { arch, platform, release } from "node:os";
|
|
204
|
+
import { createInterface } from "node:readline";
|
|
205
|
+
|
|
206
|
+
const lines = createInterface({
|
|
207
|
+
input: process.stdin,
|
|
208
|
+
crlfDelay: Number.POSITIVE_INFINITY,
|
|
131
209
|
});
|
|
210
|
+
const input = lines[Symbol.asyncIterator]();
|
|
211
|
+
|
|
212
|
+
async function readFrame() {
|
|
213
|
+
const next = await input.next();
|
|
214
|
+
if (next.done) throw new Error("Tau closed the command protocol");
|
|
215
|
+
return JSON.parse(next.value);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
function writeFrame(frame) {
|
|
219
|
+
process.stdout.write(`${JSON.stringify(frame)}\n`);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
const prepare = await readFrame();
|
|
223
|
+
if (
|
|
224
|
+
prepare.version !== 4 ||
|
|
225
|
+
prepare.type !== "prepare" ||
|
|
226
|
+
prepare.toolName !== "system_info"
|
|
227
|
+
) {
|
|
228
|
+
throw new Error("Invalid system_info preparation");
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
writeFrame({
|
|
232
|
+
version: 4,
|
|
233
|
+
type: "ready",
|
|
234
|
+
presentation: {
|
|
235
|
+
subject: "local system",
|
|
236
|
+
},
|
|
237
|
+
});
|
|
238
|
+
|
|
239
|
+
const execute = await readFrame();
|
|
240
|
+
if (execute.version !== 4 || execute.type !== "execute") {
|
|
241
|
+
throw new Error("Invalid system_info authorization");
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
writeFrame({
|
|
245
|
+
version: 4,
|
|
246
|
+
type: "exec",
|
|
247
|
+
requestId: "git-status",
|
|
248
|
+
command: "git status --short",
|
|
249
|
+
options: {
|
|
250
|
+
maxCaptureBytes: 256 * 1024,
|
|
251
|
+
},
|
|
252
|
+
});
|
|
253
|
+
|
|
254
|
+
const response = await readFrame();
|
|
255
|
+
if (
|
|
256
|
+
response.version !== 4 ||
|
|
257
|
+
response.type !== "exec.result" ||
|
|
258
|
+
response.requestId !== "git-status"
|
|
259
|
+
) {
|
|
260
|
+
throw new Error("Invalid execution-environment response");
|
|
261
|
+
}
|
|
262
|
+
if (!response.ok) throw new Error(response.error);
|
|
263
|
+
|
|
264
|
+
const localSystem = `${platform()} ${release()} ${arch()}`;
|
|
265
|
+
const workspaceStatus =
|
|
266
|
+
response.result.output.trim() || "Working tree is clean.";
|
|
267
|
+
writeFrame({
|
|
268
|
+
version: 4,
|
|
269
|
+
type: "result",
|
|
270
|
+
ok: true,
|
|
271
|
+
content: `${localSystem}\n\n${workspaceStatus}`,
|
|
272
|
+
presentation: {
|
|
273
|
+
subject: "local system",
|
|
274
|
+
},
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
lines.close();
|
|
132
278
|
```
|
|
133
279
|
|
|
134
|
-
`
|
|
280
|
+
The `exec` frame asks Tau to run `git status --short` in the session execution environment, which may be a different machine from the JavaScript process. Tau returns the matching `exec.result` on stdin. Request IDs are single-use, and the command must check both the ID and `ok` before consuming the result.
|
|
281
|
+
|
|
282
|
+
Make the file executable with `chmod +x`. Diagnostics and uncaught errors go to stderr; stdout remains reserved for protocol frames.
|
|
283
|
+
|
|
284
|
+
### Implement a simple command tool in Bash
|
|
285
|
+
|
|
286
|
+
A small command that needs only client-machine authority can also implement the handshake in Bash. This example depends on `jq` for safe JSON parsing and encoding:
|
|
287
|
+
|
|
288
|
+
```bash
|
|
289
|
+
#!/usr/bin/env bash
|
|
290
|
+
set -euo pipefail
|
|
291
|
+
|
|
292
|
+
IFS= read -r prepare
|
|
293
|
+
jq -e '
|
|
294
|
+
.version == 4 and
|
|
295
|
+
.type == "prepare" and
|
|
296
|
+
.toolName == "system_info"
|
|
297
|
+
' >/dev/null <<<"$prepare"
|
|
298
|
+
|
|
299
|
+
jq -cn '{
|
|
300
|
+
version: 4,
|
|
301
|
+
type: "ready",
|
|
302
|
+
presentation: {
|
|
303
|
+
subject: "local system"
|
|
304
|
+
}
|
|
305
|
+
}'
|
|
306
|
+
|
|
307
|
+
IFS= read -r execute
|
|
308
|
+
jq -e '.version == 4 and .type == "execute"' >/dev/null <<<"$execute"
|
|
309
|
+
|
|
310
|
+
content=$(uname -a)
|
|
311
|
+
jq -cn --arg content "$content" '{
|
|
312
|
+
version: 4,
|
|
313
|
+
type: "result",
|
|
314
|
+
ok: true,
|
|
315
|
+
content: $content
|
|
316
|
+
}'
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
Configure either executable as an argument-free command tool:
|
|
320
|
+
|
|
321
|
+
```json
|
|
322
|
+
{
|
|
323
|
+
"name": "system_info",
|
|
324
|
+
"defaultEnabled": true,
|
|
325
|
+
"description": "Report operating-system information from the client machine.",
|
|
326
|
+
"parameters": {
|
|
327
|
+
"type": "object",
|
|
328
|
+
"properties": {},
|
|
329
|
+
"additionalProperties": false
|
|
330
|
+
},
|
|
331
|
+
"command": "./bin/tau-system-info"
|
|
332
|
+
}
|
|
333
|
+
```
|
|
135
334
|
|
|
136
|
-
|
|
335
|
+
Both `ready.presentation` and `result.presentation` are optional partial objects with `subject`, `subjectWrap`, `details`, and `metadata`. The ready value applies while the call runs; the result value applies only to its terminal state. Omit either object, or any field within it, to use Tau's default for that phase. Empty `details` or `metadata` arrays suppress the corresponding default field. The script must emit `ready` before reading the authorization-bearing `execute` frame. Direct implementations can emit the same `exec` frames shown in the JavaScript example, but the TypeScript helper is preferable when the tool needs multiple target-environment requests, cancellation forwarding, or more involved protocol handling.
|
|
137
336
|
|
|
138
337
|
The handler receives:
|
|
139
338
|
|
|
@@ -181,7 +380,7 @@ Tau exports two higher-level helpers for client tools that expose a bounded Java
|
|
|
181
380
|
|
|
182
381
|
For an executable configured through `clientTools`, keep the exact parameters schema to one required `code` string with no additional properties, then call `runTauCodeModeCommand` in the executable. For SDK clients, pass the returned tool from `createTauCodeModeClientTool` in the client's `clientTools` array.
|
|
183
382
|
|
|
184
|
-
Both helpers supply the invocation identities, cancellation signal, execution-environment facade, progressive `docs` value, bounded API bridge, and agent-scoped scratch files. The model-facing description remains explicit caller input. Use Tau's optional shared description builder only when its progressive-disclosure wording fits the tool; Tau does not silently rewrite a configured description.
|
|
383
|
+
Both helpers supply the invocation identities, cancellation signal, execution-environment facade, progressive `docs` value, bounded API bridge, and agent-scoped scratch files. They use the submitted code, concisely truncated and character-wrapped, as the running and terminal tool-card subject. The model-facing description remains explicit caller input. Use Tau's optional shared description builder only when its progressive-disclosure wording fits the tool; Tau does not silently rewrite a configured description.
|
|
185
384
|
|
|
186
385
|
The generic code-mode runtime is documented through its exported types and generated tool documentation. Do not layer another unbounded process or network channel behind it without making that authority clear in the tool description.
|
|
187
386
|
|
|
@@ -195,12 +394,13 @@ The command protocol is intentionally bounded:
|
|
|
195
394
|
- Captured stderr is limited to 1 MiB. Exceeding it terminates the command and fails the tool.
|
|
196
395
|
- Execution-environment stdin is limited to 16 MiB decoded, and capture can be requested up to 24 MiB per execution.
|
|
197
396
|
- At most eight execution requests may be unresolved concurrently.
|
|
397
|
+
- Each client-tool presentation override is limited to 1 MiB in total. Its subject is limited to 256 KiB; metadata values to 16 KiB each; detail values to 256 KiB each; and detail and metadata collections to 1,024 entries each. These are safety limits, not recommended UI sizes. Tau preserves explicit values within those limits. Clients may use the exported helper when they want a concise preview.
|
|
198
398
|
|
|
199
|
-
The configured `executionTimeoutMs` covers
|
|
399
|
+
The configured `executionTimeoutMs` covers preparation and execution and defaults to 60 seconds. The host also requires the owning client to prepare and acknowledge a dispatched call promptly. Command executables emit readiness and any bounded running presentation before acknowledgement, then wait for Tau to authorize execution.
|
|
200
400
|
|
|
201
401
|
Tau starts each configured command in a detached process group. Cancellation sends termination to the group and escalates to `SIGKILL` after a short grace period, even if the original group leader exits first. The helper aborts pending execution-environment requests and stops accepting work when stdin closes.
|
|
202
402
|
|
|
203
|
-
A successful
|
|
403
|
+
A successful protocol exchange must emit one version 4 ready frame, wait for the execute frame, emit one final version 4 result with `ok: true` or `ok: false`, and exit with status zero. An `ok: false` frame is a communicated tool failure; process and framing failures still use stderr and a nonzero exit. Missing or duplicate readiness, execution data before authorization, missing results, malformed framing, data after the result, reused execution request IDs, timeout, cancellation, excessive output, and protocol-limit violations fail the call.
|
|
204
404
|
|
|
205
405
|
## Disconnects, reconnects, and durability
|
|
206
406
|
|
|
@@ -222,7 +222,7 @@ A global-only remote history target:
|
|
|
222
222
|
|
|
223
223
|
| Nested field | Type | Required | Contract |
|
|
224
224
|
| --- | --- | --- | --- |
|
|
225
|
-
| `endpoint` | Non-empty string | Yes | HTTP(S) URL with no query or fragment |
|
|
225
|
+
| `endpoint` | Non-empty string | Yes | HTTP(S) URL with no credentials, query, or fragment |
|
|
226
226
|
| `apiKey` | Non-empty string | No | Inline service API key |
|
|
227
227
|
| `apiKeyEnv` | Non-empty string | No | Host environment variable containing the key |
|
|
228
228
|
|
|
@@ -185,7 +185,7 @@ Restart the host process to apply settings used to construct host-wide services,
|
|
|
185
185
|
- `history`
|
|
186
186
|
- host environment variables and Codex account forcing
|
|
187
187
|
|
|
188
|
-
For `tau serve
|
|
188
|
+
For `tau serve`, make the changes on the host machine and restart the server. Restarting only an attached TUI does not rebuild the host.
|
|
189
189
|
|
|
190
190
|
### New session or runner
|
|
191
191
|
|
|
@@ -19,10 +19,10 @@ Common cases are:
|
|
|
19
19
|
| Nook host tool | Session host |
|
|
20
20
|
| Cloudflare Sandbox bridge and Fly Sprite API | Session host startup |
|
|
21
21
|
| `/listen` and `/speak` | TUI client |
|
|
22
|
-
| Telegram transcription | Telegram runner |
|
|
22
|
+
| Telegram transcription and voice responses | Telegram runner |
|
|
23
23
|
| `tau tool pdf-unpack` | The process running that command |
|
|
24
24
|
|
|
25
|
-
With local `tau`, these roles normally share one machine. With `tau attach`, setting a key only in the attached client's shell does not authenticate the remote host. Run `tau auth` on the host machine and set host-owned environment variables where `tau serve
|
|
25
|
+
With local `tau`, these roles normally share one machine. With `tau attach`, setting a key only in the attached client's shell does not authenticate the remote host. Run `tau auth` on the host machine and set host-owned environment variables where `tau serve` or the SDK host actually runs. See [ownership and scope](ownership-and-scope.md) for the full boundary.
|
|
26
26
|
|
|
27
27
|
## Provider API keys
|
|
28
28
|
|
|
@@ -61,12 +61,12 @@ Several Tau features share provider credentials but intentionally prefer a fixed
|
|
|
61
61
|
| Feature | Resolution order |
|
|
62
62
|
| --- | --- |
|
|
63
63
|
| Exa web search and fetch | `EXA_API_KEY`, then `apiKeys.exa` |
|
|
64
|
-
| Google speech, Gemini speech-to-text,
|
|
64
|
+
| Google speech, Gemini speech-to-text, Telegram Gemini transcription, and Telegram voice responses | `GEMINI_API_KEY`, then `apiKeys.google` |
|
|
65
65
|
| Mistral speech-to-text, Telegram Mistral transcription, and PDF OCR | `MISTRAL_API_KEY`, then `apiKeys.mistral` |
|
|
66
66
|
|
|
67
67
|
The Google and Mistral rows describe feature-specific helpers. Model calls follow the general model-authentication order instead, where the configured provider key wins over ambient environment authentication.
|
|
68
68
|
|
|
69
|
-
`web.discover` does not require Exa. `web.search` and `web.fetch` do. `/speak`
|
|
69
|
+
`web.discover` does not require Exa. `web.search` and `web.fetch` do. `/speak` and Telegram `/tts_on` voice responses use Google. `/listen` and incoming Telegram audio use the configured `speechToText.provider`, which is `mistral` unless configuration selects `gemini`. PDF OCR through `tau tool pdf-unpack` uses Mistral.
|
|
70
70
|
|
|
71
71
|
Set these variables on the process that owns the feature. For example, a remote TUI's `/speak` reads the attached client's `GEMINI_API_KEY`, while a Google model selected by the session reads credentials at the host.
|
|
72
72
|
|
|
@@ -12,7 +12,7 @@ Every Tau host opens a machine-local SQLite database at:
|
|
|
12
12
|
~/.config/tau/history.sqlite
|
|
13
13
|
```
|
|
14
14
|
|
|
15
|
-
The path belongs to the **host home**. An attached TUI and a remote execution environment do not get separate history stores merely because they participate in the session. Local `tau`, `tau serve`,
|
|
15
|
+
The path belongs to the **host home**. An attached TUI and a remote execution environment do not get separate history stores merely because they participate in the session. Local `tau`, `tau serve`, and the default SDK host all use the host machine's database.
|
|
16
16
|
|
|
17
17
|
For each session, history stores its immutable creation attributes and an ordered active transcript containing:
|
|
18
18
|
|
|
@@ -99,7 +99,7 @@ Remote history is accepted only in the host's eligible global Tau config, normal
|
|
|
99
99
|
}
|
|
100
100
|
```
|
|
101
101
|
|
|
102
|
-
`endpoint` must be an HTTP or HTTPS URL without a query or hash. Tau removes trailing slashes. The API key resolves on the host in this order:
|
|
102
|
+
`endpoint` must be an HTTP or HTTPS URL without credentials, a query, or a hash. Tau removes trailing slashes. The API key resolves on the host in this order:
|
|
103
103
|
|
|
104
104
|
1. `TAU_HISTORY_API_KEY`
|
|
105
105
|
2. the host environment variable named by `history.apiKeyEnv`
|
|
@@ -118,7 +118,9 @@ Remote replication is local-first:
|
|
|
118
118
|
3. The host sends pending operations to the configured endpoint asynchronously.
|
|
119
119
|
4. Successful acknowledgements remove those operations from the outbox.
|
|
120
120
|
|
|
121
|
-
A service outage does not block session execution or local transcript capture. Pending operations remain durable and are retried when replication is scheduled again, including after host restart or later history activity. The remote service applies operations idempotently
|
|
121
|
+
A service outage does not block session execution or local transcript capture. Pending operations remain durable and are retried when replication is scheduled again, including after host restart or later history activity. The remote service applies operations idempotently. Tau preserves operation order within each session while processing separate session lanes independently.
|
|
122
|
+
|
|
123
|
+
A permanent operation-domain rejection, such as conflicting immutable session metadata, quarantines only that session's replication lane. Its pending operations and diagnostic remain in local SQLite, later operations for that session stay blocked, and unrelated sessions continue replicating. Transient transport, authentication, rate-limit, and service failures do not quarantine a lane; they leave endpoint replication pending for a later retry. Both kinds of failure produce a structured `history_replication_failed` host log without exposing the API key.
|
|
122
124
|
|
|
123
125
|
Local entries retain their complete captured payloads. For remote replication, an entry larger than 1 MiB keeps its identity and metadata but middle-truncates oversized content, arguments, or results with an explicit marker. Remote history is therefore useful for retrieval, but the host's local entry can contain details that the shared copy intentionally omits.
|
|
124
126
|
|
|
@@ -144,7 +146,7 @@ Cloudflare operational failures are visible through normal Worker logs, Cron Eve
|
|
|
144
146
|
|
|
145
147
|
**The history tool returns a service error while the session still works.** Remote queries and asynchronous replication can fail independently of session execution. Check endpoint reachability and Worker logs without printing the bearer key. Local capture should continue unless the session also contains a `history unavailable` warning.
|
|
146
148
|
|
|
147
|
-
**A session does not appear in remote search.** Confirm that the host was restarted with the global remote config, that the session was opened while that target was active, and that later history activity has had a chance to flush the durable outbox. Do not assume remote digests are immediate.
|
|
149
|
+
**A session does not appear in remote search.** Confirm that the host was restarted with the global remote config, that the session was opened while that target was active, and that later history activity has had a chance to flush the durable outbox. Check host logs for `history_replication_failed`; a quarantined failure affects only the named session, while an unquarantined endpoint failure remains retryable. Do not assume remote digests are immediate.
|
|
148
150
|
|
|
149
151
|
**Local history became unavailable.** Check host-side filesystem access, free space, and ownership for `~/.config/tau`. Restarting is required to reopen a manager disabled by an earlier local failure.
|
|
150
152
|
|
|
@@ -34,7 +34,7 @@ The intrinsic `tau_docs` tool reads one exact Markdown path at a time. It does n
|
|
|
34
34
|
|
|
35
35
|
- [Tools](tools.md) explains built-in tool availability, execution, cancellation, and code-mode tools.
|
|
36
36
|
- [Sessions](sessions.md) covers creation, turns, queueing, compaction, rewind, goals, recovery, and persistence.
|
|
37
|
-
- [Remote sessions](remote-sessions.md) explains `serve`, `
|
|
37
|
+
- [Remote sessions](remote-sessions.md) explains `serve`, `attach`, remote paths, and transport authentication.
|
|
38
38
|
- [History](history.md) covers local transcript history, optional remote replication, and the history tool.
|
|
39
39
|
- [Nook](nook.md) explains configuration and operation of the optional static mini-app platform.
|
|
40
40
|
- [Telegram](telegram.md) covers runner configuration, projects, workspaces, routing, and recovery.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Node SDK
|
|
2
2
|
|
|
3
|
-
Tau's Node SDK provides a typed client for creating, observing, and controlling sessions without implementing the wire protocol directly. Use the in-process client when your application should own the host, the WebSocket client for a long-running `tau serve` host, or the transport adapter
|
|
3
|
+
Tau's Node SDK provides a typed client for creating, observing, and controlling sessions without implementing the wire protocol directly. Use the in-process client when your application should own the host, the WebSocket client for a long-running `tau serve` host, or the transport adapter with a custom connection implementation.
|
|
4
4
|
|
|
5
5
|
The SDK uses the same public [session protocol](session-protocol.md) as the TUI. Session behavior is therefore consistent across local applications, remote integrations, and terminal clients.
|
|
6
6
|
|
|
@@ -74,23 +74,7 @@ WebSocket authentication grants full session access. Deployment and TLS guidance
|
|
|
74
74
|
|
|
75
75
|
### Supply a protocol transport
|
|
76
76
|
|
|
77
|
-
`createTauSdkClientFromTransport(transport, options?)` builds the same client facade over any `SessionProtocolTransport`.
|
|
78
|
-
|
|
79
|
-
```ts
|
|
80
|
-
import { spawn } from "node:child_process";
|
|
81
|
-
import {
|
|
82
|
-
StdioSessionProtocolTransport,
|
|
83
|
-
createTauSdkClientFromTransport,
|
|
84
|
-
} from "@markusylisiurunen/tau/sdk";
|
|
85
|
-
|
|
86
|
-
const child = spawn("tau", ["rpc"], {
|
|
87
|
-
stdio: ["pipe", "pipe", "pipe"],
|
|
88
|
-
});
|
|
89
|
-
const transport = new StdioSessionProtocolTransport(child);
|
|
90
|
-
const client = await createTauSdkClientFromTransport(transport);
|
|
91
|
-
```
|
|
92
|
-
|
|
93
|
-
The stdio transport owns the supplied process connection and terminates it on close. Stdout must contain only protocol NDJSON; stderr is retained for bounded process diagnostics.
|
|
77
|
+
`createTauSdkClientFromTransport(transport, options?)` builds the same client facade over any `SessionProtocolTransport`. This keeps the SDK facade independent of WebSocket and allows applications to supply another transport without changing session semantics.
|
|
94
78
|
|
|
95
79
|
A custom transport implements:
|
|
96
80
|
|
|
@@ -295,6 +279,11 @@ If rendering `timeline.item`, accept only the active epoch and merge by its allo
|
|
|
295
279
|
Pass `TauSdkClientTool` entries in `clientTools` when model-facing work must run in the integration process:
|
|
296
280
|
|
|
297
281
|
```ts
|
|
282
|
+
import {
|
|
283
|
+
createTauSdkClient,
|
|
284
|
+
truncateTauClientToolText,
|
|
285
|
+
} from "@markusylisiurunen/tau/sdk";
|
|
286
|
+
|
|
298
287
|
const client = await createTauSdkClient({
|
|
299
288
|
clientTools: [
|
|
300
289
|
{
|
|
@@ -303,12 +292,22 @@ const client = await createTauSdkClient({
|
|
|
303
292
|
description: "Choose one item from the user's local workspace.",
|
|
304
293
|
parameters: {
|
|
305
294
|
type: "object",
|
|
306
|
-
properties: {
|
|
295
|
+
properties: {
|
|
296
|
+
choice: { type: "string" },
|
|
297
|
+
},
|
|
298
|
+
required: ["choice"],
|
|
307
299
|
additionalProperties: false,
|
|
308
300
|
},
|
|
309
301
|
executionTimeoutMs: 60_000,
|
|
310
302
|
},
|
|
311
|
-
|
|
303
|
+
describe: (args) => {
|
|
304
|
+
const input = args as { choice: string };
|
|
305
|
+
return {
|
|
306
|
+
subject: truncateTauClientToolText(input.choice),
|
|
307
|
+
};
|
|
308
|
+
},
|
|
309
|
+
execute: async (args, context) => {
|
|
310
|
+
const input = args as { choice: string };
|
|
312
311
|
context.signal.throwIfAborted();
|
|
313
312
|
const status = await context.executionEnvironment.exec(
|
|
314
313
|
"git status --short",
|
|
@@ -316,7 +315,12 @@ const client = await createTauSdkClient({
|
|
|
316
315
|
signal: context.signal,
|
|
317
316
|
},
|
|
318
317
|
);
|
|
319
|
-
return
|
|
318
|
+
return {
|
|
319
|
+
content: status.output || "Working tree is clean.",
|
|
320
|
+
presentation: {
|
|
321
|
+
subject: truncateTauClientToolText(input.choice),
|
|
322
|
+
},
|
|
323
|
+
};
|
|
320
324
|
},
|
|
321
325
|
},
|
|
322
326
|
],
|
|
@@ -325,7 +329,11 @@ const client = await createTauSdkClient({
|
|
|
325
329
|
|
|
326
330
|
The handler receives `sessionId`, owning `agentId`, `callId`, an `AbortSignal`, and an execution-environment facade. The handler itself runs on the client machine. `context.executionEnvironment.exec()` crosses the session boundary and runs in the session execution environment.
|
|
327
331
|
|
|
328
|
-
|
|
332
|
+
`describe` is optional. When present, the SDK calls it with the arguments and a reduced context containing `sessionId`, `agentId`, `callId`, and `signal` before acknowledgement. This context deliberately has no execution-environment facade. It may return a partial running presentation containing `subject`, `subjectWrap`, `details`, or `metadata`. Tau owns action and operation, fills every omitted field, and acknowledges the resolved presentation before calling `execute`.
|
|
333
|
+
|
|
334
|
+
The execution result may independently include the same partial shape for the terminal card. Return a string or `{ content, presentation? }` for success, or `{ ok: false, error, presentation? }` for a structured failure. Omitted presentation fields use Tau's terminal defaults; empty detail or metadata arrays suppress those defaults. If `describe` throws, the SDK reports a preparation error without calling `execute`. If the client never returns a result because of cancellation, timeout, detach, or another failure, the host produces a complete fallback presentation.
|
|
335
|
+
|
|
336
|
+
Tau preserves every explicit presentation field up to the protocol safety limits; it does not apply display truncation or normalize client text. `truncateTauClientToolText` provides optional caller-controlled line, character, and head or middle truncation. Use its result directly for a subject. For a block of detail text, split the result on `\n` and map each line to one `details` entry; use `maxLines: 1` when assigning it directly to one detail or metadata entry. The helper shapes text but does not replace protocol validation. The SDK aborts handlers on host cancellation, client close, or terminal transport failure. `client.close()` waits for active handlers to settle.
|
|
329
337
|
|
|
330
338
|
Tool definitions are frozen for each assistant turn and remain independent of persona tool allowlists. Names cannot collide with host tools or another observing client's tools. See [client tools](client-tools.md) for authority, limits, command-backed tools, and disconnect behavior.
|
|
331
339
|
|
|
@@ -353,7 +361,7 @@ const tickets = createTauCodeModeClientTool({
|
|
|
353
361
|
});
|
|
354
362
|
```
|
|
355
363
|
|
|
356
|
-
Pass `tickets` in `clientTools`. Generated code receives the declared API namespace, progressively disclosed `docs`, console output, live `Date` and `Math`, and agent-scoped scratch files when invoked as a client tool. API calls cross a bounded JSON bridge. The tool description remains explicit caller input; the builder is optional.
|
|
364
|
+
Pass `tickets` in `clientTools`. Generated code receives the declared API namespace, progressively disclosed `docs`, console output, live `Date` and `Math`, and agent-scoped scratch files when invoked as a client tool. API calls cross a bounded JSON bridge. The submitted code appears, concisely truncated and character-wrapped, as the running and terminal tool-card subject. The tool description remains explicit caller input; the builder is optional.
|
|
357
365
|
|
|
358
366
|
The SDK also exports `executeTauCodeMode` for standalone execution. The separate `@markusylisiurunen/tau/code-mode` entry point additionally exports file-capability types, `runTauClientToolCommand`, and `runTauCodeModeCommand` for command-backed tools. Use the helpers instead of implementing their framing manually.
|
|
359
367
|
|
|
@@ -361,7 +369,7 @@ The SDK also exports `executeTauCodeMode` for standalone execution. The separate
|
|
|
361
369
|
|
|
362
370
|
Most turn and mutation methods do not accept an `AbortSignal`. Call `session.interrupt()` to cancel active host work. `session.exec()` is the exception: its optional signal targets only that execution.
|
|
363
371
|
|
|
364
|
-
`session.unobserve()` retires one facade. `client.close()` retires the connection, rejects pending transport requests, aborts client-tool handlers, waits for them to settle, and then closes the transport. For the default in-process client it also persists sessions and shuts down the owned host. For WebSocket it leaves the remote host and sessions running.
|
|
372
|
+
`session.unobserve()` retires one facade. `client.close()` retires the connection, rejects pending transport requests, aborts client-tool handlers, waits for them to settle, and then closes the transport. For the default in-process client it also persists sessions and shuts down the owned host. For WebSocket it leaves the remote host and sessions running.
|
|
365
373
|
|
|
366
374
|
Always close clients in `finally`. Do not continue using a session facade after unobserve or any client after close.
|
|
367
375
|
|
|
@@ -371,7 +379,6 @@ All exported SDK and transport errors extend `TauSessionClientError`:
|
|
|
371
379
|
|
|
372
380
|
- `TauSessionProtocolResponseError` means the host returned a protocol error. It exposes `code`, `message`, `requestId`, and optional `data`.
|
|
373
381
|
- `TauTransportError` means connection setup, framing, version validation, timeout, closure, or another terminal transport operation failed.
|
|
374
|
-
- `TauProcessError` extends `TauTransportError` for a stdio subprocess failure and includes `exitCode`, `signal`, and bounded `stderr`.
|
|
375
382
|
|
|
376
383
|
Branch on a protocol error's `code`, not its message. A successful request can still return a failed, aborted, or blocked turn outcome, so inspect `result.turn.status` separately.
|
|
377
384
|
|
|
@@ -384,7 +391,7 @@ The SDK entry point exports the types needed at integration boundaries rather th
|
|
|
384
391
|
- `TauSdkClient`, `TauSdkSession`, client option types, session summaries, and request and result aliases;
|
|
385
392
|
- `TauSdkDelta`, `SessionProtocolSnapshot`, pending-message types, subagent-activity types, and ephemeral event types;
|
|
386
393
|
- `TauSdkClientTool`, its execution context and environment facade, and code-mode definition and result types;
|
|
387
|
-
- `SessionProtocolTransport`, listener types, WebSocket options,
|
|
394
|
+
- `SessionProtocolTransport`, listener types, WebSocket options, and transport errors.
|
|
388
395
|
|
|
389
396
|
It also exports `applySessionProtocolDelta`, `applySessionProtocolSubagentActivitiesMessage`, the turn-ledger helpers, and user-text projection helpers:
|
|
390
397
|
|
|
@@ -12,7 +12,7 @@ Client tools execute on the client machine, not wherever the agent's Bash tool r
|
|
|
12
12
|
|
|
13
13
|
### Host
|
|
14
14
|
|
|
15
|
-
The **host** creates, observes, persists, and recovers sessions. It owns model calls, credentials, session orchestration, tool binding, history storage, and execution-environment lifecycle. Local `tau` creates an in-process host. `tau serve`
|
|
15
|
+
The **host** creates, observes, persists, and recovers sessions. It owns model calls, credentials, session orchestration, tool binding, history storage, and execution-environment lifecycle. Local `tau` creates an in-process host. `tau serve` is the standalone host entry point.
|
|
16
16
|
|
|
17
17
|
The host's home owns data such as session snapshots, authentication storage, usage logs, and the local history database. Use Tau commands and session operations to manage these stores rather than editing their files directly.
|
|
18
18
|
|
|
@@ -38,10 +38,9 @@ For repository and composite projects it prepares managed workspaces. A configur
|
|
|
38
38
|
| --- | --- | --- | --- |
|
|
39
39
|
| `tau` | Local TUI process | In-process on the same machine | Local `cwd` where Tau started |
|
|
40
40
|
| `tau attach … ws://…` | Machine running `tau attach` | Machine running `tau serve` | Environment selected or restored by that host |
|
|
41
|
-
| `tau
|
|
42
|
-
| `tau rpc` or `tau serve` | A separate protocol client | The server process | Local or configured hosted environment chosen by the client |
|
|
41
|
+
| `tau serve` | A separate protocol client | The server process | Local or configured hosted environment chosen by the client |
|
|
43
42
|
| Default Node SDK client | SDK caller | In-process with the SDK caller | Usually a local environment supplied at session creation |
|
|
44
|
-
| SDK over WebSocket
|
|
43
|
+
| SDK over WebSocket | SDK caller | Remote server | Environment selected or restored by that host |
|
|
45
44
|
| `tau telegram` | Telegram runner | In-process on the runner machine | Prepared project workspace or persistent directory |
|
|
46
45
|
|
|
47
46
|
A Cloudflare Sandbox or Fly Sprite can place the execution environment on another target while the host stays on its own machine. The host keeps provider credentials and orchestration authority; the target owns its paths and commands.
|
|
@@ -139,7 +139,7 @@ tau --no-agent-context-files
|
|
|
139
139
|
|
|
140
140
|
This disables ancestor `AGENTS.md` injection, configured `agentContextFiles`, and the descendant paths-only scan. It does not disable personas, prompt templates, or [skills](skills.md).
|
|
141
141
|
|
|
142
|
-
The option applies to local TUI sessions and to hosts started with `tau
|
|
142
|
+
The option applies to local TUI sessions and to hosts started with `tau serve`. For the Node SDK, `noAgentContextFiles: true` provides the same host-level behavior. An attached client cannot retroactively change how an existing remote host session was created.
|
|
143
143
|
|
|
144
144
|
## Alternate subagent working directories
|
|
145
145
|
|
|
@@ -176,6 +176,6 @@ For a new local TUI session, debug mode prints discovered content, loaded contex
|
|
|
176
176
|
tau --debug --persona release-coder
|
|
177
177
|
```
|
|
178
178
|
|
|
179
|
-
Add `--no-agent-context-files` to verify the context-free variant. Debug mode is TUI startup functionality and is not available with `tau
|
|
179
|
+
Add `--no-agent-context-files` to verify the context-free variant. Debug mode is TUI startup functionality and is not available with `tau serve`.
|
|
180
180
|
|
|
181
181
|
If expected context is missing, verify the execution-environment `cwd` and `home`, not just the attached client's current directory. Then check exact filenames, canonical path eligibility, configuration-level path bases, scan exclusions, and reload warnings. See [troubleshooting](troubleshooting.md) for broader diagnostics.
|