@markusylisiurunen/tau 0.3.96 → 0.3.98

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 (117) hide show
  1. package/dist/code_mode/runtime.js +1 -1
  2. package/dist/code_mode/runtime.js.map +1 -1
  3. package/dist/core/code_mode/agents.js +9 -1
  4. package/dist/core/code_mode/agents.js.map +1 -1
  5. package/dist/core/code_mode/models.js +69 -21
  6. package/dist/core/code_mode/models.js.map +1 -1
  7. package/dist/core/config/content_loader.js +27 -1
  8. package/dist/core/config/content_loader.js.map +1 -1
  9. package/dist/core/config/schema.js +9 -3
  10. package/dist/core/config/schema.js.map +1 -1
  11. package/dist/core/models/model_id.js +12 -0
  12. package/dist/core/models/model_id.js.map +1 -0
  13. package/dist/core/models/openrouter.js +63 -52
  14. package/dist/core/models/openrouter.js.map +1 -1
  15. package/dist/core/models/openrouter_budget.js +54 -0
  16. package/dist/core/models/openrouter_budget.js.map +1 -0
  17. package/dist/core/models/openrouter_media.js +20 -17
  18. package/dist/core/models/openrouter_media.js.map +1 -1
  19. package/dist/core/runtime/chat_runtime.js +25 -3
  20. package/dist/core/runtime/chat_runtime.js.map +1 -1
  21. package/dist/core/session/auto_compaction_threshold.js.map +1 -1
  22. package/dist/core/static/code_mode/sandbox_runner.mjs +1 -1
  23. package/dist/core/static/index.js +4 -6
  24. package/dist/core/static/index.js.map +1 -1
  25. package/dist/core/static/tau_docs/code-mode.md +2 -2
  26. package/dist/core/static/tau_docs/history.md +1 -1
  27. package/dist/core/static/tau_docs/node-sdk.md +1 -1
  28. package/dist/core/static/tau_docs/openrouter.md +11 -10
  29. package/dist/core/static/tau_docs/personas.md +15 -0
  30. package/dist/core/static/tau_docs/session-protocol-methods.md +3 -3
  31. package/dist/core/static/tau_docs/session-protocol.md +2 -2
  32. package/dist/core/static/tau_docs/sessions.md +10 -3
  33. package/dist/core/static/tau_docs/subagents.md +11 -1
  34. package/dist/core/static/tau_docs/telegram.md +35 -5
  35. package/dist/core/static/tau_docs/tui.md +2 -2
  36. package/dist/core/subagents/claude_code_runner.mjs +55 -50
  37. package/dist/core/subagents/launch_model.js +4 -7
  38. package/dist/core/subagents/launch_model.js.map +1 -1
  39. package/dist/core/subagents/native_subagent_runtime.js +1 -1
  40. package/dist/core/subagents/native_subagent_runtime.js.map +1 -1
  41. package/dist/core/subagents/registry.js.map +1 -1
  42. package/dist/core/telegram/adapter.js +46 -29
  43. package/dist/core/telegram/adapter.js.map +1 -1
  44. package/dist/core/telegram/config.js +9 -1
  45. package/dist/core/telegram/config.js.map +1 -1
  46. package/dist/core/telegram/local_session_client.js +4 -1
  47. package/dist/core/telegram/local_session_client.js.map +1 -1
  48. package/dist/core/telegram/runtime.js +8 -0
  49. package/dist/core/telegram/runtime.js.map +1 -1
  50. package/dist/core/telegram/session_manager.js.map +1 -1
  51. package/dist/core/tool/openrouter.js +1 -1
  52. package/dist/core/tool/openrouter.js.map +1 -1
  53. package/dist/core/tools/catalog.js +1 -0
  54. package/dist/core/tools/catalog.js.map +1 -1
  55. package/dist/core/tools/code_mode_worker.js +2 -2
  56. package/dist/core/tools/code_mode_worker.js.map +1 -1
  57. package/dist/core/utils/model_notices.js +0 -19
  58. package/dist/core/utils/model_notices.js.map +1 -1
  59. package/dist/core/version.js +1 -1
  60. package/dist/diff_tool/app/dist/assets/{apl-oXhhIufm.js → apl-B2CApK1w.js} +1 -1
  61. package/dist/diff_tool/app/dist/assets/{astro-BSfvy1I6.js → astro-BngVf-Vk.js} +1 -1
  62. package/dist/diff_tool/app/dist/assets/{blade-BPJIqBv7.js → blade-CJoxmvIk.js} +1 -1
  63. package/dist/diff_tool/app/dist/assets/{core-NkxL1yZC.js → core-D8lOlLN2.js} +1 -1
  64. package/dist/diff_tool/app/dist/assets/{crystal-BGOEqbwF.js → crystal-HDtM80sC.js} +1 -1
  65. package/dist/diff_tool/app/dist/assets/{edge-CQJH3_5t.js → edge-D4Nvwgsf.js} +1 -1
  66. package/dist/diff_tool/app/dist/assets/{erb-DZNowPeY.js → erb-CyjZ4knI.js} +1 -1
  67. package/dist/diff_tool/app/dist/assets/{glimmer-js-jxYiQSCJ.js → glimmer-js-D6M3MOmY.js} +1 -1
  68. package/dist/diff_tool/app/dist/assets/{glimmer-ts-DoFbDDKI.js → glimmer-ts-DfokzFjG.js} +1 -1
  69. package/dist/diff_tool/app/dist/assets/{graphql-CA_BX0d6.js → graphql-DTnqPoeZ.js} +1 -1
  70. package/dist/diff_tool/app/dist/assets/{handlebars-Bumg1nhL.js → handlebars-DZi9CvTQ.js} +1 -1
  71. package/dist/diff_tool/app/dist/assets/highlights-B80gocb2.js +3 -0
  72. package/dist/diff_tool/app/dist/assets/{http-Dt-6KBlS.js → http-ynmm9XFY.js} +1 -1
  73. package/dist/diff_tool/app/dist/assets/hurl-jiJ4Cyz5.js +1 -0
  74. package/dist/diff_tool/app/dist/assets/index-DSKn9aHV.js +205 -0
  75. package/dist/diff_tool/app/dist/assets/julia-BqNVScfB.js +1 -0
  76. package/dist/diff_tool/app/dist/assets/{just-CePkuXj4.js → just-D4SaWSq3.js} +1 -1
  77. package/dist/diff_tool/app/dist/assets/langs-Cb6u03GG.js +1 -0
  78. package/dist/diff_tool/app/dist/assets/{liquid-DBxKJhTy.js → liquid-DZ2yKB_9.js} +1 -1
  79. package/dist/diff_tool/app/dist/assets/marko-r9UJPNdX.js +1 -0
  80. package/dist/diff_tool/app/dist/assets/{mdc-AoEkrSRV.js → mdc-Bc7j-rRZ.js} +1 -1
  81. package/dist/diff_tool/app/dist/assets/{nim-CdOSsVN7.js → nim-Bzsd8mjy.js} +1 -1
  82. package/dist/diff_tool/app/dist/assets/{org-wLn5ov6u.js → org-D0z5J7r3.js} +1 -1
  83. package/dist/diff_tool/app/dist/assets/{perl-D1d-UYsx.js → perl-DSZpjAyA.js} +1 -1
  84. package/dist/diff_tool/app/dist/assets/{php-BXtg-e-b.js → php-BJRzLxXW.js} +1 -1
  85. package/dist/diff_tool/app/dist/assets/rst-CFIvEOFm.js +1 -0
  86. package/dist/diff_tool/app/dist/assets/{ruby-DAY5ZYSg.js → ruby-SpTrDNEO.js} +1 -1
  87. package/dist/diff_tool/app/dist/assets/shiki-DaptjTao.js +2 -0
  88. package/dist/diff_tool/app/dist/assets/{stream-tokenizer-h1lwRQEk.js → stream-tokenizer-BkuDYA48.js} +1 -1
  89. package/dist/diff_tool/app/dist/assets/{svelte-CouSRXXN.js → svelte-BjJxriRn.js} +1 -1
  90. package/dist/diff_tool/app/dist/assets/{templ-nHebsoOx.js → templ-B8KaQl_2.js} +1 -1
  91. package/dist/diff_tool/app/dist/assets/themes-BaMgiyFz.js +2 -0
  92. package/dist/diff_tool/app/dist/assets/{ts-tags-ByyA0QCx.js → ts-tags-BJYJ_DXd.js} +1 -1
  93. package/dist/diff_tool/app/dist/assets/{twig-DUDRwdST.js → twig-Bf7V1wC8.js} +1 -1
  94. package/dist/diff_tool/app/dist/assets/typst-DxctUuHF.js +1 -0
  95. package/dist/diff_tool/app/dist/assets/{vue-BMcQkxhM.js → vue-BeSZAYMy.js} +1 -1
  96. package/dist/diff_tool/app/dist/assets/{vue-vine-CEJFhGMr.js → vue-vine-D-Me5wQp.js} +1 -1
  97. package/dist/diff_tool/app/dist/index.html +1 -1
  98. package/dist/host/hosted_ephemeral_agent_session.js +1 -1
  99. package/dist/host/hosted_ephemeral_agent_session.js.map +1 -1
  100. package/dist/host/local_session_host.js +3 -2
  101. package/dist/host/local_session_host.js.map +1 -1
  102. package/dist/sdk/local_client.d.ts +2 -0
  103. package/dist/sdk/local_client.js +1 -0
  104. package/dist/sdk/local_client.js.map +1 -1
  105. package/dist/tui/session_chat_controller.js +4 -1
  106. package/dist/tui/session_chat_controller.js.map +1 -1
  107. package/package.json +6 -6
  108. package/dist/diff_tool/app/dist/assets/highlights-Coi8xHW0.js +0 -3
  109. package/dist/diff_tool/app/dist/assets/hurl-DUghBkZb.js +0 -1
  110. package/dist/diff_tool/app/dist/assets/index-Jt-l2Q96.js +0 -205
  111. package/dist/diff_tool/app/dist/assets/julia-CRQfdd-b.js +0 -1
  112. package/dist/diff_tool/app/dist/assets/langs-qJAo26KT.js +0 -1
  113. package/dist/diff_tool/app/dist/assets/marko-CjRgUMoV.js +0 -1
  114. package/dist/diff_tool/app/dist/assets/rst-D9EQsBp-.js +0 -1
  115. package/dist/diff_tool/app/dist/assets/shiki-B8l9Ufae.js +0 -2
  116. package/dist/diff_tool/app/dist/assets/themes-D3P9yN9_.js +0 -2
  117. package/dist/diff_tool/app/dist/assets/typst-DE5bnHEE.js +0 -1
