@markusylisiurunen/tau 0.3.50 → 0.3.51

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 (88) 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/modes/index.js +0 -1
  11. package/dist/core/modes/index.js.map +1 -1
  12. package/dist/core/static/tau_docs/client-tools.md +212 -12
  13. package/dist/core/static/tau_docs/configuration.md +1 -1
  14. package/dist/core/static/tau_docs/credentials.md +4 -4
  15. package/dist/core/static/tau_docs/history.md +1 -1
  16. package/dist/core/static/tau_docs/index.md +1 -1
  17. package/dist/core/static/tau_docs/node-sdk.md +33 -26
  18. package/dist/core/static/tau_docs/ownership-and-scope.md +3 -4
  19. package/dist/core/static/tau_docs/prompts-and-project-context.md +2 -2
  20. package/dist/core/static/tau_docs/remote-sessions.md +4 -47
  21. package/dist/core/static/tau_docs/security.md +2 -6
  22. package/dist/core/static/tau_docs/session-protocol-methods.md +48 -7
  23. package/dist/core/static/tau_docs/session-protocol.md +18 -18
  24. package/dist/core/static/tau_docs/sessions.md +6 -5
  25. package/dist/core/static/tau_docs/telegram.md +8 -4
  26. package/dist/core/static/tau_docs/troubleshooting.md +3 -5
  27. package/dist/core/static/tau_docs/tui.md +4 -6
  28. package/dist/core/telegram/adapter.js +226 -18
  29. package/dist/core/telegram/adapter.js.map +1 -1
  30. package/dist/core/telegram/config.js +1 -1
  31. package/dist/core/telegram/config.js.map +1 -1
  32. package/dist/core/telegram/project_preferences.js +42 -12
  33. package/dist/core/telegram/project_preferences.js.map +1 -1
  34. package/dist/core/telegram/runtime.js +6 -1
  35. package/dist/core/telegram/runtime.js.map +1 -1
  36. package/dist/core/telegram/session_manager.js +50 -4
  37. package/dist/core/telegram/session_manager.js.map +1 -1
  38. package/dist/core/telegram/tts.js +137 -0
  39. package/dist/core/telegram/tts.js.map +1 -0
  40. package/dist/core/tools/presentation.js +55 -17
  41. package/dist/core/tools/presentation.js.map +1 -1
  42. package/dist/core/utils/gemini_speech.js +122 -41
  43. package/dist/core/utils/gemini_speech.js.map +1 -1
  44. package/dist/core/version.js +1 -1
  45. package/dist/host/client_tool_broker.js +71 -17
  46. package/dist/host/client_tool_broker.js.map +1 -1
  47. package/dist/host/local_session_host.js +2 -2
  48. package/dist/host/local_session_host.js.map +1 -1
  49. package/dist/host/session_host.js.map +1 -1
  50. package/dist/host/session_protocol_handler.js +17 -6
  51. package/dist/host/session_protocol_handler.js.map +1 -1
  52. package/dist/main.js +18 -92
  53. package/dist/main.js.map +1 -1
  54. package/dist/protocol/session_protocol.d.ts +22 -2
  55. package/dist/protocol/session_protocol.js +47 -3
  56. package/dist/protocol/session_protocol.js.map +1 -1
  57. package/dist/sdk/client_tool_command.d.ts +41 -13
  58. package/dist/sdk/client_tool_command.js +157 -39
  59. package/dist/sdk/client_tool_command.js.map +1 -1
  60. package/dist/sdk/client_tool_presentation.d.ts +17 -0
  61. package/dist/sdk/client_tool_presentation.js +9 -0
  62. package/dist/sdk/client_tool_presentation.js.map +1 -0
  63. package/dist/sdk/code_mode.js +10 -1
  64. package/dist/sdk/code_mode.js.map +1 -1
  65. package/dist/sdk/index.d.ts +5 -4
  66. package/dist/sdk/index.js +2 -1
  67. package/dist/sdk/index.js.map +1 -1
  68. package/dist/sdk/session.js +28 -9
  69. package/dist/sdk/session.js.map +1 -1
  70. package/dist/sdk/types.d.ts +11 -1
  71. package/dist/transport/errors.d.ts +0 -11
  72. package/dist/transport/errors.js +0 -12
  73. package/dist/transport/errors.js.map +1 -1
  74. package/dist/transport/index.d.ts +1 -3
  75. package/dist/transport/index.js +1 -2
  76. package/dist/transport/index.js.map +1 -1
  77. package/dist/tui/session_chat_app.js +28 -15
  78. package/dist/tui/session_chat_app.js.map +1 -1
  79. package/dist/tui/session_chat_controller.js +0 -51
  80. package/dist/tui/session_chat_controller.js.map +1 -1
  81. package/dist/tui/speech_playback.js +3 -3
  82. package/dist/tui/speech_playback.js.map +1 -1
  83. package/package.json +2 -2
  84. package/dist/core/modes/rpc_server.js +0 -105
  85. package/dist/core/modes/rpc_server.js.map +0 -1
  86. package/dist/transport/stdio_session_transport.d.ts +0 -48
  87. package/dist/transport/stdio_session_transport.js +0 -338
  88. package/dist/transport/stdio_session_transport.js.map +0 -1
