@markusylisiurunen/tau 0.3.68 → 0.3.70
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/core/history/cli.js +8 -1
- package/dist/core/history/cli.js.map +1 -1
- package/dist/core/history/migrations.js +0 -55
- package/dist/core/history/migrations.js.map +1 -1
- package/dist/core/history/remote_history_client.js +14 -2
- package/dist/core/history/remote_history_client.js.map +1 -1
- package/dist/core/history/replication.js +1 -1
- package/dist/core/history/replication.js.map +1 -1
- package/dist/core/history/setup.js +31 -4
- package/dist/core/history/setup.js.map +1 -1
- package/dist/core/personas.js +34 -3
- package/dist/core/personas.js.map +1 -1
- package/dist/core/static/code_mode/history/documentation.md +3 -1
- package/dist/core/static/tau_docs/history.md +28 -6
- package/dist/core/static/tau_docs/prompts-and-project-context.md +8 -0
- package/dist/core/static/tau_docs/telegram.md +6 -5
- package/dist/core/static/tau_docs/tui.md +2 -2
- package/dist/core/telegram/adapter.js +117 -3
- package/dist/core/telegram/adapter.js.map +1 -1
- package/dist/core/telegram/config.js +1 -1
- package/dist/core/telegram/session_manager.js +26 -0
- package/dist/core/telegram/session_manager.js.map +1 -1
- package/dist/core/tools/history.js +1 -0
- package/dist/core/tools/history.js.map +1 -1
- package/dist/core/utils/gemini_speech.js +1 -1
- package/dist/core/utils/gemini_transcription.js +1 -1
- package/dist/core/version.js +2 -2
- package/dist/diff_tool/app/dist/assets/{angular-html-D1LkfYUk.js → angular-html-TGVKIbXA.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{angular-ts-GBkN0dgz.js → angular-ts-BR1Ck4xw.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{apl-B9B6LoBR.js → apl-DX86sScC.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{astro-Bq1oMHJ9.js → astro-CPBmHrtV.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{blade-COJUdHCh.js → blade-CxhONptb.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{c-B5mehGRz.js → c-DGLPRsse.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{chapel-mTzW_3Rb.js → chapel-RThVDyb2.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{cobol-CUZj6Dna.js → cobol-DdmfL9_4.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{coffee-CNqmYL25.js → coffee-Cc3rH_kQ.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{cpp-CRMagQcD.js → cpp-ByIB1X9N.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{crystal-DCj_yeSi.js → crystal-D4oyx0-U.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{css-DAwpXLWY.js → css-D8nErU8j.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{edge-CtFTwS18.js → edge-CwM1llxP.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{elixir-C1OrVr_M.js → elixir-CH1xxWSt.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{elm-BdS37bq6.js → elm-DIHxLa6c.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{erb-Ba0Xnkuj.js → erb-Cm1nGJ0q.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{git-rebase-DRtTCAv_.js → git-rebase-XqH6cLrF.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{glimmer-js-B4F-uWDL.js → glimmer-js-BqGQt95b.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{glimmer-ts-JRBbzMuE.js → glimmer-ts-C9m18ZbT.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{glsl-B0F7j1rZ.js → glsl-F8r7-2qc.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{graphql-B2oXozjz.js → graphql-HRIQ08tp.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{hack-BmdKh4Xg.js → hack-b2OBFgba.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{haml-B5txh1mt.js → haml-BMiBYzBg.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{handlebars-BrOeahQH.js → handlebars-DekHln92.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{html-CwVI_Nmo.js → html-0sl00AVS.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{html-derivative-Dmp-VtO0.js → html-derivative-olhhIOfr.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{http-DZvA2jMi.js → http-DHDcde9F.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{hurl-Czca3pRy.js → hurl-DDYRhecJ.js} +1 -1
- package/dist/diff_tool/app/dist/assets/index-C-CAr6eO.js +1559 -0
- package/dist/diff_tool/app/dist/assets/{java-C9B5avDT.js → java-HX7ZmFma.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{javascript-DdUPgmCi.js → javascript-B46p6LUW.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{jinja-C88anDVh.js → jinja-0oRZFwZT.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{jison-CYn9Sl79.js → jison-Bsqd8yEw.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{json-CYp3vrCJ.js → json-1uKHLwRn.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{jsx-BuDHdbPM.js → jsx-D2laGlc4.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{julia-CLyKC_SD.js → julia-B7CzN7W2.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{just-BRw_BRkc.js → just-Duoo4Aa7.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{latex-Bsyk0ZET.js → latex-yy-UOrbw.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{liquid-B2KWKTUY.js → liquid-DGliSu2Y.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{lua-BBCZNaoe.js → lua-MFb4H6uH.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{marko-CzEoqxXx.js → marko-DO4tJoIQ.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{mdc-BYYhPtQ2.js → mdc-B_h-aRcg.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{nginx-B0ANyMYF.js → nginx-ZW7yrLH6.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{nim-BnO-hPuv.js → nim-DTOMK7Zk.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{org-DZ53bUbb.js → org-BRx006Oj.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{perl-DCaXAjqZ.js → perl-CzcNKD-6.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{php-DFJP7AYG.js → php-BiSrGF6V.js} +1 -1
- package/dist/diff_tool/app/dist/assets/pierre-dark-CpLgRqie.js +1 -0
- package/dist/diff_tool/app/dist/assets/pierre-dark-protanopia-deuteranopia-B35FxJx-.js +1 -0
- package/dist/diff_tool/app/dist/assets/pierre-dark-soft-kZQmAZld.js +1 -0
- package/dist/diff_tool/app/dist/assets/pierre-dark-tritanopia-CpjhbsIL.js +1 -0
- package/dist/diff_tool/app/dist/assets/pierre-dark-vibrant-CpQYzh95.js +1 -0
- package/dist/diff_tool/app/dist/assets/pierre-light-CoaEpmwp.js +1 -0
- package/dist/diff_tool/app/dist/assets/pierre-light-protanopia-deuteranopia-0fSaH845.js +1 -0
- package/dist/diff_tool/app/dist/assets/pierre-light-soft-lWLdNTOI.js +1 -0
- package/dist/diff_tool/app/dist/assets/pierre-light-tritanopia-CEbqgOJL.js +1 -0
- package/dist/diff_tool/app/dist/assets/pierre-light-vibrant-D80Fkn33.js +1 -0
- package/dist/diff_tool/app/dist/assets/{pug-CibApuhk.js → pug-CYv51GYY.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{qml-DwVnDdTM.js → qml-0pTrG3lk.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{r-C4Dchd1P.js → r-B0zy4_qi.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{razor-CyJ-w1Ub.js → razor-BMuOnZCw.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{regexp-CNghQ5eY.js → regexp-D4sf8V9F.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{rst-CynWjePz.js → rst-B-dJoZuq.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{ruby-CLYbVE1Z.js → ruby-B9dG1g9M.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{sas-bJHxiY-x.js → sas-jS1VjXDD.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{scss-CcgsuVdc.js → scss-DaEAH7JG.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{shellscript-CFJeRn3g.js → shellscript-D26VaoMD.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{shellsession-BzeG4DIz.js → shellsession-BrDdB3Ze.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{soy-B1Ewncjv.js → soy-Dw-L8Pu_.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{sql-C6gIz-i-.js → sql-C81_P4zv.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{stata-DZ3n2NNy.js → stata-CvjhiEWy.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{surrealql-CxjJ_MYO.js → surrealql-zH2wPEcX.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{svelte-Dad0hAwn.js → svelte-DkxiJRsu.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{templ-BuNk0dhh.js → templ-iHivH4zC.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{tex-C61-WHOR.js → tex-tmkUHMpX.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{ts-tags-BMWGwRt6.js → ts-tags-Co_nt4ji.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{tsx-AKa5rdAm.js → tsx-Bq4h6cEE.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{twig-CKXFwiec.js → twig-BrgfE6ee.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{typescript-BzRr3JI0.js → typescript-DXeIJyMP.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{typst-BXNdvFzz.js → typst-BDxuPNyd.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{vue-Du8kVE1C.js → vue-DpegOn40.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{vue-html-DMrkK9XH.js → vue-html-9jsGeHE2.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{vue-vine-5f0lzpP6.js → vue-vine-Di2kBUqf.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{xml-BUuAw89A.js → xml-DAh0wZod.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{xsl-cGKOdY7Q.js → xsl-CAKtuHsO.js} +1 -1
- package/dist/diff_tool/app/dist/assets/{yaml-BxZ2CAV2.js → yaml-G84U_K-l.js} +1 -1
- package/dist/diff_tool/app/dist/index.html +1 -1
- package/dist/history/worker/index.js +369 -35
- package/dist/history/worker/index.js.map +1 -1
- package/dist/history/worker/migrations/0001_initial.sql +54 -0
- package/dist/history/worker/viewer.css +72 -0
- package/dist/history/worker/viewer.js +116 -0
- package/dist/host/local_session_host.js +0 -1
- package/dist/host/local_session_host.js.map +1 -1
- package/dist/host/session_protocol_handler.js +2 -1
- package/dist/host/session_protocol_handler.js.map +1 -1
- package/dist/protocol/session_protocol.js +46 -0
- package/dist/protocol/session_protocol.js.map +1 -1
- package/dist/tui/chat_view.js +4 -4
- package/dist/tui/chat_view.js.map +1 -1
- package/dist/tui/session_chat_controller.js +3 -1
- package/dist/tui/session_chat_controller.js.map +1 -1
- package/dist/tui/tool_ui_router.js +1 -1
- package/dist/tui/tool_ui_router.js.map +1 -1
- package/dist/tui/ui/chat_container.js +24 -19
- package/dist/tui/ui/chat_container.js.map +1 -1
- package/package.json +15 -10
- package/dist/diff_tool/app/dist/assets/index-B9k3vTfc.js +0 -1565
- package/dist/diff_tool/app/dist/assets/theming-B5HubD5i.js +0 -1
- package/dist/diff_tool/app/dist/assets/theming-BTK0wyKj.js +0 -1
- package/dist/diff_tool/app/dist/assets/theming-BTUlzJFw.js +0 -1
- package/dist/diff_tool/app/dist/assets/theming-BURFlYfV.js +0 -1
- package/dist/diff_tool/app/dist/assets/theming-BVZjihoZ.js +0 -1
- package/dist/diff_tool/app/dist/assets/theming-BWSkzMBn.js +0 -1
- package/dist/diff_tool/app/dist/assets/theming-BchIqPOb.js +0 -1
- package/dist/diff_tool/app/dist/assets/theming-CeLfRn2P.js +0 -1
- package/dist/diff_tool/app/dist/assets/theming-DMjwMSwU.js +0 -1
- package/dist/diff_tool/app/dist/assets/theming-QWGGdlwd.js +0 -1
|
@@ -51,7 +51,7 @@ When Tau is idle, Enter and Ctrl+Enter both start a normal turn. While a turn is
|
|
|
51
51
|
|
|
52
52
|
Pending input is session state shared by attached clients while the host remains alive. It is not durable across host restart or session recovery. A queued turn captures the persona, reasoning, tools, and model settings when that turn actually starts. Steering remains part of the active logical turn and keeps the settings captured when that turn began.
|
|
53
53
|
|
|
54
|
-
Escape interrupts foreground client work or the main session’s active work. If a local diff review, recording, or speech playback task owns the foreground, Escape stops that task first; otherwise it requests main-session interruption from the host. It does not stop independently running supervised subagents; select one with Alt+Down and use Ctrl+G. Press Escape twice to clear the current editor text.
|
|
54
|
+
Escape interrupts foreground client work or the main session’s active work. If a local diff review, recording, or speech playback task owns the foreground, Escape stops that task first; otherwise it requests main-session interruption from the host, including cancellation of a running manual compaction. Once compaction has replaced model context, a late interruption does not undo it or turn successful persistence into a failure. It does not stop independently running supervised subagents; select one with Alt+Down and use Ctrl+G. Press Escape twice to clear the current editor text.
|
|
55
55
|
|
|
56
56
|
Press Enter twice on an empty editor to retry from the current session history. Retry does not rewind or duplicate the last user message. Goal-controlled turns cannot be retried; resume a blocked goal instead.
|
|
57
57
|
|
|
@@ -199,7 +199,7 @@ The TUI also advertises diff review as a client tool unless `--no-client-tools`
|
|
|
199
199
|
|
|
200
200
|
`/listen` and Ctrl+Y are currently macOS-only. Recording uses local `ffmpeg` with the AVFoundation audio input and stops when Ctrl+Y is pressed again, when Escape is pressed, or after 20 minutes. Startup fails if the microphone produces no audio within 15 seconds. Stopping manually or reaching the 20-minute limit finishes transcription and inserts the transcript at the cursor for review without submitting it.
|
|
201
201
|
|
|
202
|
-
If transcription fails, Tau retains the local WAV and reports its path. Run `/listen retry` to transcribe the same audio again with the current provider and conversation context, or `/listen discard` to delete it. Retained recordings longer than 20 minutes are rejected rather than sent to the provider. A replacement recording deletes the retained file only after the new capture starts producing audio. Tau keeps at most one failed recording, and exiting leaves that file at the reported path for manual recovery. For live transcription, both providers extract spelling hints from recent conversation while recording begins, buffer audio until the transcription session is ready, and then stream subsequent audio. Gemini uses Gemini 3.
|
|
202
|
+
If transcription fails, Tau retains the local WAV and reports its path. Run `/listen retry` to transcribe the same audio again with the current provider and conversation context, or `/listen discard` to delete it. Retained recordings longer than 20 minutes are rejected rather than sent to the provider. A replacement recording deletes the retained file only after the new capture starts producing audio. Tau keeps at most one failed recording, and exiting leaves that file at the reported path for manual recovery. For live transcription, both providers extract spelling hints from recent conversation while recording begins, buffer audio until the transcription session is ready, and then stream subsequent audio. Gemini uses Gemini 3.8 Flash for hint extraction and `gemini-3.5-transcribe-live` in smart mode; OpenAI uses GPT-5.6 Luna and `gpt-live-transcribe`. Hint extraction failure does not fail transcription. On retry, Gemini uploads the retained recording for `gemini-3.5-transcribe` smart transcription and attempts to delete the remote file afterward; OpenAI uploads it to `gpt-transcribe` with recent context.
|
|
203
203
|
|
|
204
204
|
Install `ffmpeg` and configure a speech-to-text provider:
|
|
205
205
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
1
2
|
import { mkdtemp, readdir, rm, writeFile } from "node:fs/promises";
|
|
2
3
|
import { tmpdir } from "node:os";
|
|
3
4
|
import { basename, extname, join } from "node:path";
|
|
@@ -543,7 +544,7 @@ const TelegramCallbackQuerySchema = telegramPartialObject({
|
|
|
543
544
|
id: z.string(),
|
|
544
545
|
from: TelegramUserSchema,
|
|
545
546
|
data: z.string(),
|
|
546
|
-
message: telegramPartialObject({ chat: TelegramChatSchema }),
|
|
547
|
+
message: telegramPartialObject({ message_id: z.number(), chat: TelegramChatSchema }),
|
|
547
548
|
});
|
|
548
549
|
const TelegramUpdateSchema = telegramPartialObject({
|
|
549
550
|
update_id: z.number(),
|
|
@@ -721,6 +722,14 @@ function createTelegramApi(botToken) {
|
|
|
721
722
|
...(options?.replyMarkup ? { reply_markup: options.replyMarkup } : {}),
|
|
722
723
|
}, z.unknown(), options.signal);
|
|
723
724
|
},
|
|
725
|
+
async editMessage(chatId, messageId, text, options) {
|
|
726
|
+
await callTelegramMethod("editMessageText", {
|
|
727
|
+
chat_id: chatId,
|
|
728
|
+
message_id: messageId,
|
|
729
|
+
text,
|
|
730
|
+
reply_markup: options.replyMarkup ?? { inline_keyboard: [] },
|
|
731
|
+
}, z.unknown(), options.signal);
|
|
732
|
+
},
|
|
724
733
|
async sendRichMessage(chatId, markdown, options) {
|
|
725
734
|
await callTelegramMethod("sendRichMessage", {
|
|
726
735
|
chat_id: chatId,
|
|
@@ -806,6 +815,7 @@ class TelegramAdapterImpl {
|
|
|
806
815
|
commandHandlers;
|
|
807
816
|
callbackActionHandlers;
|
|
808
817
|
abortController = new AbortController();
|
|
818
|
+
promptPickers = new Map();
|
|
809
819
|
activeSessionsByChat = new Map();
|
|
810
820
|
sessionsByChat = new Map();
|
|
811
821
|
chatsBySession = new Map();
|
|
@@ -929,6 +939,11 @@ class TelegramAdapterImpl {
|
|
|
929
939
|
callbackAction: "status",
|
|
930
940
|
handler: async (chatId) => this.handleStatus(chatId),
|
|
931
941
|
},
|
|
942
|
+
{
|
|
943
|
+
command: "/prompt",
|
|
944
|
+
description: "add a saved prompt without starting a turn",
|
|
945
|
+
handler: async (chatId, args) => this.handlePrompt(chatId, args),
|
|
946
|
+
},
|
|
932
947
|
{
|
|
933
948
|
command: "/compact",
|
|
934
949
|
description: "compact session context",
|
|
@@ -1203,7 +1218,7 @@ class TelegramAdapterImpl {
|
|
|
1203
1218
|
await this.answerCallbackQuery(callbackQuery.id);
|
|
1204
1219
|
return;
|
|
1205
1220
|
}
|
|
1206
|
-
const callbackHandled = await this.handleCallback(chat.id, callbackData);
|
|
1221
|
+
const callbackHandled = await this.handleCallback(chat.id, callbackData, callbackQuery.message?.message_id);
|
|
1207
1222
|
await this.answerCallbackQuery(callbackQuery.id, callbackHandled ? "done" : undefined);
|
|
1208
1223
|
}
|
|
1209
1224
|
parseAudioMessage(message) {
|
|
@@ -1583,7 +1598,11 @@ class TelegramAdapterImpl {
|
|
|
1583
1598
|
}
|
|
1584
1599
|
await handler(chatId, args, sourceMessageId);
|
|
1585
1600
|
}
|
|
1586
|
-
async handleCallback(chatId, callbackData) {
|
|
1601
|
+
async handleCallback(chatId, callbackData, messageId) {
|
|
1602
|
+
if (callbackData.startsWith("prompt:")) {
|
|
1603
|
+
await this.handlePromptCallback(chatId, callbackData, messageId);
|
|
1604
|
+
return true;
|
|
1605
|
+
}
|
|
1587
1606
|
if (!callbackData.startsWith(CALLBACK_ACTION_PREFIX)) {
|
|
1588
1607
|
return false;
|
|
1589
1608
|
}
|
|
@@ -1650,6 +1669,101 @@ class TelegramAdapterImpl {
|
|
|
1650
1669
|
await this.reply(chatId, `failed to save voice response preference: ${error instanceof Error ? error.message : String(error)}`);
|
|
1651
1670
|
}
|
|
1652
1671
|
}
|
|
1672
|
+
async handlePrompt(chatId, args) {
|
|
1673
|
+
if (args.length > 0) {
|
|
1674
|
+
await this.reply(chatId, "use /prompt to choose a saved prompt.");
|
|
1675
|
+
return;
|
|
1676
|
+
}
|
|
1677
|
+
const session = await this.requireActiveSession(chatId);
|
|
1678
|
+
if (!session)
|
|
1679
|
+
return;
|
|
1680
|
+
try {
|
|
1681
|
+
const snapshot = await this.getSessionManagerForChat(chatId).getSessionSnapshot(session.id);
|
|
1682
|
+
if (!snapshot) {
|
|
1683
|
+
await this.reply(chatId, "the session is still preparing.");
|
|
1684
|
+
return;
|
|
1685
|
+
}
|
|
1686
|
+
const prompts = snapshot.catalog.prompts;
|
|
1687
|
+
if (prompts.length === 0) {
|
|
1688
|
+
await this.reply(chatId, "this session has no saved prompts.");
|
|
1689
|
+
return;
|
|
1690
|
+
}
|
|
1691
|
+
this.promptPickers.set(chatId, { token: randomUUID(), sessionId: session.id, prompts });
|
|
1692
|
+
await this.showPromptPage(chatId, 0);
|
|
1693
|
+
}
|
|
1694
|
+
catch (error) {
|
|
1695
|
+
await this.reply(chatId, this.formatManagerError(error));
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
async showPromptPage(chatId, page, messageId) {
|
|
1699
|
+
const picker = this.promptPickers.get(chatId);
|
|
1700
|
+
if (!picker)
|
|
1701
|
+
return;
|
|
1702
|
+
const start = page * 20;
|
|
1703
|
+
const keyboard = picker.prompts.slice(start, start + 20).map((prompt, index) => [
|
|
1704
|
+
{
|
|
1705
|
+
text: prompt.label ?? prompt.id,
|
|
1706
|
+
callback_data: `prompt:${picker.token}:select:${start + index}`,
|
|
1707
|
+
},
|
|
1708
|
+
]);
|
|
1709
|
+
const navigation = [];
|
|
1710
|
+
if (page > 0)
|
|
1711
|
+
navigation.push({
|
|
1712
|
+
text: "previous",
|
|
1713
|
+
callback_data: `prompt:${picker.token}:page:${page - 1}`,
|
|
1714
|
+
});
|
|
1715
|
+
if (start + 20 < picker.prompts.length)
|
|
1716
|
+
navigation.push({ text: "next", callback_data: `prompt:${picker.token}:page:${page + 1}` });
|
|
1717
|
+
if (navigation.length > 0)
|
|
1718
|
+
keyboard.push(navigation);
|
|
1719
|
+
const text = "choose a saved prompt to add to the conversation without starting a turn. selection is available only while Tau is idle.";
|
|
1720
|
+
const replyMarkup = { inline_keyboard: keyboard };
|
|
1721
|
+
if (messageId !== undefined) {
|
|
1722
|
+
await this.sendWithRetry((signal) => this.api.editMessage(chatId, messageId, text, { replyMarkup, signal }));
|
|
1723
|
+
}
|
|
1724
|
+
else {
|
|
1725
|
+
await this.reply(chatId, text, { replyMarkup });
|
|
1726
|
+
}
|
|
1727
|
+
}
|
|
1728
|
+
async handlePromptCallback(chatId, data, messageId) {
|
|
1729
|
+
const match = /^prompt:([^:]+):(select|page):(0|[1-9][0-9]*)$/.exec(data);
|
|
1730
|
+
const picker = this.promptPickers.get(chatId);
|
|
1731
|
+
if (!match ||
|
|
1732
|
+
!picker ||
|
|
1733
|
+
picker.token !== match[1] ||
|
|
1734
|
+
this.getActiveSession(chatId)?.id !== picker.sessionId ||
|
|
1735
|
+
messageId === undefined) {
|
|
1736
|
+
await this.reply(chatId, "this prompt picker has expired. use /prompt to open a new one.");
|
|
1737
|
+
return;
|
|
1738
|
+
}
|
|
1739
|
+
const index = Number(match[3]);
|
|
1740
|
+
if (match[2] === "page") {
|
|
1741
|
+
if (index * 20 < picker.prompts.length)
|
|
1742
|
+
await this.showPromptPage(chatId, index, messageId);
|
|
1743
|
+
return;
|
|
1744
|
+
}
|
|
1745
|
+
const prompt = picker.prompts[index];
|
|
1746
|
+
if (!prompt)
|
|
1747
|
+
return;
|
|
1748
|
+
let text;
|
|
1749
|
+
try {
|
|
1750
|
+
text = await this.getSessionManagerForChat(chatId).recordPrompt(picker.sessionId, prompt.id);
|
|
1751
|
+
}
|
|
1752
|
+
catch (error) {
|
|
1753
|
+
await this.reply(chatId, this.formatManagerError(error));
|
|
1754
|
+
return;
|
|
1755
|
+
}
|
|
1756
|
+
this.promptPickers.delete(chatId);
|
|
1757
|
+
const chunks = splitTelegramMessage(`added this prompt to the conversation. send a message when you’re ready for Tau to respond.\n\n${text}`);
|
|
1758
|
+
for (const [index, chunk] of chunks.entries()) {
|
|
1759
|
+
if (index === 0) {
|
|
1760
|
+
await this.sendWithRetry((signal) => this.api.editMessage(chatId, messageId, chunk, { signal }));
|
|
1761
|
+
}
|
|
1762
|
+
else {
|
|
1763
|
+
await this.reply(chatId, chunk);
|
|
1764
|
+
}
|
|
1765
|
+
}
|
|
1766
|
+
}
|
|
1653
1767
|
async handleSetReasoning(chatId, reasoning, args) {
|
|
1654
1768
|
if (args.length > 0) {
|
|
1655
1769
|
await this.reply(chatId, `usage: /effort_${reasoning}`);
|