@markusylisiurunen/tau 0.3.77 → 0.3.79

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 (262) hide show
  1. package/dist/code_mode/images.d.ts +3 -0
  2. package/dist/code_mode/images.js +37 -0
  3. package/dist/code_mode/images.js.map +1 -0
  4. package/dist/code_mode/output.d.ts +22 -0
  5. package/dist/code_mode/output.js +109 -0
  6. package/dist/code_mode/output.js.map +1 -0
  7. package/dist/code_mode/runtime.d.ts +2 -1
  8. package/dist/code_mode/runtime.js +92 -12
  9. package/dist/code_mode/runtime.js.map +1 -1
  10. package/dist/core/agent/agent_runtime.js +6 -11
  11. package/dist/core/agent/agent_runtime.js.map +1 -1
  12. package/dist/core/cli.js +2 -2
  13. package/dist/core/cli.js.map +1 -1
  14. package/dist/core/client_tools/command_client_tools.js +2 -2
  15. package/dist/core/commands/registry.js +18 -2
  16. package/dist/core/commands/registry.js.map +1 -1
  17. package/dist/core/config/content_loader.js +12 -194
  18. package/dist/core/config/content_loader.js.map +1 -1
  19. package/dist/core/config/index.js +1 -1
  20. package/dist/core/config/index.js.map +1 -1
  21. package/dist/core/config/mcp.js +68 -0
  22. package/dist/core/config/mcp.js.map +1 -0
  23. package/dist/core/config/runtime.js +1 -2
  24. package/dist/core/config/runtime.js.map +1 -1
  25. package/dist/core/config/schema.js +36 -155
  26. package/dist/core/config/schema.js.map +1 -1
  27. package/dist/core/config/virtual_bundle.js +2 -5
  28. package/dist/core/config/virtual_bundle.js.map +1 -1
  29. package/dist/core/config/virtual_defaults.js +0 -2
  30. package/dist/core/config/virtual_defaults.js.map +1 -1
  31. package/dist/core/debug.js +8 -23
  32. package/dist/core/debug.js.map +1 -1
  33. package/dist/core/diff_review/bridge.js +2 -24
  34. package/dist/core/diff_review/bridge.js.map +1 -1
  35. package/dist/core/index.js.map +1 -1
  36. package/dist/core/mcp/manager.js +245 -0
  37. package/dist/core/mcp/manager.js.map +1 -0
  38. package/dist/core/mcp/search.js +77 -0
  39. package/dist/core/mcp/search.js.map +1 -0
  40. package/dist/core/personas.js +6 -9
  41. package/dist/core/personas.js.map +1 -1
  42. package/dist/core/runtime/agent_model.js +0 -2
  43. package/dist/core/runtime/agent_model.js.map +1 -1
  44. package/dist/core/runtime/chat_runtime.js +7 -6
  45. package/dist/core/runtime/chat_runtime.js.map +1 -1
  46. package/dist/core/runtime/session_prompt_composer.js +12 -27
  47. package/dist/core/runtime/session_prompt_composer.js.map +1 -1
  48. package/dist/core/static/code_mode/mcp/documentation.md +113 -0
  49. package/dist/core/static/code_mode/sandbox_runner.mjs +58 -3
  50. package/dist/core/static/index.js +4 -4
  51. package/dist/core/static/index.js.map +1 -1
  52. package/dist/core/static/tau_docs/client-tools.md +33 -31
  53. package/dist/core/static/tau_docs/config-reference.md +54 -88
  54. package/dist/core/static/tau_docs/configuration.md +4 -11
  55. package/dist/core/static/tau_docs/node-sdk.md +4 -2
  56. package/dist/core/static/tau_docs/ownership-and-scope.md +4 -2
  57. package/dist/core/static/tau_docs/personas.md +8 -21
  58. package/dist/core/static/tau_docs/prompts-and-project-context.md +1 -1
  59. package/dist/core/static/tau_docs/remote-sessions.md +2 -2
  60. package/dist/core/static/tau_docs/security.md +15 -3
  61. package/dist/core/static/tau_docs/session-protocol-methods.md +8 -3
  62. package/dist/core/static/tau_docs/session-protocol.md +11 -9
  63. package/dist/core/static/tau_docs/sessions.md +2 -14
  64. package/dist/core/static/tau_docs/skills.md +1 -1
  65. package/dist/core/static/tau_docs/subagents.md +27 -99
  66. package/dist/core/static/tau_docs/telegram.md +10 -13
  67. package/dist/core/static/tau_docs/tools.md +24 -9
  68. package/dist/core/static/tau_docs/troubleshooting.md +4 -5
  69. package/dist/core/static/tau_docs/tui.md +16 -22
  70. package/dist/core/subagents/agent_supervisor.js +6 -7
  71. package/dist/core/subagents/agent_supervisor.js.map +1 -1
  72. package/dist/core/subagents/format.js +1 -1
  73. package/dist/core/subagents/format.js.map +1 -1
  74. package/dist/core/subagents/prompt.js +7 -0
  75. package/dist/core/subagents/prompt.js.map +1 -0
  76. package/dist/core/subagents/registry.js +15 -43
  77. package/dist/core/subagents/registry.js.map +1 -1
  78. package/dist/core/subagents/types.js +3 -2
  79. package/dist/core/subagents/types.js.map +1 -1
  80. package/dist/core/telegram/adapter.js +6 -10
  81. package/dist/core/telegram/adapter.js.map +1 -1
  82. package/dist/core/telegram/config.js +32 -57
  83. package/dist/core/telegram/config.js.map +1 -1
  84. package/dist/core/telegram/local_session_client.js +0 -3
  85. package/dist/core/telegram/local_session_client.js.map +1 -1
  86. package/dist/core/telegram/runtime.js +0 -3
  87. package/dist/core/telegram/runtime.js.map +1 -1
  88. package/dist/core/telegram/session_manager.js +29 -52
  89. package/dist/core/telegram/session_manager.js.map +1 -1
  90. package/dist/core/telegram/workspace.js +13 -18
  91. package/dist/core/telegram/workspace.js.map +1 -1
  92. package/dist/core/tools/catalog.js +23 -6
  93. package/dist/core/tools/catalog.js.map +1 -1
  94. package/dist/core/tools/code_mode.js +5 -2
  95. package/dist/core/tools/code_mode.js.map +1 -1
  96. package/dist/core/tools/code_mode_worker.js +33 -1
  97. package/dist/core/tools/code_mode_worker.js.map +1 -1
  98. package/dist/core/tools/history.js +1 -1
  99. package/dist/core/tools/history.js.map +1 -1
  100. package/dist/core/tools/mcp.js +167 -0
  101. package/dist/core/tools/mcp.js.map +1 -0
  102. package/dist/core/tools/nook.js +1 -1
  103. package/dist/core/tools/nook.js.map +1 -1
  104. package/dist/core/tools/send_input_to_agent.js +1 -1
  105. package/dist/core/tools/send_input_to_agent.js.map +1 -1
  106. package/dist/core/tools/spawn_agent.js +14 -30
  107. package/dist/core/tools/spawn_agent.js.map +1 -1
  108. package/dist/core/tools/tool_names.js +2 -0
  109. package/dist/core/tools/tool_names.js.map +1 -1
  110. package/dist/core/tools/view_image.js +1 -110
  111. package/dist/core/tools/view_image.js.map +1 -1
  112. package/dist/core/tools/web.js +1 -1
  113. package/dist/core/tools/web.js.map +1 -1
  114. package/dist/core/types.js.map +1 -1
  115. package/dist/core/usage/logs.js.map +1 -1
  116. package/dist/core/utils/bm25.js +74 -0
  117. package/dist/core/utils/bm25.js.map +1 -0
  118. package/dist/core/utils/model_image.js +106 -0
  119. package/dist/core/utils/model_image.js.map +1 -0
  120. package/dist/core/version.js +1 -1
  121. package/dist/diff_tool/app/dist/assets/{angular-html-BjHlbeCk.js → angular-html-CnO8qept.js} +1 -1
  122. package/dist/diff_tool/app/dist/assets/{angular-ts-5J5hsUV-.js → angular-ts-DPXUio9Z.js} +1 -1
  123. package/dist/diff_tool/app/dist/assets/{apl-ChIs51_N.js → apl-X8YsymsQ.js} +1 -1
  124. package/dist/diff_tool/app/dist/assets/{astro-RtGdbaIT.js → astro-BQ9k8AQ0.js} +1 -1
  125. package/dist/diff_tool/app/dist/assets/{blade-Cuc0ZzS1.js → blade-DZ1LYIzB.js} +1 -1
  126. package/dist/diff_tool/app/dist/assets/{c-IpjS3QEt.js → c-VLTwNh7z.js} +1 -1
  127. package/dist/diff_tool/app/dist/assets/{chapel-BvHOmF40.js → chapel-5s-sGN8D.js} +1 -1
  128. package/dist/diff_tool/app/dist/assets/{cobol-BWLkapNx.js → cobol-C9RzwrVu.js} +1 -1
  129. package/dist/diff_tool/app/dist/assets/{coffee-lfdf_MuK.js → coffee-BHvjZ343.js} +1 -1
  130. package/dist/diff_tool/app/dist/assets/{cpp-GvMfdutG.js → cpp-CBTVXbBp.js} +1 -1
  131. package/dist/diff_tool/app/dist/assets/{crystal--kdmUeXB.js → crystal-DQJua4y4.js} +1 -1
  132. package/dist/diff_tool/app/dist/assets/{css-CnlOazId.js → css-BQflXFb6.js} +1 -1
  133. package/dist/diff_tool/app/dist/assets/{edge-CwnxQiFe.js → edge-BmdmXGH4.js} +1 -1
  134. package/dist/diff_tool/app/dist/assets/{elixir-BVO19qQd.js → elixir-oiOLs98L.js} +1 -1
  135. package/dist/diff_tool/app/dist/assets/{elm-BK3istEo.js → elm-BgYuiU4E.js} +1 -1
  136. package/dist/diff_tool/app/dist/assets/{erb-CO4uKwKD.js → erb-CvFrXpyY.js} +1 -1
  137. package/dist/diff_tool/app/dist/assets/{git-rebase-CDrrgbGV.js → git-rebase-D3Zo1BLH.js} +1 -1
  138. package/dist/diff_tool/app/dist/assets/{glimmer-js-7CFSyo6c.js → glimmer-js-B4-8E3lJ.js} +1 -1
  139. package/dist/diff_tool/app/dist/assets/{glimmer-ts-Ofllf2Yo.js → glimmer-ts-CtKkD0t_.js} +1 -1
  140. package/dist/diff_tool/app/dist/assets/{glsl-K_36bq1K.js → glsl-BAqforx_.js} +1 -1
  141. package/dist/diff_tool/app/dist/assets/{graphql-BMZnssUN.js → graphql-DuE1RMyL.js} +1 -1
  142. package/dist/diff_tool/app/dist/assets/{hack-MG_t8QNs.js → hack-CHBcXjz1.js} +1 -1
  143. package/dist/diff_tool/app/dist/assets/{haml-0hDK-uCt.js → haml-DAs2z3tD.js} +1 -1
  144. package/dist/diff_tool/app/dist/assets/{handlebars-D4_MRJPB.js → handlebars-CfAla6QK.js} +1 -1
  145. package/dist/diff_tool/app/dist/assets/{html-BCi--7qp.js → html-D5co0BLD.js} +1 -1
  146. package/dist/diff_tool/app/dist/assets/{html-derivative-DYq2AWiD.js → html-derivative-BZaWEmAT.js} +1 -1
  147. package/dist/diff_tool/app/dist/assets/{http-BmLFm2Pm.js → http-Cii5MjJE.js} +1 -1
  148. package/dist/diff_tool/app/dist/assets/{hurl-CT71cK69.js → hurl-Bur-XdJO.js} +1 -1
  149. package/dist/diff_tool/app/dist/assets/index-CZUi_I-p.js +340 -0
  150. package/dist/diff_tool/app/dist/assets/{java-Bm2FCq-d.js → java-DN39wI4w.js} +1 -1
  151. package/dist/diff_tool/app/dist/assets/{javascript-C7oEny21.js → javascript-VUReF1H4.js} +1 -1
  152. package/dist/diff_tool/app/dist/assets/{jinja-igQBS-SS.js → jinja-BcrfV1JB.js} +1 -1
  153. package/dist/diff_tool/app/dist/assets/{jison-BrOUp4rK.js → jison-Bez5Mtmy.js} +1 -1
  154. package/dist/diff_tool/app/dist/assets/{json-DsuR7Nai.js → json-ChV8m0Le.js} +1 -1
  155. package/dist/diff_tool/app/dist/assets/{jsx-BdomFXcA.js → jsx-D0SXNtM0.js} +1 -1
  156. package/dist/diff_tool/app/dist/assets/{julia-DqOG4pbM.js → julia-DvhpcBwG.js} +1 -1
  157. package/dist/diff_tool/app/dist/assets/{just-ZrSTuT0n.js → just-BGwe8S6x.js} +1 -1
  158. package/dist/diff_tool/app/dist/assets/{latex-DbmtZIwN.js → latex-pWSag83P.js} +1 -1
  159. package/dist/diff_tool/app/dist/assets/{liquid-DKnUlRIp.js → liquid-UdnqDjKz.js} +1 -1
  160. package/dist/diff_tool/app/dist/assets/{lua-Cyq3f59a.js → lua-CjDHeHEr.js} +1 -1
  161. package/dist/diff_tool/app/dist/assets/{marko-hmOsFPHQ.js → marko-yLX6iW68.js} +1 -1
  162. package/dist/diff_tool/app/dist/assets/{mdc-BnnQmDC-.js → mdc-BOLj6Oyq.js} +1 -1
  163. package/dist/diff_tool/app/dist/assets/{nginx-C0zLUSna.js → nginx-5r5xPc2T.js} +1 -1
  164. package/dist/diff_tool/app/dist/assets/{nim-Oljl3c5n.js → nim-9exKQYMz.js} +1 -1
  165. package/dist/diff_tool/app/dist/assets/{org-Cp4CA-0c.js → org-B2fpAlbt.js} +1 -1
  166. package/dist/diff_tool/app/dist/assets/{perl-DstDVYmJ.js → perl-DV2fcwyY.js} +1 -1
  167. package/dist/diff_tool/app/dist/assets/{php-Cc3bNZ7J.js → php-D-AthX_E.js} +1 -1
  168. package/dist/diff_tool/app/dist/assets/{pug-B3xDUzl0.js → pug-DuKcQxFj.js} +1 -1
  169. package/dist/diff_tool/app/dist/assets/{qml-B9iDahKk.js → qml-C16b4SYx.js} +1 -1
  170. package/dist/diff_tool/app/dist/assets/{r-B7M5ZSBC.js → r-B1ZldnJf.js} +1 -1
  171. package/dist/diff_tool/app/dist/assets/{razor-BlfV6bjQ.js → razor-TYmslaAB.js} +1 -1
  172. package/dist/diff_tool/app/dist/assets/{regexp-BVT0NBj6.js → regexp-dWCffmDD.js} +1 -1
  173. package/dist/diff_tool/app/dist/assets/{rst-Cq-Mcher.js → rst-DEkLr2YR.js} +1 -1
  174. package/dist/diff_tool/app/dist/assets/{ruby-5uCK_s01.js → ruby-BJnJzr4u.js} +1 -1
  175. package/dist/diff_tool/app/dist/assets/{sas-m4dYluKN.js → sas-DeRsDbUE.js} +1 -1
  176. package/dist/diff_tool/app/dist/assets/{scss-DFiJcBQH.js → scss-SGV_CwKm.js} +1 -1
  177. package/dist/diff_tool/app/dist/assets/{shellscript-DCtSkJJQ.js → shellscript-BI7khmmR.js} +1 -1
  178. package/dist/diff_tool/app/dist/assets/{shellsession-_DntbpLM.js → shellsession-Nupw_Vvw.js} +1 -1
  179. package/dist/diff_tool/app/dist/assets/{soy-Dd1fWsG8.js → soy-B96cBzxv.js} +1 -1
  180. package/dist/diff_tool/app/dist/assets/{sql-Bygp5F-5.js → sql-CsIdKfaO.js} +1 -1
  181. package/dist/diff_tool/app/dist/assets/{stata-CqIA1VQD.js → stata-Dnq48cE6.js} +1 -1
  182. package/dist/diff_tool/app/dist/assets/{surrealql-C2-2C-z3.js → surrealql-D6lw4TiD.js} +1 -1
  183. package/dist/diff_tool/app/dist/assets/{svelte-CrTy7VSb.js → svelte-ChVoq9tB.js} +1 -1
  184. package/dist/diff_tool/app/dist/assets/{templ-B_h9AHFJ.js → templ-Dh1EXuHD.js} +1 -1
  185. package/dist/diff_tool/app/dist/assets/{tex-AwlGuBDG.js → tex-KTYusNFe.js} +1 -1
  186. package/dist/diff_tool/app/dist/assets/{ts-tags--oqU6stH.js → ts-tags-DC2RU1_R.js} +1 -1
  187. package/dist/diff_tool/app/dist/assets/{tsx-Cx-oUPFA.js → tsx-DtIM39Jy.js} +1 -1
  188. package/dist/diff_tool/app/dist/assets/{twig-DMQw3R9O.js → twig-C6D_TA3n.js} +1 -1
  189. package/dist/diff_tool/app/dist/assets/{typescript-BCtu9W7E.js → typescript-BGAE5iuw.js} +1 -1
  190. package/dist/diff_tool/app/dist/assets/{typst-jGrqJHSo.js → typst-nWoGZ22y.js} +1 -1
  191. package/dist/diff_tool/app/dist/assets/{vue-html-DTMalvg7.js → vue-html-prNdIjLu.js} +1 -1
  192. package/dist/diff_tool/app/dist/assets/{vue-GFZcsvXd.js → vue-iyHf-l4z.js} +1 -1
  193. package/dist/diff_tool/app/dist/assets/{vue-vine-BwDeqLrM.js → vue-vine-KSSlnVeg.js} +1 -1
  194. package/dist/diff_tool/app/dist/assets/{xml-CoXyuOzf.js → xml-DdCC83Xd.js} +1 -1
  195. package/dist/diff_tool/app/dist/assets/{xsl-BQFm34CN.js → xsl-DSqZxsez.js} +1 -1
  196. package/dist/diff_tool/app/dist/assets/{yaml-CbO2A_pF.js → yaml-CZcBUWvf.js} +1 -1
  197. package/dist/diff_tool/app/dist/index.html +1 -1
  198. package/dist/diff_tool/http_server.js +2 -9
  199. package/dist/diff_tool/http_server.js.map +1 -1
  200. package/dist/diff_tool/index.js +2 -2
  201. package/dist/diff_tool/index.js.map +1 -1
  202. package/dist/diff_tool/launcher.js +14 -8
  203. package/dist/diff_tool/launcher.js.map +1 -1
  204. package/dist/diff_tool/protocol_client.js +0 -7
  205. package/dist/diff_tool/protocol_client.js.map +1 -1
  206. package/dist/diff_tool/review_state.js +4 -10
  207. package/dist/diff_tool/review_state.js.map +1 -1
  208. package/dist/diff_tool/review_state_persistence.js +12 -7
  209. package/dist/diff_tool/review_state_persistence.js.map +1 -1
  210. package/dist/diff_tool/shared_types.js +0 -48
  211. package/dist/diff_tool/shared_types.js.map +1 -1
  212. package/dist/host/client_tool_broker.js +1 -1
  213. package/dist/host/client_tool_broker.js.map +1 -1
  214. package/dist/host/execution_runtime.js +1 -1
  215. package/dist/host/execution_runtime.js.map +1 -1
  216. package/dist/host/hosted_ephemeral_agent_session.js +1 -1
  217. package/dist/host/hosted_ephemeral_agent_session.js.map +1 -1
  218. package/dist/host/local_session_host.js +19 -19
  219. package/dist/host/local_session_host.js.map +1 -1
  220. package/dist/host/session_host.js.map +1 -1
  221. package/dist/main.js +2 -15
  222. package/dist/main.js.map +1 -1
  223. package/dist/protocol/index.d.ts +1 -1
  224. package/dist/protocol/index.js.map +1 -1
  225. package/dist/protocol/session_protocol.d.ts +14 -15
  226. package/dist/protocol/session_protocol.js +30 -12
  227. package/dist/protocol/session_protocol.js.map +1 -1
  228. package/dist/sdk/client_tool_command.d.ts +12 -11
  229. package/dist/sdk/client_tool_command.js +8 -8
  230. package/dist/sdk/client_tool_command.js.map +1 -1
  231. package/dist/sdk/code_mode.js +1 -1
  232. package/dist/sdk/code_mode.js.map +1 -1
  233. package/dist/sdk/local_client.js +1 -0
  234. package/dist/sdk/local_client.js.map +1 -1
  235. package/dist/sdk/session.js +1 -1
  236. package/dist/sdk/session.js.map +1 -1
  237. package/dist/sdk/types.d.ts +2 -1
  238. package/dist/store/session_snapshot_migrations.js +32 -1
  239. package/dist/store/session_snapshot_migrations.js.map +1 -1
  240. package/dist/tui/chat_controller/diff_review_service.js +0 -15
  241. package/dist/tui/chat_controller/diff_review_service.js.map +1 -1
  242. package/dist/tui/chat_view.js +8 -2
  243. package/dist/tui/chat_view.js.map +1 -1
  244. package/dist/tui/session_chat_app.js +1 -2
  245. package/dist/tui/session_chat_app.js.map +1 -1
  246. package/dist/tui/session_chat_controller.js +141 -42
  247. package/dist/tui/session_chat_controller.js.map +1 -1
  248. package/dist/tui/ui/custom_editor.js +70 -25
  249. package/dist/tui/ui/custom_editor.js.map +1 -1
  250. package/dist/tui/ui/footer.js +4 -2
  251. package/dist/tui/ui/footer.js.map +1 -1
  252. package/dist/tui/ui/slash_autocomplete.js +6 -9
  253. package/dist/tui/ui/slash_autocomplete.js.map +1 -1
  254. package/dist/tui/ui/subagent_panel.js +1 -12
  255. package/dist/tui/ui/subagent_panel.js.map +1 -1
  256. package/package.json +7 -6
  257. package/dist/core/config/diff_tool.js +0 -51
  258. package/dist/core/config/diff_tool.js.map +0 -1
  259. package/dist/core/subagents/default.js +0 -8
  260. package/dist/core/subagents/default.js.map +0 -1
  261. package/dist/diff_tool/app/dist/assets/index-DyaXBald.js +0 -340
  262. /package/dist/core/static/prompts/{default-subagent-wrapper.md → subagent-wrapper.md} +0 -0