@@ -0,0 +1,137 @@
1
+ import { mkdtemp, readdir, readFile, rm, writeFile } from "node:fs/promises";
2
+ import { tmpdir } from "node:os";
3
+ import { join } from "node:path";
4
+ import { GEMINI_SPEECH_PLAYBACK_RATE, streamGeminiSpeechAudio } from "../utils/gemini_speech.js";
5
+ import { spawnWithCapture } from "../utils/spawn_capture.js";
6
+ const TELEGRAM_TTS_TEMP_DIR_PREFIX = "tau-telegram-tts-";
7
+ const TELEGRAM_TTS_CONVERSION_TIMEOUT_MS = 120_000;
8
+ const WAVE_HEADER_BYTES = 44;
9
+ export async function sweepStaleTelegramTtsTempDirs() {
10
+ const systemTmpDir = tmpdir();
11
+ try {
12
+ const entries = await readdir(systemTmpDir, { withFileTypes: true, encoding: "utf8" });
13
+ await Promise.allSettled(entries
14
+ .filter((entry) => entry.isDirectory() && entry.name.startsWith(TELEGRAM_TTS_TEMP_DIR_PREFIX))
15
+ .map(async (entry) => await rm(join(systemTmpDir, entry.name), { recursive: true, force: true })));
16
+ }
17
+ catch {
18
+ return;
19
+ }
20
+ }
21
+ export async function generateTelegramVoice(options) {
22
+ const streamSpeechAudio = options.deps?.streamSpeechAudio ?? streamGeminiSpeechAudio;
23
+ const spawn = options.deps?.spawn ?? spawnWithCapture;
24
+ const temporaryDirectory = await mkdtemp(join(tmpdir(), TELEGRAM_TTS_TEMP_DIR_PREFIX));
25
+ const manifestPath = join(temporaryDirectory, "speech.ffconcat");
26
+ const outputPath = join(temporaryDirectory, "speech.ogg");
27
+ try {
28
+ const chunkNames = [];
29
+ let waveFormat;
30
+ for await (const chunk of streamSpeechAudio({
31
+ apiKey: options.apiKey,
32
+ sourceText: options.sourceText,
33
+ deliveryMode: "complete",
34
+ fetchImpl: options.fetchImpl,
35
+ signal: options.signal,
36
+ })) {
37
+ const header = parseWaveHeader(chunk.audio);
38
+ if (waveFormat && !header.format.equals(waveFormat)) {
39
+ throw new Error("Gemini TTS returned incompatible audio chunks");
40
+ }
41
+ waveFormat ??= Buffer.from(header.format);
42
+ const chunkName = `chunk-${String(chunkNames.length).padStart(3, "0")}.wav`;
43
+ await writeFile(join(temporaryDirectory, chunkName), chunk.audio.subarray(0, WAVE_HEADER_BYTES + header.dataBytes));
44
+ chunkNames.push(chunkName);
45
+ }
46
+ if (chunkNames.length === 0) {
47
+ throw new Error("Gemini TTS returned no audio");
48
+ }
49
+ await writeFile(manifestPath, `ffconcat version 1.0\n${chunkNames.map((name) => `file '${name}'`).join("\n")}\n`, "utf8");
50
+ const result = await spawn("ffmpeg", [
51
+ "-nostdin",
52
+ "-hide_banner",
53
+ "-loglevel",
54
+ "error",
55
+ "-y",
56
+ "-f",
57
+ "concat",
58
+ "-safe",
59
+ "1",
60
+ "-i",
61
+ "speech.ffconcat",
62
+ "-filter:a",
63
+ `atempo=${GEMINI_SPEECH_PLAYBACK_RATE}`,
64
+ "-c:a",
65
+ "libopus",
66
+ "-b:a",
67
+ "48k",
68
+ "-vbr",
69
+ "on",
70
+ "-application",
71
+ "voip",
72
+ "speech.ogg",
73
+ ], {
74
+ cwd: temporaryDirectory,
75
+ detached: true,
76
+ killProcessGroup: true,
77
+ signal: options.signal,
78
+ timeoutMs: TELEGRAM_TTS_CONVERSION_TIMEOUT_MS,
79
+ maxCaptureBytes: 20_000,
80
+ });
81
+ if (result.aborted || options.signal?.aborted) {
82
+ throw abortError();
83
+ }
84
+ if (result.timedOut) {
85
+ throw new Error("ffmpeg timed out while encoding Telegram voice audio");
86
+ }
87
+ if (result.exitCode !== 0) {
88
+ const detail = result.stderr.trim();
89
+ throw new Error(detail
90
+ ? `ffmpeg failed to encode Telegram voice audio: ${detail}`
91
+ : `ffmpeg exited with code ${result.exitCode ?? "unknown"}`);
92
+ }
93
+ const voice = await readFile(outputPath);
94
+ if (voice.length === 0) {
95
+ throw new Error("ffmpeg produced empty Telegram voice audio");
96
+ }
97
+ return voice;
98
+ }
99
+ catch (error) {
100
+ if (isMissingExecutableError(error)) {
101
+ throw new Error("ffmpeg is required to encode Telegram voice notes");
102
+ }
103
+ throw error;
104
+ }
105
+ finally {
106
+ await rm(temporaryDirectory, { recursive: true, force: true });
107
+ }
108
+ }
109
+ function parseWaveHeader(audio) {
110
+ if (audio.length < WAVE_HEADER_BYTES ||
111
+ audio.toString("ascii", 0, 4) !== "RIFF" ||
112
+ audio.toString("ascii", 8, 12) !== "WAVE" ||
113
+ audio.toString("ascii", 12, 16) !== "fmt " ||
114
+ audio.toString("ascii", 36, 40) !== "data") {
115
+ throw new Error("Gemini TTS returned invalid WAV audio");
116
+ }
117
+ const dataBytes = audio.readUInt32LE(40);
118
+ if (dataBytes > audio.length - WAVE_HEADER_BYTES) {
119
+ throw new Error("Gemini TTS returned truncated WAV audio");
120
+ }
121
+ return {
122
+ format: audio.subarray(20, 36),
123
+ dataBytes,
124
+ };
125
+ }
126
+ function isMissingExecutableError(error) {
127
+ return (typeof error === "object" &&
128
+ error !== null &&
129
+ "code" in error &&
130
+ error.code === "ENOENT");
131
+ }
132
+ function abortError() {
133
+ const error = new Error("Telegram TTS was aborted");
134
+ error.name = "AbortError";
135
+ return error;
136
+ }
137
+ //# sourceMappingURL=tts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tts.js","sourceRoot":"","sources":["../../../src/core/telegram/tts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,2BAA2B,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AACjG,OAAO,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAE7D,MAAM,4BAA4B,GAAG,mBAAmB,CAAC;AACzD,MAAM,kCAAkC,GAAG,OAAO,CAAC;AACnD,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B,MAAM,CAAC,KAAK,UAAU,6BAA6B;IACjD,MAAM,YAAY,GAAG,MAAM,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,YAAY,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;QACvF,MAAM,OAAO,CAAC,UAAU,CACtB,OAAO;aACJ,MAAM,CACL,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,4BAA4B,CAAC,CACtF;aACA,GAAG,CACF,KAAK,EAAE,KAAK,EAAE,EAAE,CACd,MAAM,EAAE,CAAC,IAAI,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAC7E,CACJ,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO;IACT,CAAC;AACH,CAAC;AAaD,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,OAAqC;IAErC,MAAM,iBAAiB,GAAG,OAAO,CAAC,IAAI,EAAE,iBAAiB,IAAI,uBAAuB,CAAC;IACrF,MAAM,KAAK,GAAG,OAAO,CAAC,IAAI,EAAE,KAAK,IAAI,gBAAgB,CAAC;IACtD,MAAM,kBAAkB,GAAG,MAAM,OAAO,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,4BAA4B,CAAC,CAAC,CAAC;IACvF,MAAM,YAAY,GAAG,IAAI,CAAC,kBAAkB,EAAE,iBAAiB,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,IAAI,CAAC,kBAAkB,EAAE,YAAY,CAAC,CAAC;IAE1D,IAAI,CAAC;QACH,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,IAAI,UAA8B,CAAC;QAEnC,IAAI,KAAK,EAAE,MAAM,KAAK,IAAI,iBAAiB,CAAC;YAC1C,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,YAAY,EAAE,UAAU;YACxB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,EAAE,CAAC;YACH,MAAM,MAAM,GAAG,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;YAC5C,IAAI,UAAU,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC;gBACpD,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;YACnE,CAAC;YACD,UAAU,KAAK,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YAE1C,MAAM,SAAS,GAAG,SAAS,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC;YAC5E,MAAM,SAAS,CACb,IAAI,CAAC,kBAAkB,EAAE,SAAS,CAAC,EACnC,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,EAAE,iBAAiB,GAAG,MAAM,CAAC,SAAS,CAAC,CAC9D,CAAC;YACF,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;QAED,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAClD,CAAC;QAED,MAAM,SAAS,CACb,YAAY,EACZ,yBAAyB,UAAU,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,SAAS,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAClF,MAAM,CACP,CAAC;QACF,MAAM,MAAM,GAAG,MAAM,KAAK,CACxB,QAAQ,EACR;YACE,UAAU;YACV,cAAc;YACd,WAAW;YACX,OAAO;YACP,IAAI;YACJ,IAAI;YACJ,QAAQ;YACR,OAAO;YACP,GAAG;YACH,IAAI;YACJ,iBAAiB;YACjB,WAAW;YACX,UAAU,2BAA2B,EAAE;YACvC,MAAM;YACN,SAAS;YACT,MAAM;YACN,KAAK;YACL,MAAM;YACN,IAAI;YACJ,cAAc;YACd,MAAM;YACN,YAAY;SACb,EACD;YACE,GAAG,EAAE,kBAAkB;YACvB,QAAQ,EAAE,IAAI;YACd,gBAAgB,EAAE,IAAI;YACtB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,SAAS,EAAE,kCAAkC;YAC7C,eAAe,EAAE,MAAM;SACxB,CACF,CAAC;QAEF,IAAI,MAAM,CAAC,OAAO,IAAI,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC;YAC9C,MAAM,UAAU,EAAE,CAAC;QACrB,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,MAAM,IAAI,KAAK,CAAC,sDAAsD,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CACb,MAAM;gBACJ,CAAC,CAAC,iDAAiD,MAAM,EAAE;gBAC3D,CAAC,CAAC,2BAA2B,MAAM,CAAC,QAAQ,IAAI,SAAS,EAAE,CAC9D,CAAC;QACJ,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,CAAC;QACzC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;QAChE,CAAC;QACD,OAAO,KAAK,CAAC;IACf,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,wBAAwB,CAAC,KAAK,CAAC,EAAE,CAAC;YACpC,MAAM,IAAI,KAAK,CAAC,mDAAmD,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,KAAK,CAAC;IACd,CAAC;YAAS,CAAC;QACT,MAAM,EAAE,CAAC,kBAAkB,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACjE,CAAC;AACH,CAAC;AAED,SAAS,eAAe,CAAC,KAAa;IACpC,IACE,KAAK,CAAC,MAAM,GAAG,iBAAiB;QAChC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,CAAC,CAAC,KAAK,MAAM;QACxC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,MAAM;QACzC,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,KAAK,MAAM;QAC1C,KAAK,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,EAAE,EAAE,CAAC,KAAK,MAAM,EAC1C,CAAC;QACD,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC;IACzC,IAAI,SAAS,GAAG,KAAK,CAAC,MAAM,GAAG,iBAAiB,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAC;IAC7D,CAAC;IAED,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,QAAQ,CAAC,EAAE,EAAE,EAAE,CAAC;QAC9B,SAAS;KACV,CAAC;AACJ,CAAC;AAED,SAAS,wBAAwB,CAAC,KAAc;IAC9C,OAAO,CACL,OAAO,KAAK,KAAK,QAAQ;QACzB,KAAK,KAAK,IAAI;QACd,MAAM,IAAI,KAAK;QACd,KAA+B,CAAC,IAAI,KAAK,QAAQ,CACnD,CAAC;AACJ,CAAC;AAED,SAAS,UAAU;IACjB,MAAM,KAAK,GAAG,IAAI,KAAK,CAAC,0BAA0B,CAAC,CAAC;IACpD,KAAK,CAAC,IAAI,GAAG,YAAY,CAAC;IAC1B,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -1,6 +1,8 @@
1
1
  import { z } from "zod";