@@ -151,7 +151,7 @@ try {
151
151
 
152
152
  Creating a session requires the full execution environment and the creation attributes, which never change afterward. The `cwd` must be absolute and is a path in the chosen environment, which may not be where the SDK runs. A Fly Sprite session refers to an existing Sprite that the host is configured to reach. See [sessions](sessions.md) for creation attributes and [ownership and scope](ownership-and-scope.md) for which machine owns which paths.
153
153
 
154
- To set the main conversation's automatic-compaction threshold at creation, pass `autoCompactThresholdTokens` as a safe integer of at least 50,000. Omit it or pass `null` to use the model's context window minus 16,384 tokens. The effective threshold cannot exceed this model-based default.
154
+ To set the main conversation's automatic-compaction threshold at creation, pass `autoCompactThresholdTokens` as a safe integer of at least 50,000. Omit it or pass `null` to use the persona default, falling back to the model's context window minus 16,384 tokens. Changing to a different persona resets the threshold to `null`. The effective threshold cannot exceed this model-based limit.
155
155
 
156
156
  Use `session.setAutoCompactThreshold(50000)` to change the threshold from the next logical turn, or `session.setAutoCompactThreshold(null)` to restore the default. Snapshot `settings` contain both `autoCompactThresholdTokens` (the configured value) and `effectiveAutoCompactThresholdTokens` (the trigger for the selected model). See [automatic compaction](sessions.md#automatic-compaction) for timing, limits, and costs.
157
157
 
@@ -87,7 +87,7 @@ Instructions and criterion guidance accept strings, JSON objects, or arrays; cho
87
87
 
88
88
  Luna Decisions supports at most 200 questions, 255 categories per choice question, and 2–10 rubric levels per score question. Tau checks these limits before sending the request. Jev also accepts a single-level score rubric. Both models use the same JSON input format.
89
89
 
90
- Luna also accepts up to 16 ordered local PNG/JPEG/WebP images using repeatable `--image <path>` flags:
90
+ Luna also accepts up to 64 ordered local PNG/JPEG/WebP images using repeatable `--image <path>` flags:
91
91
 
92
92
  ```sh
93
93
  tau tool openrouter decisions \
@@ -136,7 +136,7 @@ Flags belong after `chat`. No positional arguments are accepted.
136
136
  | `--system <text>` or `--system-file <path>` | Optional, mutually exclusive, nonblank explicit system instructions |
137
137
  | `--image <path>` | Repeatable local PNG, JPEG, or WebP image |
138
138
  | `--audio <path>` | Repeatable local WAV or MP3 audio; Gemini only |
139
- | `--video <path>` | Local MP4 video; Gemini only |
139
+ | `--video <path>` | Repeatable local MP4 video; Gemini only |
140
140
  | `--reasoning <effort>` | Optional model-supported effort from the table |
141
141
 
142
142
  All file paths resolve relative to the invoking working directory. Prompt/system files name regular files; `-` has special stdin meaning only for decisions. Omitting system instructions sends no system message. Omitting reasoning leaves that parameter to the provider, not necessarily disabled. Effort does not request a written reasoning trace.
@@ -164,19 +164,20 @@ These are successful exchanges with distinguishable outcomes; scripts must inspe
164
164
 
165
165
  ## Outputs and recovery
166
166
 
167
- These are cautious safety limits set by Tau, not the providers' maximum capacities. Byte limits use decimal units.
167
+ Tau sets these limits to reject abnormal input. They are not the providers' maximum capacities, and a request within them can still exceed the selected model's context window or a provider limit. 1 MiB is 1,048,576 bytes.
168
168
 
169
169
  | Resource | Limit |
170
170
  | --- | --- |
171
- | Decisions JSON, each prompt or system input | 1,000,000 UTF-8 bytes |
172
- | Attachments per request | 16 total, including at most 4 audio files and 1 video |
173
- | Each image | 5,000,000 bytes, 8,000 pixels per edge, 32 megapixels; one frame |
174
- | Each audio or video | 12,000,000 bytes |
171
+ | Decisions JSON | 20 MiB of UTF-8 |
172
+ | Chat prompt, system instructions, and schema | 20 MiB of UTF-8 combined |
173
+ | Attachments per request | 64 of any mix of types; 16 for Jev |
174
+ | Each image | 32 MiB, 32,768 pixels per edge, 100 megapixels; one frame |
175
+ | Each audio or video | 256 MiB |
175
176
  | Audio formats | Single-stream PCM 16-bit little-endian WAV or MP3 |
176
177
  | Video format | H.264 MP4 up to 3840×2160 with optional AAC audio |
177
- | Audio/video duration | Known positive duration; 600 seconds combined |
178
- | Complete encoded JSON request | 20,000,000 bytes, including base64 expansion and text |
179
- | Response | 8,000,000 bytes |
178
+ | Audio/video duration | Known positive duration; 7,200 seconds (2 hours) combined |
179
+ | Complete encoded JSON request | 512 MiB, including base64 expansion and text |
180
+ | Response | 32 MiB |
180
181
  | Local media probe | 15 seconds per file |
181
182
  | HTTP request and response | 10 minutes |
182
183
 
@@ -92,6 +92,20 @@ Each custom persona is complete on its own. It does not inherit a provider, mode
92
92
  | `serviceTier` | `priority` or `flex`. Used only by `openai` and `openai-codex`. |
93
93
  | `allowedReasoningLevels` | Array of reasoning efforts offered by the TUI selector. |
94
94
  | `tools` | List of persona-selectable tools. |
95
+ | `autoCompactThresholdTokens` | Default automatic-compaction threshold: a safe integer of at least 50,000 tokens. |
96
+ | `subagentAutoCompactThresholdTokens` | Map from `<provider>/<model>` IDs (without reasoning effort) to safe integer thresholds of at least 50,000 tokens for native Tau subagents launched with that model. |
97
+
98
+ For example, these optional frontmatter fields give the main conversation a 200,000-token default and explicit launches of one subagent model an 80,000-token default:
99
+
100
+ ```yaml
101
+ autoCompactThresholdTokens: 200000
102
+ subagentAutoCompactThresholdTokens:
103
+ openai/gpt-6.1-sol: 80000
104
+ ```
105
+
106
+ In `subagentAutoCompactThresholdTokens` keys, the provider is lowercased and the model ID is kept exactly as written, so `OpenAI/gpt-6.1-sol` and `openai/gpt-6.1-sol` name the same model. The provider must be known. A model ID missing from the catalog is allowed, as for `model`. Claude Code models are not allowed because Claude Code manages its own compaction.
107
+
108
+ Thresholds are capped at the selected model's context window minus 16,384 tokens. A session's `/auto-compact` override takes precedence over the persona default, and so do a Telegram bot's thresholds. See [sessions](sessions.md) and [subagents](subagents.md) for inheritance and reset behavior.
95
109
 
96
110
  Every persona can use all discovered skills. If a custom persona omits `tools`, Tau enables the standard tools and `agents`. A `tools` list without `agents` prevents the agent from starting or managing subagents. See [skills](skills.md) and [subagents](subagents.md) for those contracts.
97
111
 
@@ -158,6 +172,7 @@ An invalid persona is skipped and reported as a configuration warning. Other val
158
172
  - an `id` that does not exactly match the filename;
159
173
  - an unknown provider or an unresolved model;
160
174
  - an invalid reasoning effort or service tier;
175
+ - an automatic-compaction threshold below 50,000, or a `subagentAutoCompactThresholdTokens` key with an unknown provider or the `claude-code` provider;
161
176
  - an unknown persona tool.
162
177
 
163
178
  `/reload` shows warnings, with file paths, in the transcript. For a new local session, `tau --debug --persona <id>` shows the selected model, settings, skills, subagents, tools, and the complete prompt. If an edit seems to have no effect in a remote session, confirm the session's execution environment and `cwd` before editing another copy of the file. [Troubleshooting](troubleshooting.md) covers that check in more detail.
@@ -332,13 +332,13 @@ result: {
332
332
  }
333
333
  ```
334
334
 
335
- `thresholdTokens` must be a safe integer of at least 50,000, or `null` to restore the model-based default. Numeric strings are rejected. Session creation accepts the same values in the optional `autoCompactThresholdTokens` field, which defaults to `null`.
335
+ `thresholdTokens` must be a safe integer of at least 50,000, or `null` to remove the session override and use the default threshold. Numeric strings are rejected. Session creation accepts the same values in the optional `autoCompactThresholdTokens` field, which defaults to `null`.
336
336
 
337
- The default threshold is the model's context window minus 16,384 tokens. With an override, the effective threshold is the smaller of the configured value and that default. A model with a small context window can therefore have an effective threshold below 50,000.
337
+ The effective threshold uses the session override, then any host default (such as [Telegram bot thresholds](telegram.md#compaction-thresholds)), then the persona default, then the model's context window minus 16,384 tokens. It cannot exceed that model-based limit. A model with a small context window can therefore have an effective threshold below 50,000.
338
338
 
339
339
  The host saves the setting and publishes a `settings.set` delta to observers. Changing it does not start compaction. A running turn and its steering continuations keep their original threshold.
340
340
 
341
- Reloads, persona changes, and recovery preserve the configured value. The effective threshold is recalculated for the selected model. Subagents and ephemeral threads use their model-based defaults. See [automatic compaction](sessions.md#automatic-compaction) for request-size limits and costs.
341
+ Reloads, reasoning changes, recovery, and `session.setPersona` with the current persona ID preserve the configured value. `session.setPersona` with a different persona ID resets it to `null`. The effective threshold is recalculated for the selected persona and model. Native Tau subagents launched without a model override inherit the parent's launching-turn threshold. Native launches with an explicit model use the persona's subagent threshold for that model, or the model's default. Claude Code subagents manage their own compaction. Ephemeral threads use the persona default without the main session override. See [automatic compaction](sessions.md#automatic-compaction) for request-size limits and costs.
342
342
 
343
343
  ### `session.setReasoning`
344
344
 
@@ -110,8 +110,8 @@ Observing controls which updates you receive; it does not make you the owner. `s
110
110
 
111
111
  Both auto-compaction fields in `settings` are required:
112
112
 
113
- - `autoCompactThresholdTokens` is the configured value: a safe integer of at least 50,000, or `null` for the model-based default.
114
- - `effectiveAutoCompactThresholdTokens` is the integer threshold clients should display. It is the model's context window minus 16,384 tokens, or the configured value if that is smaller.
113
+ - `autoCompactThresholdTokens` is the configured value: a safe integer of at least 50,000, or `null` to use the default threshold.
114
+ - `effectiveAutoCompactThresholdTokens` is the integer threshold clients should display. It resolves the session override, then any host default for the persona or session (such as Telegram bot thresholds), then the persona default, then the model's context window minus 16,384 tokens. It is capped at that model-based limit.
115
115
 
116
116
  `bootstrap.model.contextWindow` is the full model window, regardless of the compaction threshold.
117
117
 
@@ -90,16 +90,23 @@ The summary aims both to let work continue right away and to keep earlier work r
90
90
 
91
91
  ### Automatic compaction
92
92
 
93
- Automatic compaction runs before a model call when the provider's latest token count, plus an estimate for content added since, exceeds the threshold. By default, the threshold is the model's context window minus a fixed reserve of 16,384 tokens. Writing the checkpoint uses the normal model settings, with no special output limit.
93
+ Automatic compaction runs before a model call when the provider's latest token count, plus an estimate for content added since, exceeds the threshold. The threshold comes from the first of these that is set:
94
+
95
+ 1. the session override;
96
+ 2. in Telegram sessions, the bot's `personaMenu` entry for the current persona, then the bot's `autoCompactThresholdTokens` (see [Telegram](telegram.md#compaction-thresholds));
97
+ 3. the persona's `autoCompactThresholdTokens`;
98
+ 4. the model's context window minus a fixed reserve of 16,384 tokens.
99
+
100
+ Every threshold is capped at that model-based limit. Writing the checkpoint uses the normal model settings, with no special output limit.
94
101
 
95
102
  To compact earlier, set a token threshold for the session. The effective threshold is the smaller of this setting and the model's context window minus 16,384 tokens.
96
103
 
97
104
  - In the TUI, use `/auto-compact 50000` or `/auto-compact 50k`.
98
105
  - In Telegram, use `/auto_compact 50000` or `/auto_compact 50k`.
99
- - With either command, use `default` to restore the model-based threshold, or omit the argument to show the configured and effective thresholds.
106
+ - With either command, use `default` to remove the session override and use the configured default again. Omit the argument to show the configured and effective thresholds.
100
107
  - SDK and protocol inputs accept a safe integer of at least 50,000, or `null` for the default. They do not accept strings such as `50k`.
101
108
 
102
- The minimum configured threshold is 50,000 tokens. The setting applies to the main conversation and survives recovery, reloads, and persona changes. Subagents and ephemeral threads use their model-based defaults.
109
+ The minimum configured threshold is 50,000 tokens. The setting applies to the main conversation. It survives recovery, reloads, reasoning changes, and switching to the persona already in use. Switching to a different persona removes it, so the new persona starts with its default threshold, and so does a later switch back. Native Tau subagents launched without a model override inherit the parent launching turn's effective threshold, including its session override. Native launches with an explicit model use the persona's model-keyed subagent threshold or that model's default (see [subagents](subagents.md)). Claude Code subagents manage their own compaction. Ephemeral threads use the persona default, without the main session override; forks retain their source thread's threshold.
103
110
 
104
111
  Changing the setting does not start compaction. The new threshold applies from the next logical turn. A running turn and its steering continuations keep their original threshold.
105
112
 
@@ -51,6 +51,16 @@ The configured list of launch models is an allowlist. It does not choose a defau
51
51
 
52
52
  A model ID may be missing from the catalog if its provider is known (see [models](models.md)). An entry with an invalid provider, model, effort, or format makes the configuration field invalid. Duplicate entries are removed.
53
53
 
54
+ ### Automatic compaction
55
+
56
+ These rules apply to native Tau subagents. [Claude Code subagents](#claude-code-subagents) manage their own compaction.
57
+
58
+ When `model` is omitted, a subagent inherits the effective threshold of the parent's launching turn, including any session `/auto-compact` override. A setting change during that turn affects only later turns and their launches.
59
+
60
+ When `model` is specified, the threshold comes from the persona's `subagentAutoCompactThresholdTokens` entry for that `<provider>/<model>`, without reasoning effort. The provider matches in any case, and the model ID must match exactly. If there is no entry, it uses the selected model's context window minus 16,384 tokens. This applies even when the explicit model matches the parent or only changes reasoning effort. The parent's threshold is not inherited in this case.
61
+
62
+ All thresholds are capped at the selected model's context window minus 16,384 tokens. Each child measures its own usage and keeps its launch threshold for follow-ups. These optional settings do not change the launch allowlist. See [personas](personas.md) for a configuration example.
63
+
54
64
  ### Allowing model overrides
55
65
 
56
66
  Configure the allowlist with `subagents.launchModels` in `config.json`:
@@ -150,7 +160,7 @@ The agent reads the complete reference, with types and examples, by printing `aw
150
160
 
151
161
  `spawn` takes a single-line title of at most 512 characters, a prompt of at most 262,144 characters, an optional model, and an optional working directory. The prompt is the subagent's first message, and the subagent does not see the parent conversation, so the prompt should be self-contained. The call returns right away with the subagent's state, and the subagent keeps working in the background.
152
162
 
153
- When the main persona has `history`, a native Tau subagent may read the parent session's transcript as a last resort, when missing context would stop the work or force an important assumption. It reads with `tau.history.read` and `source: "local"`, so the read uses the host's local history even when a remote collection is configured. Local recording is best-effort, so the newest parent entries can occasionally be missing.
163
+ When the main persona has `history`, a native Tau subagent follows the same history rules as the main agent, and an assignment that asks about past conversations counts as an explicit request. The subagent also has one extra permission: as a last resort, it may read the parent session's transcript when missing context would stop the work or force an important assumption. Every read of the parent session uses `tau.history.read` with `source: "local"`, so it reads the host's local history even when a remote collection is configured. Other reads use the configured collection unless the subagent is told to read locally. Local recording is best-effort, so the newest parent entries can occasionally be missing.
154
164
 
155
165
  At most eight subagents can be working at once in one main session. Idle subagents do not count toward this limit.
156
166
 
@@ -69,6 +69,7 @@ Each `bots.<id>` object supports:
69
69
  | --- | --- | --- |
70
70
  | `botToken` | Yes | Telegram Bot API token. |
71
71
  | `allowedProjectIds` | No | Non-empty unique subset of configured project IDs; omission exposes all projects. |
72
+ | `autoCompactThresholdTokens` | No | Default automatic-compaction threshold for this bot's sessions. See [compaction thresholds](#compaction-thresholds). |
72
73
  | `personaMenu` | No | Ordered list of personas offered by `/persona`; omission offers every persona. See [persona menu](#persona-menu). |
73
74
  | `allowedUserIds` | No | Integer user IDs allowed to trigger turns, commands, and callbacks. |
74
75
  | `allowedChatIds` | No | Integer chat IDs allowed to interact with the bot; also opts groups in. |
@@ -105,6 +106,14 @@ A project's `persona` replaces the default for its sessions. Composite sessions
105
106
 
106
107
  Every Telegram turn starts with a hidden `<system>` block saying the message comes from Telegram and the reply goes there. It asks for direct answers to simple questions, and for short acknowledgements or useful progress updates during longer work, because users cannot see tool activity.
107
108
 
109
+ Each message also carries its sender, as reported by Telegram. A DM turn gets a hidden block with the sender. In a group, the trigger message and each context message are labeled with their sender. Each queued attachment keeps the sender of the message that carried it. The sender is a JSON object with the numeric Telegram user ID and, when available, the display name and the username without the `@`, or `null` when Telegram does not identify one:
110
+
111
+ ```json
112
+ { "user-id": 123456789, "name": "Ada Lovelace", "username": "ada" }
113
+ ```
114
+
115
+ The agent is told that names and usernames are chosen by the sender and do not prove identity or grant permission. Only `allowedChatIds` and `allowedUserIds` control who can use the bot.
116
+
108
117
  A per-bot `systemMessage` goes in a second hidden block. Audio transcripts get another block warning that they may contain noise or errors. Hidden blocks are saved with the user's message and can appear in history, so never put credentials in configured messages.
109
118
 
110
119
  The runner loads its speech credentials and `speech.voiceId` at startup, from its environment and from the Tau config for its startup directory. Restart the runner after changing them.
@@ -122,13 +131,13 @@ The runner loads its speech credentials and `speech.voiceId` at startup, from it
122
131
  | `/effort_high` | Selects high reasoning for future turns. |
123
132
  | `/effort_xhigh` | Selects xhigh reasoning for future turns. |
124
133
  | `/prompt` | [Records a saved prompt](prompts-and-project-context.md#telegram-prompt-picker) while idle, without starting a turn. |
125
- | `/auto_compact [tokens\|default]` | Shows the automatic-compaction threshold. Pass `50k` or `50000` to set it (minimum 50,000 tokens), or `default` to restore the model-based threshold. |
134
+ | `/auto_compact [tokens\|default]` | Shows the automatic-compaction threshold. Pass `50k` or `50000` to set it (minimum 50,000 tokens), or `default` to remove the session override and use the default. |
126
135
  | `/compact` | Runs summary-only compaction while idle. |
127
136
  | `/interrupt` | Interrupts the active Tau turn. |
128
137
  | `/tts_on` | Sends a voice note after each final assistant response. |
129
138
  | `/tts_off` | Disables voice responses. |
130
139
 
131
- Changes to the auto-compaction threshold apply from the next turn and survive session recovery. `/status` shows context usage as a percentage of the full model window. When an override is set, it also shows the effective threshold in parentheses. See [automatic compaction](sessions.md#automatic-compaction) for limits and costs.
140
+ Changes to the auto-compaction threshold apply from the next turn and survive session recovery. Switching to a different persona removes the override. `/status` shows context usage as a percentage of the full model window. When a session override is set, or the default threshold is below the model-based threshold, it also shows the effective threshold in parentheses. See [compaction thresholds](#compaction-thresholds) for bot defaults and [automatic compaction](sessions.md#automatic-compaction) for limits and costs.
132
141
 
133
142
  A [persona](personas.md) choice applies to the current session only; `/new` uses the project's default.
134
143
 
@@ -151,15 +160,36 @@ By default, `/persona` offers every persona in the session. A bot's `personaMenu
151
160
  ```json
152
161
  "personaMenu": [
153
162
  { "id": "gpt-6.1-sol-coder", "label": "sol" },
154
- { "id": "sonnet-5.5-coder" }
163
+ { "id": "sonnet-5.5-coder", "autoCompactThresholdTokens": 150000 }
155
164
  ]
156
165
  ```
157
166
 
158
- Each entry has a required `id`, the exact persona ID, and an optional `label`. Both must be non-empty after surrounding whitespace is trimmed, IDs must be unique, and no other fields are allowed. Without a label, the picker shows the persona's own label, or its ID if it has none. The label appears in the picker and in the switch confirmation. It changes nothing else, so the persona keeps its ID, prompt, model, tools, and reasoning settings, and the TUI still shows its normal name.
167
+ Each entry has a required `id`, the exact persona ID, an optional `label`, and an optional `autoCompactThresholdTokens` (see [compaction thresholds](#compaction-thresholds)). The ID and label must be non-empty after surrounding whitespace is trimmed, IDs must be unique, and no other fields are allowed. Without a label, the picker shows the persona's own label, or its ID if it has none. The label appears in the picker and in the switch confirmation. It changes nothing else, so the persona keeps its ID, prompt, model, tools, and reasoning settings, and the TUI still shows its normal name.
159
168
 
160
169
  The menu is matched against each session's personas when `/persona` runs, because different projects can define different personas. Listed personas that the session lacks are named in the picker message, and the rest of the menu still works. An empty list, `[]`, offers no personas.
161
170
 
162
- The menu only changes what the picker offers. It does not restrict which personas a session may use, and it does not change defaults. A project's `persona` still applies to new sessions even if the menu omits it. When the session's current persona is not in the menu, the picker message names it, but it is not added as a choice.
171
+ Apart from compaction thresholds, the menu only changes what the picker offers. It does not restrict which personas a session may use, and it does not change default personas. A project's `persona` still applies to new sessions even if the menu omits it. When the session's current persona is not in the menu, the picker message names it, but it is not added as a choice.
172
+
173
+ ### Compaction thresholds
174
+
175
+ A bot can set default [automatic-compaction](sessions.md#automatic-compaction) thresholds for its sessions. Both fields take a safe integer of at least 50,000 tokens:
176
+
177
+ ```json
178
+ "engineering": {
179
+ "botToken": "<telegram-bot-token>",
180
+ "autoCompactThresholdTokens": 200000,
181
+ "personaMenu": [
182
+ { "id": "gpt-6.1-sol-coder", "autoCompactThresholdTokens": 120000 },
183
+ { "id": "sonnet-5.5-coder" }
184
+ ]
185
+ }
186
+ ```
187
+
188
+ A session uses the first threshold that is set: its `/auto_compact` override, the `personaMenu` entry whose `id` exactly matches the current persona, the bot's `autoCompactThresholdTokens`, the persona's own `autoCompactThresholdTokens`, and finally the model's context window minus 16,384 tokens. Every threshold is capped at that model-based limit. In this example, a session using `gpt-6.1-sol-coder` compacts at 120,000 tokens, and a session using any other persona compacts at 200,000 tokens. A menu entry's threshold applies whenever the session uses that persona, including through the project's default `persona`.
189
+
190
+ These defaults are not saved with the session. The runner reads them at startup, so restart the runner after changing them. Recovered sessions then use the new defaults, and keep any `/auto_compact` override they had.
191
+
192
+ Native subagents launched without a model use the session's effective threshold, as described in [subagents](subagents.md#automatic-compaction). Ephemeral threads use the persona's own default and ignore the bot's thresholds.
163
193
 
164
194
  ## DMs, groups, and active work
165
195
 
@@ -90,7 +90,7 @@ Then use Shift+Tab to choose a reasoning level. A newly added persona appears on
90
90
  | `/exit` | Close this TUI. On a long-running remote host, this detaches; the session is not deleted. |
91
91
  | `/rewind` | Pick an earlier user message, remove it and everything after it, and put its text back in the editor. |
92
92
  | `/diff [git diff args...]` | Open the local diff review tool on a snapshot taken from the execution environment. |
93
- | `/auto-compact [tokens\|default]` | Show the automatic-compaction threshold. Pass `50k` or `50000` to set it (minimum 50,000 tokens), or `default` to restore the model-based threshold. |
93
+ | `/auto-compact [tokens\|default]` | Show the automatic-compaction threshold. Pass `50k` or `50000` to set it (minimum 50,000 tokens), or `default` to remove the session override and use the default. |
94
94
  | `/compact-all [guidance]` | Replace the model's context with a generated summary. |
95
95
  | `/compact-keep-last [guidance]` | Same, and include the last assistant response in the summary when there is one. |
96
96
  | `/reload` | Reload session configuration and content from the execution environment. |
@@ -106,7 +106,7 @@ Then use Shift+Tab to choose a reasoning level. A newly added persona appears on
106
106
 
107
107
  Run commands that change the context, such as persona changes, compaction, rewind, and reload, while idle. `/auto-compact` can inspect or change the next-turn threshold during a running turn. `/auto-speak`, `/listen`, `/prompt:<id>`, and `/exit` do little during a running turn. Other commands wait until Tau is idle.
108
108
 
109
- The footer shows context usage as a percentage of the full model window, such as `20%/272k`. When an override is set, the effective compaction threshold appears in parentheses: `20%/272k (50k)`. This threshold cannot exceed the model's context window minus 16,384 tokens. With the default setting, the footer shows no threshold.
109
+ The footer shows context usage as a percentage of the full model window, such as `20%/272k`. When a session override is set, or the default threshold is below the model-based threshold, the effective compaction threshold appears in parentheses: `20%/272k (50k)`. This threshold cannot exceed the model's context window minus 16,384 tokens. Without an override or a lower default, the footer shows no threshold. Switching to a different persona removes the session override.
110
110
 
111
111
  While subagents are running, a panel above the editor shows the selected subagent's title, recent activity, and a usage line such as `openai-codex/gpt-6-astra:medium · ↑12k ↓2k (r8k w0) · 14%/200k · $0.04`. The line starts with the subagent's provider, model, and reasoning effort, including settings inherited from the persona. Text that does not fit the terminal width is cut off on the right.
112
112