@@ -1,6 +1,6 @@
1
1
  import { dirname } from "node:path/posix";
2
2
  import { createCommandRegistry, } from "../core/commands/index.js";
3
- import { getElevenLabsApiKey, getOpenAIApiKey, } from "../core/config/index.js";
3
+ import { getElevenLabsApiKey, getOpenAIApiKey } from "../core/config/index.js";
4
4
  import { captureDiffReviewSnapshot, DiffReviewBridge, } from "../core/diff_review/index.js";
5
5
  import { buildDiffReviewInstructions } from "../core/diff_review/review_instructions.js";
6
6
  import { createDefaultCoreDeps } from "../core/runtime/deps.js";
@@ -14,6 +14,7 @@ import { getSpeechToTextRecordingMaxDurationMs, getSpeechToTextStreamingSampleRa
14
14
  import { collectSpeechToTextContext } from "../core/utils/speech_to_text_context.js";
15
15
  import { formatTauUserText, hasAutoCompactionContinuationMetadata, splitTauUserText, } from "../core/utils/user_metadata.js";
16
16
  import { APP_VERSION } from "../core/version.js";
17
+ import { launchBuiltInDiffTool } from "../diff_tool/launcher.js";
17
18
  import { applySessionProtocolDelta, applySessionProtocolSubagentActivitiesMessage, } from "../protocol/session_protocol.js";
18
19
  import { TauSessionProtocolResponseError } from "../transport/errors.js";
19
20
  import { copyAssistantCodeToClipboard, copyAssistantTextToClipboard, } from "./chat_controller/assistant_clipboard.js";
@@ -37,7 +38,6 @@ export class SessionChatController {
37
38
  targetLabel;
38
39
  configuredClientToolNames;
39
40
  config;
40
- defaultDiffTool;
41
41
  diffToolLauncher;
42
42
  deps;
43
43
  speechToTextDeps;
@@ -88,6 +88,9 @@ export class SessionChatController {
88
88
  submissionHiddenSystemMessages = [];
89
89
  pendingEditorMutations = 0;
90
90
  speechActivityLabel;
91
+ autoSpeak = false;
92
+ pendingAutoSpeak;
93
+ lastAutoSpeakMessageId;
91
94
  speakTask;
92
95
  constructor(options) {
93
96
  this.view = options.view;
@@ -98,7 +101,6 @@ export class SessionChatController {
98
101
  this.targetLabel = options.targetLabel;
99
102
  this.configuredClientToolNames = options.configuredClientToolNames ?? [];
100
103
  this.config = options.config ?? {};
101
- this.defaultDiffTool = options.defaultDiffTool;
102
104
  this.diffToolLauncher = options.diffToolLauncher;
103
105
  this.deps = options.deps ?? createDefaultCoreDeps();
104
106
  this.speechToTextDeps = options.speechToTextDeps;
@@ -119,6 +121,7 @@ export class SessionChatController {
119
121
  reload: () => this.reloadContent(),
120
122
  listen: (action) => this.handleListenCommand(action),
121
123
  speak: () => this.speakLastAssistantMessage(),
124
+ autoSpeak: (enabled) => this.setAutoSpeak(enabled),
122
125
  persona: (id) => this.setPersona(id),
123
126
  prompt: (id) => this.insertPrompt(id),
124
127
  theme: (id) => this.switchTheme(id),
@@ -130,7 +133,6 @@ export class SessionChatController {
130
133
  refreshStatus: () => this.refreshStatus(),
131
134
  startTurnTimer: () => this.startTurnTimer(),
132
135
  stopTurnTimer: () => this.stopTurnTimer(),
133
- getDiffToolConfig: () => this.resolveDiffToolConfig(),
134
136
  startSession: (args) => this.startDiffReviewBridge(args, this.session, this.snapshot),
135
137
  onReviewReturned: (review) => this.handleReturnedDiffReview(review, this.session),
136
138
  });
@@ -187,7 +189,13 @@ export class SessionChatController {
187
189
  onShiftTab: () => void this.cycleReasoningLevel(),
188
190
  onCtrlP: () => void this.cyclePersonality(),
189
191
  onCtrlS: () => void this.stashEditorToClipboard(),
190
- onCtrlY: () => void this.toggleListenCapture(),
192
+ onToggleRecording: () => void this.toggleListenCapture(),
193
+ recordingShortcut: this.config.speech?.recordingShortcut,
194
+ onDisabledSubmit: (mode) => {
195
+ if (this.listenRecording && !this.listenTransition) {
196
+ void this.runListenTransition(() => this.stopListenCapture(mode));
197
+ }
198
+ },
191
199
  onCtrlG: () => this.interruptSelectedSubagent(),
192
200
  onEscape: () => void this.interrupt(),
193
201
  beforeSubmit: (text) => {
@@ -197,7 +205,7 @@ export class SessionChatController {
197
205
  },
198
206
  onChange: (text) => this.handleEditorChange(text),
199
207
  onSubmit: (text) => void this.handleSubmit(text, this.takeHiddenSystemSubmission()),
200
- onSteerSubmit: (text) => void this.submitSteeringMessage(text, this.takeHiddenSystemSubmission()),
208
+ onQueueSubmit: (text) => void this.handleSubmit(text, this.takeHiddenSystemSubmission(), "queue"),
201
209
  onAltUp: () => void this.cancelPendingMessagesIntoEditor(),
202
210
  onAltDown: () => this.cycleSubagentSelection(),
203
211
  };
@@ -234,7 +242,7 @@ export class SessionChatController {
234
242
  formatSubmittedText(text, hiddenSystemMessages) {
235
243
  return formatTauUserText({ text, hiddenSystemMessages });
236
244
  }
237
- async handleSubmit(text, hiddenSystemMessages = []) {
245
+ async handleSubmit(text, hiddenSystemMessages = [], mode = "steer") {
238
246
  const trimmed = text.trim();
239
247
  if (!trimmed) {
240
248
  if (this.isStreaming || this.submittedTurnInProgress) {
@@ -272,7 +280,11 @@ export class SessionChatController {
272
280
  if (trimmed.startsWith("!")) {
273
281
  return;
274
282
  }
275
- this.submitQueuedText(this.formatSubmittedText(trimmed, hiddenSystemMessages));
283
+ const submittedText = this.formatSubmittedText(trimmed, hiddenSystemMessages);
284
+ if (mode === "steer")
285
+ this.submitSteeringText(submittedText);
286
+ else
287
+ this.submitQueuedText(submittedText);
276
288
  return;
277
289
  }
278
290
  if (trimmed.startsWith("/") && this.isSingleLineInput(text)) {
@@ -314,6 +326,9 @@ export class SessionChatController {
314
326
  contextFiles: this.getContextFilePaths(),
315
327
  skills: this.snapshot.catalog.skills,
316
328
  themes: this.themeIds,
329
+ recordingShortcut: this.config.speech?.recordingShortcut
330
+ ? `${this.config.speech.recordingShortcut.gesture === "double-tap" ? "double-tap " : ""}${this.config.speech.recordingShortcut.key}`
331
+ : "ctrl+y",
317
332
  formatPath: (path) => formatPathForSessionDisplay(path, this.snapshot.executionEnvironment.home),
318
333
  }),
319
334
  });
@@ -353,7 +368,6 @@ export class SessionChatController {
353
368
  themes: () => this.themeIds.map((id) => ({ id })),
354
369
  autocompletePaths: async (query, limit) => (await this.session.autocompletePaths({ query, limit })).paths,
355
370
  skills: () => this.snapshot.catalog.skills.map((skill) => skill.name),
356
- subagents: () => Object.keys(this.getCurrentPersonaSnapshot()?.subagents ?? {}),
357
371
  };
358
372
  }
359
373
  buildStartupIntroTitle() {
@@ -473,21 +487,6 @@ export class SessionChatController {
473
487
  this.view.requestRender();
474
488
  }
475
489
  }
476
- async submitSteeringMessage(text, hiddenSystemMessages = []) {
477
- const trimmed = text.trim();
478
- if (!trimmed) {
479
- return;
480
- }
481
- if (!this.isSessionOperationActive()) {
482
- await this.runSessionTurn(() => this.session.submit(this.formatSubmittedText(trimmed, hiddenSystemMessages)));
483
- return;
484
- }
485
- if (this.isBlockingSessionOperationActive()) {
486
- this.view.showFooterNotice("wait for tau to become idle before submitting input", "default");
487
- return;
488
- }
489
- this.submitSteeringText(this.formatSubmittedText(trimmed, hiddenSystemMessages));
490
- }
491
490
  submitQueuedText(text) {
492
491
  void this.session.queue(text).catch((error) => {
493
492
  if (!this.isPendingMessageCancellation(error)) {
@@ -553,8 +552,10 @@ export class SessionChatController {
553
552
  this.view.startWorkingIcon();
554
553
  this.refreshStatus();
555
554
  try {
556
- await task();
555
+ const result = await task();
557
556
  await this.syncFromSessionSnapshot();
557
+ if (result.turn.status === "completed")
558
+ this.queueAutoSpeak();
558
559
  }
559
560
  catch (error) {
560
561
  this.view.addTranscriptNotice("failed to run assistant turn", "error", [
@@ -570,6 +571,7 @@ export class SessionChatController {
570
571
  }
571
572
  }
572
573
  async interrupt() {
574
+ this.pendingAutoSpeak = undefined;
573
575
  if (this.interruptLifecycle.interruptActiveTask()) {
574
576
  this.view.showFooterNotice("interrupted", "default");
575
577
  return;
@@ -655,7 +657,15 @@ export class SessionChatController {
655
657
  this.view.showFooterNotice("speech transcription already in progress", "default");
656
658
  return;
657
659
  }
658
- await this.runListenTransition(() => this.startListenCapture());
660
+ this.pendingAutoSpeak = undefined;
661
+ await this.runListenTransition(async () => {
662
+ if (this.speakTask) {
663
+ this.speakTask.abortController.abort();
664
+ await this.speakTask.completion.catch(() => { });
665
+ }
666
+ if (!this.disposed)
667
+ await this.startListenCapture();
668
+ });
659
669
  }
660
670
  async runListenTransition(task) {
661
671
  if (this.listenTransition) {
@@ -790,7 +800,7 @@ export class SessionChatController {
790
800
  clearTimeout(timeout);
791
801
  }
792
802
  }
793
- async stopListenCapture() {
803
+ async stopListenCapture(mode) {
794
804
  const recording = this.listenRecording;
795
805
  if (!recording)
796
806
  return;
@@ -810,7 +820,9 @@ export class SessionChatController {
810
820
  return;
811
821
  }
812
822
  const durationMs = Math.min(Math.max(Date.now() - recording.startedAt, 0), SPEECH_TO_TEXT_CLIENT_MAX_DURATION_MS);
813
- await this.transcribeListenAudioFile(recording.audioPath, durationMs, recording.transcription);
823
+ const transcribed = await this.transcribeListenAudioFile(recording.audioPath, durationMs, recording.transcription);
824
+ if (mode && transcribed && !this.disposed)
825
+ this.view.submitEditor(mode);
814
826
  }
815
827
  async retryRetainedListenAudio() {
816
828
  if (this.pendingEditorMutations > 0) {
@@ -826,7 +838,9 @@ export class SessionChatController {
826
838
  this.view.showFooterNotice("no failed speech recording to retry", "default");
827
839
  return;
828
840
  }
829
- await this.runListenTransition(() => this.transcribeListenAudioFile(retainedAudio.audioPath, retainedAudio.durationMs));
841
+ await this.runListenTransition(async () => {
842
+ await this.transcribeListenAudioFile(retainedAudio.audioPath, retainedAudio.durationMs);
843
+ });
830
844
  }
831
845
  async discardRetainedListenAudio() {
832
846
  if (this.listenRecording || this.listenTransition || this.listenActivityLabel) {
@@ -883,7 +897,7 @@ export class SessionChatController {
883
897
  this.retainedListenAudio = undefined;
884
898
  }
885
899
  await cleanupListenTempFile(audioPath);
886
- return;
900
+ return false;
887
901
  }
888
902
  if (!this.listenPreview)
889
903
  this.beginListenPreview();
@@ -897,7 +911,7 @@ export class SessionChatController {
897
911
  `recording retained at ${audioPath}`,
898
912
  "run /listen discard to delete it",
899
913
  ]);
900
- return;
914
+ return false;
901
915
  }
902
916
  let audio;
903
917
  try {
@@ -912,7 +926,7 @@ export class SessionChatController {
912
926
  this.retainedListenAudio = undefined;
913
927
  }
914
928
  await cleanupListenTempFile(audioPath);
915
- return;
929
+ return false;
916
930
  }
917
931
  if (audio.byteLength < LISTEN_RECORDING_MIN_BYTES) {
918
932
  transcription?.abort();
@@ -921,7 +935,7 @@ export class SessionChatController {
921
935
  this.retainedListenAudio = undefined;
922
936
  }
923
937
  await cleanupListenTempFile(audioPath);
924
- return;
938
+ return false;
925
939
  }
926
940
  if (this.disposed) {
927
941
  transcription?.abort();
@@ -929,7 +943,7 @@ export class SessionChatController {
929
943
  this.retainedListenAudio = undefined;
930
944
  }
931
945
  await cleanupListenTempFile(audioPath);
932
- return;
946
+ return false;
933
947
  }
934
948
  let activeTranscription = transcription;
935
949
  this.listenActivityLabel = "transcribing voice input";
@@ -942,7 +956,7 @@ export class SessionChatController {
942
956
  mimeType: "audio/wav",
943
957
  });
944
958
  if (this.listenPreview !== preview)
945
- return;
959
+ return false;
946
960
  preview.commit(text);
947
961
  if (text.trim() && !this.editorHiddenSystemMessages.includes(TRANSCRIPTION_GUIDANCE)) {
948
962
  this.editorHiddenSystemMessages.push(TRANSCRIPTION_GUIDANCE);
@@ -957,6 +971,7 @@ export class SessionChatController {
957
971
  `recording remains at ${audioPath}; delete it manually`,
958
972
  ]);
959
973
  }
974
+ return Boolean(text.trim());
960
975
  }
961
976
  catch (error) {
962
977
  this.retainedListenAudio = { audioPath, durationMs };
@@ -965,6 +980,7 @@ export class SessionChatController {
965
980
  `recording retained at ${audioPath}`,
966
981
  "run /listen retry to try again, or /listen discard to delete it",
967
982
  ]);
983
+ return false;
968
984
  }
969
985
  finally {
970
986
  activeTranscription?.abort();
@@ -1117,6 +1133,9 @@ export class SessionChatController {
1117
1133
  this.ephemeralUnsubscribe?.();
1118
1134
  this.pendingUserMessagesUnsubscribe?.();
1119
1135
  this.subagentActivitiesUnsubscribe?.();
1136
+ this.autoSpeak = false;
1137
+ this.pendingAutoSpeak = undefined;
1138
+ this.lastAutoSpeakMessageId = undefined;
1120
1139
  this.session = nextSession;
1121
1140
  this.snapshot = nextSnapshot;
1122
1141
  this.subagentActivities = nextSession.subagentActivities();
@@ -1218,9 +1237,48 @@ export class SessionChatController {
1218
1237
  this.snapshotRecoveryDeltas.push(delta);
1219
1238
  return;
1220
1239
  }
1240
+ if (delta.toRevision <= this.snapshot.revision)
1241
+ return;
1242
+ const invalidatesSpeech = delta.cause.type === "rewind" ||
1243
+ delta.cause.type === "compaction" ||
1244
+ delta.cause.type === "resync";
1245
+ if (invalidatesSpeech)
1246
+ this.pendingAutoSpeak = undefined;
1247
+ const previousLifecycle = this.snapshot.lifecycle;
1248
+ const previousTurns = this.snapshot.turns;
1221
1249
  if (this.tryApplySdkDelta(delta)) {
1250
+ if (this.autoSpeak && !invalidatesSpeech) {
1251
+ if (previousLifecycle !== "running" && this.snapshot.lifecycle === "running") {
1252
+ this.pendingAutoSpeak = undefined;
1253
+ this.speakTask?.abortController.abort();
1254
+ this.lastAutoSpeakMessageId = this.snapshot.messages.findLast((entry) => isAssistantMessage(entry.message) && entry.state === "committed")?.id;
1255
+ }
1256
+ if (delta.delta.type === "snapshot.patch") {
1257
+ for (const change of delta.delta.changes) {
1258
+ if (change.type !== "turn.set")
1259
+ continue;
1260
+ const turn = change.turn;
1261
+ if (turn.state === "running") {
1262
+ this.pendingAutoSpeak = undefined;
1263
+ this.speakTask?.abortController.abort();
1264
+ continue;
1265
+ }
1266
+ if (previousTurns[turn.userHistoryEntryId]?.state === "running" &&
1267
+ turn.outcome.status === "completed") {
1268
+ this.queueAutoSpeak();
1269
+ }
1270
+ }
1271
+ }
1272
+ if (previousLifecycle === "running" &&
1273
+ this.snapshot.lifecycle === "idle" &&
1274
+ !Object.values(previousTurns).some((turn) => turn.state === "running")) {
1275
+ this.queueAutoSpeak();
1276
+ }
1277
+ this.drainAutoSpeak();
1278
+ }
1222
1279
  return;
1223
1280
  }
1281
+ this.pendingAutoSpeak = undefined;
1224
1282
  this.snapshotRecoveryDeltas.push(delta);
1225
1283
  void this.recoverFromRevisionGap();
1226
1284
  }
@@ -1988,7 +2046,50 @@ export class SessionChatController {
1988
2046
  this.view.addTranscriptNotice("failed to clear goal", "error", [error.message]);
1989
2047
  }
1990
2048
  }
1991
- async speakLastAssistantMessage() {
2049
+ setAutoSpeak(enabled) {
2050
+ if ((enabled ?? !this.autoSpeak) && this.deps.env.platform() !== "darwin") {
2051
+ this.view.showFooterNotice("auto-speak is currently supported only on macOS", "default");
2052
+ return;
2053
+ }
2054
+ const next = enabled ?? !this.autoSpeak;
2055
+ if (next && !this.autoSpeak) {
2056
+ this.lastAutoSpeakMessageId = this.snapshot.messages.findLast((entry) => isAssistantMessage(entry.message))?.id;
2057
+ }
2058
+ this.autoSpeak = next;
2059
+ if (!this.autoSpeak) {
2060
+ this.pendingAutoSpeak = undefined;
2061
+ this.speakTask?.abortController.abort();
2062
+ }
2063
+ this.view.showFooterNotice(`auto-speak ${this.autoSpeak ? "on" : "off"}`, "default");
2064
+ this.refreshStatus();
2065
+ }
2066
+ queueAutoSpeak() {
2067
+ if (!this.autoSpeak)
2068
+ return;
2069
+ const entry = this.snapshot.messages.findLast((entry) => isAssistantMessage(entry.message));
2070
+ if (!entry || entry.id === this.lastAutoSpeakMessageId || !isAssistantMessage(entry.message))
2071
+ return;
2072
+ this.lastAutoSpeakMessageId = entry.id;
2073
+ if (entry.message.stopReason === "stop" || entry.message.stopReason === "length") {
2074
+ this.pendingAutoSpeak = entry.message;
2075
+ }
2076
+ }
2077
+ drainAutoSpeak() {
2078
+ if (!this.pendingAutoSpeak || this.isSessionOperationActive())
2079
+ return;
2080
+ const message = this.pendingAutoSpeak;
2081
+ this.pendingAutoSpeak = undefined;
2082
+ if (!this.autoSpeak ||
2083
+ this.disposed ||
2084
+ this.listenRecording ||
2085
+ this.listenTransition ||
2086
+ this.listenActivityLabel ||
2087
+ this.speakTask ||
2088
+ this.hasPendingUserMessages)
2089
+ return;
2090
+ void this.speakLastAssistantMessage(message);
2091
+ }
2092
+ async speakLastAssistantMessage(message) {
1992
2093
  if (this.speakTask) {
1993
2094
  this.view.showFooterNotice("speech playback already in progress", "default");
1994
2095
  return;
@@ -2001,7 +2102,7 @@ export class SessionChatController {
2001
2102
  this.view.showFooterNotice("/speak is currently supported only on macOS.", "default");
2002
2103
  return;
2003
2104
  }
2004
- const lastAssistant = this.getLastAssistantMessage();
2105
+ const lastAssistant = message ?? this.getLastAssistantMessage();
2005
2106
  if (!lastAssistant) {
2006
2107
  this.view.showFooterNotice("no assistant message to speak yet.", "default");
2007
2108
  return;
@@ -2067,6 +2168,7 @@ export class SessionChatController {
2067
2168
  });
2068
2169
  }
2069
2170
  refreshStatus() {
2171
+ this.drainAutoSpeak();
2070
2172
  const activityLabel = this.getActivityLabel();
2071
2173
  this.view.updateStatus({
2072
2174
  footer: activityLabel
@@ -2078,6 +2180,7 @@ export class SessionChatController {
2078
2180
  sessionCost: this.getSessionCostString(),
2079
2181
  duration: this.getTurnDurationString(),
2080
2182
  pursuingGoal: this.snapshot.goal?.status === "active",
2183
+ autoSpeak: this.autoSpeak,
2081
2184
  },
2082
2185
  editor: {
2083
2186
  mode: this.getInputMode(),
@@ -2278,9 +2381,6 @@ export class SessionChatController {
2278
2381
  !this.listenActivityLabel &&
2279
2382
  !this.speakTask);
2280
2383
  }
2281
- resolveDiffToolConfig() {
2282
- return this.config.diffTool ?? this.defaultDiffTool;
2283
- }
2284
2384
  async startDiffReviewBridge(args, session, sessionSnapshot, executionEnvironment = session) {
2285
2385
  const cwd = sessionSnapshot.executionEnvironment.cwd;
2286
2386
  const backend = createSdkToolExecutionBackend({ executionEnvironment, cwd });
@@ -2305,7 +2405,6 @@ export class SessionChatController {
2305
2405
  ...(options.reasoning !== undefined ? { reasoning: options.reasoning } : {}),
2306
2406
  }),
2307
2407
  deps: this.deps,
2308
- ...(this.diffToolLauncher ? { toolLauncher: this.diffToolLauncher } : {}),
2309
2408
  });
2310
2409
  const unsubscribeEphemeral = session.onEphemeral((message) => {
2311
2410
  const event = message.event;
@@ -2326,7 +2425,7 @@ export class SessionChatController {
2326
2425
  if (args.signal.aborted) {
2327
2426
  throw new Error("diff review start aborted");
2328
2427
  }
2329
- await bridge.launchTool(args.diffTool);
2428
+ await bridge.launchTool(this.diffToolLauncher ?? launchBuiltInDiffTool);
2330
2429
  }
2331
2430
  catch (error) {
2332
2431
  unsubscribeEphemeral();