2
+ import { SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_BYTES, SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_DETAIL_BYTES, SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_DETAILS, SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_LABEL_BYTES, SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_METADATA, SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_METADATA_VALUE_BYTES, SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_SUBJECT_BYTES, } from "../../protocol/session_protocol.js";
2
3
  import { TOOL_NAME_BASH, TOOL_NAME_EDIT, TOOL_NAME_HISTORY, TOOL_NAME_INTERRUPT_AGENT, TOOL_NAME_LIST_AGENTS, TOOL_NAME_NOOK, TOOL_NAME_SEND_INPUT_TO_AGENT, TOOL_NAME_SPAWN_AGENT, TOOL_NAME_TAU_DOCS, TOOL_NAME_VIEW_IMAGE, TOOL_NAME_WAIT_FOR_AGENTS, TOOL_NAME_WEB, TOOL_NAME_WRITE, } from "./tool_names.js";
3
4
  export const TOOL_UI_FACET_VERSION = 3;
5
+ export const TOOL_RUN_PRESENTATION_MAX_BYTES = SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_BYTES * 2;
4
6
  export const TOOL_CARD_SUBJECT_MAX_LINES = 8;
5
7
  export const TOOL_CARD_DEFAULT_DETAILS_MAX_LINES = 7;
6
8
  export const TOOL_CARD_TRUNCATED_DETAILS_MAX_LINES = 33;
@@ -8,15 +10,18 @@ export const TOOL_CARD_MAX_LINE_CHARS = 512;
8
10
  function isSingleLine(text) {
9
11
  return !text.includes("\n") && !text.includes("\r");
10
12
  }
11
- function isBoundedLine(text) {
12
- return isSingleLine(text) && Array.from(text).length <= TOOL_CARD_MAX_LINE_CHARS;
13
+ function utf8ByteLength(text) {
14
+ return Buffer.byteLength(text, "utf8");
13
15
  }
14
16
  const singleLineSchema = z.string().refine(isSingleLine, "must be one line");
15
- const boundedLineSchema = z.string().refine(isBoundedLine, "must be one bounded line");
16
- const boundedLabelSchema = boundedLineSchema.min(1);
17
+ const boundedLabelSchema = singleLineSchema
18
+ .min(1)
19
+ .refine((value) => utf8ByteLength(value) <= SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_LABEL_BYTES, `must not exceed ${SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_LABEL_BYTES} UTF-8 bytes`);
20
+ const boundedDetailSchema = singleLineSchema.refine((value) => utf8ByteLength(value) <= SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_DETAIL_BYTES, `must not exceed ${SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_DETAIL_BYTES} UTF-8 bytes`);
21
+ const boundedMetadataSchema = singleLineSchema.refine((value) => utf8ByteLength(value) <= SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_METADATA_VALUE_BYTES, `must not exceed ${SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_METADATA_VALUE_BYTES} UTF-8 bytes`);
17
22
  const toolCardLineSchema = z
18
23
  .object({
19
- text: singleLineSchema,
24
+ text: boundedDetailSchema,
20
25
  tone: z.enum(["added", "removed"]).optional(),
21
26
  wrap: z.enum(["word", "character"]),
22
27
  })
@@ -38,15 +43,16 @@ const toolRunPresentationSchema = z
38
43
  subject: z
39
44
  .string()
40
45
  .min(1)
41
- .refine((subject) => {
42
- const lines = subject.split("\n");
43
- return lines.length <= TOOL_CARD_SUBJECT_MAX_LINES && lines.every(isBoundedLine);
44
- }, "must contain only bounded lines"),
46
+ .refine((value) => !value.includes("\r"), "must not contain carriage returns")
47
+ .refine((value) => utf8ByteLength(value) <= SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_SUBJECT_BYTES, `must not exceed ${SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_SUBJECT_BYTES} UTF-8 bytes`),
45
48
  subjectWrap: z.enum(["word", "character"]),
46
- details: z.array(toolCardLineSchema),
47
- metadata: z.array(boundedLineSchema),
49
+ details: z.array(toolCardLineSchema).max(SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_DETAILS),
50
+ metadata: z
51
+ .array(boundedMetadataSchema)
52
+ .max(SESSION_PROTOCOL_MAX_CLIENT_TOOL_PRESENTATION_METADATA),
48
53
  })
49
- .strict();
54
+ .strict()
55
+ .refine((value) => utf8ByteLength(JSON.stringify(value)) <= TOOL_RUN_PRESENTATION_MAX_BYTES, `must not exceed ${TOOL_RUN_PRESENTATION_MAX_BYTES} UTF-8 bytes`);
50
56
  const GENERIC_TOOL_RUN_ACTION_LABELS = {
51
57
  preparing: "preparing",
52
58
  queued: "queued",
@@ -188,9 +194,41 @@ function truncateLines(lines, maxLines, maxLineChars, strategy = "middle") {
188
194
  text: truncateLine(`…${omitted} more ${omitted === 1 ? "line" : "lines"}…`, maxLineChars),
189
195
  wrap: "word",
190
196
  },
191
- ...bounded.slice(-tailCount),
197
+ ...(tailCount > 0 ? bounded.slice(-tailCount) : []),
192
198
  ];
193
199
  }
200
+ export function truncateToolText(text, options) {
201
+ if (!Number.isInteger(options.maxLines) || options.maxLines < 1) {
202
+ throw new Error("text maxLines must be a positive integer");
203
+ }
204
+ if (!Number.isInteger(options.maxLineChars) || options.maxLineChars < 1) {
205
+ throw new Error("text maxLineChars must be a positive integer");
206
+ }
207
+ return truncateLines(text
208
+ .replace(/\r\n?/g, "\n")
209
+ .replace(/\n+$/, "")
210
+ .split("\n")
211
+ .map((line) => ({ text: line, wrap: "word" })), options.maxLines, options.maxLineChars, options.strategy)
212
+ .map((line) => line.text)
213
+ .join("\n");
214
+ }
215
+ export function truncateToolRunSubject(subject, options = {}) {
216
+ const maxLines = options.maxLines ?? TOOL_CARD_SUBJECT_MAX_LINES;
217
+ const maxLineChars = options.maxLineChars ?? TOOL_CARD_MAX_LINE_CHARS;
218
+ if (!Number.isInteger(maxLines) || maxLines < 1 || maxLines > TOOL_CARD_SUBJECT_MAX_LINES) {
219
+ throw new Error(`subject maxLines must be between 1 and ${TOOL_CARD_SUBJECT_MAX_LINES}`);
220
+ }
221
+ if (!Number.isInteger(maxLineChars) ||
222
+ maxLineChars < 1 ||
223
+ maxLineChars > TOOL_CARD_MAX_LINE_CHARS) {
224
+ throw new Error(`subject maxLineChars must be between 1 and ${TOOL_CARD_MAX_LINE_CHARS}`);
225
+ }
226
+ return truncateToolText(subject, {
227
+ maxLines,
228
+ maxLineChars,
229
+ strategy: options.strategy,
230
+ });
231
+ }
194
232
  export function parseToolRunPresentation(value) {
195
233
  return toolRunPresentationSchema.parse(value);
196
234
  }
@@ -210,10 +248,10 @@ const CHARACTER_WRAPPED_SUBJECT_TOOLS = new Set([
210
248
  TOOL_NAME_VIEW_IMAGE,
211
249
  ]);
212
250
  export function buildToolRunPresentation(args) {
213
- const subjectLines = args.subject.replace(/\r\n?/g, "\n").replace(/\n+$/, "").split("\n");
214
- const boundedSubject = truncateLines(subjectLines.map((text) => ({ text, wrap: "word" })), TOOL_CARD_SUBJECT_MAX_LINES, TOOL_CARD_MAX_LINE_CHARS)
215
- .map((line) => line.text)
216
- .join("\n");
251
+ const normalizedSubject = args.subject.replace(/\r\n?/g, "\n").replace(/\n+$/, "");
252
+ const boundedSubject = args.subjectTruncation === false
253
+ ? normalizedSubject
254
+ : truncateToolRunSubject(normalizedSubject, args.subjectTruncation);
217
255
  const labels = { ...getToolRunActionLabels(args.toolName), ...args.actionOverrides };
218
256
  for (const status of Object.keys(labels)) {
219
257
  labels[status] = normalizeLabel(labels[status]) || GENERIC_TOOL_RUN_ACTION_LABELS[status];
@@ -1 +1 @@
1
- {"version":3,"file":"presentation.js","sourceRoot":"","sources":["../../../src/core/tools/presentation.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"presentation.js","sourceRoot":"","sources":["../../../src/core/tools/presentation.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { z } from "zod";
2
2
  const GEMINI_GENERATE_CONTENT_BASE_URL = "https://generativelanguage.googleapis.com/v1beta/models";
3
+ export const GEMINI_SPEECH_PLAYBACK_RATE = 1.1;
3
4
  const DEFAULT_GEMINI_SPEECH_REWRITE_MODEL = "gemini-3.6-flash";
4
5
  const DEFAULT_GEMINI_SPEECH_REWRITE_THINKING_LEVEL = "minimal";
5
6
  const DEFAULT_GEMINI_SPEECH_TTS_MODEL = "gemini-3.1-flash-tts-preview";
@@ -8,8 +9,15 @@ const DEFAULT_TTS_SAMPLE_RATE_HZ = 24000;
8
9
  const DEFAULT_TTS_CHANNEL_COUNT = 1;
9
10
  const DEFAULT_TTS_BITS_PER_SAMPLE = 16;
10
11
  const DEFAULT_TTS_MAX_ATTEMPTS = 3;
11
- const DEFAULT_TTS_CONCURRENCY = 6;
12
- const MIN_SPEECH_CHUNK_CHARACTERS = 240;
12
+ const SPEECH_REWRITE_TIMEOUT_MS = 60_000;
13
+ const PROGRESSIVE_TTS_CONCURRENCY = 6;
14
+ const COMPLETE_TTS_CONCURRENCY = 3;
15
+ const PROGRESSIVE_SPEECH_CHUNK_CHARACTERS = 500;
16
+ const COMPLETE_SPEECH_CHUNK_CHARACTERS = 1000;
17
+ const MAX_SPEECH_SOURCE_CHARACTERS = 10_000;
18
+ const MAX_SPOKEN_TEXT_CHARACTERS = 10_000;
19
+ const MAX_SPEECH_PCM_BYTES = 32 * 1024 * 1024;
20
+ const TTS_MAX_OUTPUT_TOKENS = 8192;
13
21
  const RETRYABLE_TTS_STATUS_CODES = new Set([408, 429, 500, 502, 503, 504]);
14
22
  const errorPayloadSchema = z.object({
15
23
  error: z
@@ -34,11 +42,20 @@ class GeminiTtsResponseError extends Error {
34
42
  this.name = "GeminiTtsResponseError";
35
43
  }
36
44
  }
45
+ class GeminiTtsOutputLimitError extends Error {
46
+ constructor() {
47
+ super("Gemini TTS reached its output token limit");
48
+ this.name = "GeminiTtsOutputLimitError";
49
+ }
50
+ }
37
51
  export async function* streamGeminiSpeechAudio(options) {
38
52
  const sourceText = options.sourceText.trim();
39
53
  if (!sourceText) {
40
54
  throw new Error("speech source text was empty");
41
55
  }
56
+ if (exceedsUnicodeCharacterLimit(sourceText, MAX_SPEECH_SOURCE_CHARACTERS)) {
57
+ throw new Error("speech source text exceeds 10,000 characters");
58
+ }
42
59
  const apiKey = options.apiKey.trim();
43
60
  if (!apiKey) {
44
61
  throw new Error("missing Gemini API key");
@@ -51,14 +68,33 @@ export async function* streamGeminiSpeechAudio(options) {
51
68
  let completed = false;
52
69
  try {
53
70
  await options.onStageChange?.("rewriting");
54
- const spokenText = await rewriteTextForSpeech({
55
- apiKey,
56
- model: rewriteModel,
57
- sourceText,
58
- fetchImpl,
59
- signal: abortController.signal,
60
- });
61
- const spokenChunks = splitSpeechChunks(spokenText);
71
+ const rewriteController = createLinkedAbortController(abortController.signal);
72
+ const rewriteTimeout = setTimeout(() => rewriteController.abort(), SPEECH_REWRITE_TIMEOUT_MS);
73
+ rewriteTimeout.unref?.();
74
+ let spokenText;
75
+ try {
76
+ spokenText = await rewriteTextForSpeech({
77
+ apiKey,
78
+ model: rewriteModel,
79
+ sourceText,
80
+ fetchImpl,
81
+ signal: rewriteController.signal,
82
+ });
83
+ }
84
+ catch (error) {
85
+ if (!abortController.signal.aborted && rewriteController.signal.aborted) {
86
+ throw new Error("speech rewrite timed out after 1 minute");
87
+ }
88
+ throw error;
89
+ }
90
+ finally {
91
+ clearTimeout(rewriteTimeout);
92
+ rewriteController.dispose();
93
+ }
94
+ if (exceedsUnicodeCharacterLimit(spokenText, MAX_SPOKEN_TEXT_CHARACTERS)) {
95
+ throw new Error("rewritten speech text exceeds 10,000 characters");
96
+ }
97
+ const spokenChunks = splitSpeechChunks(spokenText, options.deliveryMode);
62
98
  await options.onStageChange?.("generating");
63
99
  await options.onChunkProgress?.({ ready: 0, total: spokenChunks.length });
64
100
  for await (const chunk of synthesizeSpeechAudioChunksInOrder({
@@ -69,7 +105,9 @@ export async function* streamGeminiSpeechAudio(options) {
69
105
  fetchImpl,
70
106
  signal: abortController.signal,
71
107
  maxAttempts: options.maxTtsAttempts ?? DEFAULT_TTS_MAX_ATTEMPTS,
72
- concurrency: DEFAULT_TTS_CONCURRENCY,
108
+ concurrency: options.deliveryMode === "progressive"
109
+ ? PROGRESSIVE_TTS_CONCURRENCY
110
+ : COMPLETE_TTS_CONCURRENCY,
73
111
  onChunkProgress: options.onChunkProgress,
74
112
  abortOnFailure: () => abortController.abort(),
75
113
  })) {
@@ -130,6 +168,7 @@ async function* synthesizeSpeechAudioChunksInOrder(args) {
130
168
  let nextIndex = 0;
131
169
  let nextYieldIndex = 0;
132
170
  let ready = 0;
171
+ let totalPcmBytes = 0;
133
172
  let failure;
134
173
  let notify;
135
174
  const wake = () => {
@@ -163,7 +202,7 @@ async function* synthesizeSpeechAudioChunksInOrder(args) {
163
202
  return;
164
203
  }
165
204
  try {
166
- results[index] = await synthesizeSpeechAudioChunk({
205
+ const pcmAudio = await synthesizeSpeechAudioChunk({
167
206
  apiKey: args.apiKey,
168
207
  model: args.model,
169
208
  voiceName: args.voiceName,
@@ -172,6 +211,11 @@ async function* synthesizeSpeechAudioChunksInOrder(args) {
172
211
  signal: args.signal,
173
212
  maxAttempts: args.maxAttempts,
174
213
  });
214
+ totalPcmBytes += pcmAudio.length;
215
+ if (totalPcmBytes > MAX_SPEECH_PCM_BYTES) {
216
+ throw new Error("generated speech audio exceeds the 32 MiB limit");
217
+ }
218
+ results[index] = pcmAudio;
175
219
  ready += 1;
176
220
  await args.onChunkProgress?.({ ready, total });
177
221
  wake();
@@ -192,6 +236,7 @@ async function* synthesizeSpeechAudioChunksInOrder(args) {
192
236
  while (nextYieldIndex < total) {
193
237
  const nextResult = results[nextYieldIndex];
194
238
  if (nextResult) {
239
+ results[nextYieldIndex] = undefined;
195
240
  yield { index: nextYieldIndex, pcmAudio: nextResult };
196
241
  nextYieldIndex += 1;
197
242
  continue;
@@ -229,7 +274,7 @@ async function synthesizeSpeechAudioChunk(args) {
229
274
  ],
230
275
  generationConfig: {
231
276
  responseModalities: ["AUDIO"],
232
- temperature: 1,
277
+ maxOutputTokens: TTS_MAX_OUTPUT_TOKENS,
233
278
  speechConfig: {
234
279
  voiceConfig: {
235
280
  prebuiltVoiceConfig: {
@@ -240,6 +285,7 @@ async function synthesizeSpeechAudioChunk(args) {
240
285
  },
241
286
  },
242
287
  });
288
+ assertGeminiTtsDidNotReachOutputLimit(payload);
243
289
  const audioData = extractGeminiInlineAudioData(payload);
244
290
  if (!audioData) {
245
291
  throw new GeminiTtsResponseError("Gemini TTS response did not include audio data");
@@ -304,6 +350,14 @@ function extractGeminiText(payload) {
304
350
  }
305
351
  return "";
306
352
  }
353
+ function assertGeminiTtsDidNotReachOutputLimit(payload) {
354
+ if (!isObject(payload) || !Array.isArray(payload.candidates)) {
355
+ return;
356
+ }
357
+ if (payload.candidates.some((candidate) => isObject(candidate) && candidate.finishReason === "MAX_TOKENS")) {
358
+ throw new GeminiTtsOutputLimitError();
359
+ }
360
+ }
307
361
  function extractGeminiInlineAudioData(payload) {
308
362
  if (!isObject(payload) || !Array.isArray(payload.candidates)) {
309
363
  return undefined;
@@ -336,14 +390,17 @@ function buildSpeechRewritePrompt(sourceText) {
336
390
  "Things that typically need rewriting: file paths, shell commands, code identifiers, markdown structure, XML-like tags, long option lists, and code-heavy formatting.",
337
391
  "Remove formatting. Convert headings, lists, tables, and code blocks into plain spoken prose. Do not preserve markdown bullets, heading markers, table rows, fences, or standalone labels.",
338
392
  "For file references, keep the filename and any line or range info that was actually present. Do not add location detail that was not in the original.",
339
- "Say code identifiers and version strings as natural words (for example, handleToolUiEvent as 'handle tool UI event', v5.4 as 'version 5.4'). Keep numbers and units natural (for example, 8,192 tokens as 'about eight thousand tokens').",
393
+ "Preserve numbers exactly as written, including separators, decimals, units, versions, line numbers, and ranges.",
394
+ "Preserve established technical names, acronyms, initialisms, commands, program names, filenames, and extensions exactly as written. Do not spell their letters apart, expand them, or change their capitalization. Examples that must remain unchanged include 24, PCM, ffmpeg, npm, v5.4, and config.json.",
395
+ "Rewrite a code identifier only when its literal form would be difficult to follow aloud, and preserve its exact meaning.",
340
396
  "",
341
397
  "Examples of good rewrites:",
342
398
  '- `src/core/utils/gemini_speech.ts:372` → "gemini_speech.ts, line 372"',
343
399
  '- `src/tui/session_chat_controller.ts:1819-1855` → "session_chat_controller.ts, lines 1819 to 1855"',
344
400
  '- `src/core/session/compaction.ts` → "compaction.ts"',
345
401
  '- `/Users/markus/.config/tau/config.json` → "the tau config.json in your home directory"',
346
- '- `rg --heading -n -t ts "ToolRunPresentation" src` → "ripgrep for ToolRunPresentation in TypeScript files under src"',
402
+ '- `rg --heading -n -t ts "ToolRunPresentation" src` → "the rg command searching TypeScript files for ToolRunPresentation under src"',
403
+ '- `24 kHz PCM with ffmpeg` → "24 kHz PCM with ffmpeg"',
347
404
  '- `<available-skills>` → "the available-skills tag"',
348
405
  "- A markdown bullet list of short items → a natural comma-separated list or short sentences",
349
406
  "",
@@ -355,38 +412,59 @@ function buildSpeechRewritePrompt(sourceText) {
355
412
  sourceText,
356
413
  ].join("\n");
357
414
  }
358
- function splitSpeechChunks(spokenText) {
359
- const paragraphs = spokenText
360
- .split(/\n\s*\n/g)
361
- .map((paragraph) => normalizeSpeechParagraph(paragraph))
362
- .filter((paragraph) => paragraph.length > 0);
363
- if (paragraphs.length === 0) {
364
- return [spokenText.trim()];
415
+ function exceedsUnicodeCharacterLimit(text, limit) {
416
+ let count = 0;
417
+ for (const _character of text) {
418
+ count += 1;
419
+ if (count > limit) {
420
+ return true;
421
+ }
365
422
  }
423
+ return false;
424
+ }
425
+ function splitSpeechChunks(spokenText, deliveryMode) {
426
+ const normalizedText = spokenText
427
+ .trim()
428
+ .split(/\n\s*\n/gu)
429
+ .map((paragraph) => paragraph.replace(/\s+/gu, " ").trim())
430
+ .filter(Boolean)
431
+ .join("\n\n");
432
+ const maxCharacters = deliveryMode === "progressive"
433
+ ? PROGRESSIVE_SPEECH_CHUNK_CHARACTERS
434
+ : COMPLETE_SPEECH_CHUNK_CHARACTERS;
366
435
  const chunks = [];
367
- let current = "";
368
- for (const paragraph of paragraphs) {
369
- if (!current) {
370
- current = paragraph;
371
- continue;
436
+ let remaining = Array.from(normalizedText);
437
+ while (remaining.length > maxCharacters) {
438
+ const boundary = findSpeechChunkBoundary(remaining, maxCharacters);
439
+ chunks.push(remaining.slice(0, boundary).join("").trim());
440
+ remaining = Array.from(remaining.slice(boundary).join("").trim());
441
+ }
442
+ if (remaining.length > 0) {
443
+ chunks.push(remaining.join(""));
444
+ }
445
+ return chunks.length > 0 ? chunks : [spokenText.trim()];
446
+ }
447
+ function findSpeechChunkBoundary(characters, maxCharacters) {
448
+ const preferredMinimum = Math.floor(maxCharacters * 0.6);
449
+ for (let index = maxCharacters; index >= preferredMinimum; index -= 1) {
450
+ if (characters[index] === "\n" && characters[index + 1] === "\n") {
451
+ return index;
372
452
  }
373
- if (current.length < MIN_SPEECH_CHUNK_CHARACTERS) {
374
- current = joinSpeechParagraphs(current, paragraph);
375
- continue;
453
+ }
454
+ for (let index = maxCharacters; index >= preferredMinimum; index -= 1) {
455
+ if (isSpeechSentenceBoundary(characters[index - 1] ?? "", characters[index] ?? "")) {
456
+ return index;
376
457
  }
377
- chunks.push(current);
378
- current = paragraph;
379
458
  }
380
- if (current) {
381
- chunks.push(current);
459
+ for (let index = maxCharacters; index >= 1; index -= 1) {
460
+ if (/\s/u.test(characters[index] ?? "")) {
461
+ return index;
462
+ }
382
463
  }
383
- return chunks;
464
+ return maxCharacters;
384
465
  }
385
- function normalizeSpeechParagraph(paragraph) {
386
- return paragraph.replace(/\s+/g, " ").trim();
387
- }
388
- function joinSpeechParagraphs(first, second) {
389
- return `${first}\n\n${second}`;
466
+ function isSpeechSentenceBoundary(previous, next) {
467
+ return /[。!?]/u.test(previous) || (/[.!?;:]/u.test(previous) && /\s/u.test(next));
390
468
  }
391
469
  function buildSpeechSynthesisPrompt(spokenText) {
392
470
  return [
@@ -395,13 +473,16 @@ function buildSpeechSynthesisPrompt(spokenText) {
395
473
  "",
396
474
  "### DIRECTOR'S NOTES",
397
475
  "Style: Clear, natural, conversational.",
398
- "Pacing: Slightly slower than conversational, with deliberate enunciation. The audio will be sped up during playback.",
476
+ "Pacing: Brisk conversational speed. Keep it clear, confident, and energetic without sounding rushed.",
399
477
  "",
400
478
  "### TRANSCRIPT",
401
479
  spokenText,
402
480
  ].join("\n");
403
481
  }
404
482
  function isRetryableTtsError(error) {
483
+ if (error instanceof GeminiTtsOutputLimitError) {
484
+ return false;
485
+ }
405
486
  if (error instanceof GeminiTtsResponseError) {
406
487
  return true;
407
488
  }