Skip to content

Commit 2b75806

Browse files
committed
feat: forward-port fast talks auto mode (#85104)
1 parent adb9abe commit 2b75806

171 files changed

Lines changed: 4171 additions & 474 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/workflows/workflow-sanity.yml

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -129,11 +129,28 @@ jobs:
129129
trusted_config="$RUNNER_TEMP/pre-commit-base.yaml"
130130
trusted_zizmor_config="$RUNNER_TEMP/zizmor-base.yml"
131131
132-
if ! git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null; then
133-
timeout --signal=TERM --kill-after=10s 30s git fetch --no-tags --depth=1 origin \
134-
"+${BASE_SHA}:refs/remotes/origin/security-base" ||
132+
fetch_base_ref() {
133+
local ref="$1"
134+
local target="$2"
135+
local fetch_status
136+
for attempt in 1 2 3; do
135137
timeout --signal=TERM --kill-after=10s 30s git fetch --no-tags --depth=1 origin \
136-
"+refs/heads/${BASE_REF}:refs/remotes/origin/${BASE_REF}"
138+
"+${ref}:${target}" && return 0
139+
fetch_status="$?"
140+
if [ "$fetch_status" != "124" ] && [ "$fetch_status" != "137" ]; then
141+
return "$fetch_status"
142+
fi
143+
if [ "$attempt" = "3" ]; then
144+
return "$fetch_status"
145+
fi
146+
echo "::warning::trusted base fetch for '$ref' timed out on attempt $attempt; retrying"
147+
sleep 5
148+
done
149+
}
150+
151+
if ! git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null; then
152+
fetch_base_ref "$BASE_SHA" "refs/remotes/origin/security-base" ||
153+
fetch_base_ref "refs/heads/${BASE_REF}" "refs/remotes/origin/${BASE_REF}"
137154
fi
138155
139156
if git cat-file -e "${BASE_SHA}:.pre-commit-config.yaml" 2>/dev/null; then

apps/shared/OpenClawKit/Sources/OpenClawProtocol/GatewayModels.swift

Lines changed: 49 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7277,7 +7277,9 @@ public struct ChatSendParams: Codable, Sendable {
72777277
public let sessionid: String?
72787278
public let message: String
72797279
public let thinking: String?
7280-
public let fastmode: Bool?
7280+
public let fastmodevalue: AnyCodable?
7281+
public var fastmode: Bool? { fastmodevalue?.value as? Bool }
7282+
public let fastautoonseconds: Int?
72817283
public let deliver: Bool?
72827284
public let originatingchannel: String?
72837285
public let originatingto: String?
@@ -7296,7 +7298,8 @@ public struct ChatSendParams: Codable, Sendable {
72967298
sessionid: String?,
72977299
message: String,
72987300
thinking: String?,
7299-
fastmode: Bool?,
7301+
fastmodevalue: AnyCodable?,
7302+
fastautoonseconds: Int?,
73007303
deliver: Bool?,
73017304
originatingchannel: String?,
73027305
originatingto: String?,
@@ -7314,7 +7317,8 @@ public struct ChatSendParams: Codable, Sendable {
73147317
self.sessionid = sessionid
73157318
self.message = message
73167319
self.thinking = thinking
7317-
self.fastmode = fastmode
7320+
self.fastmodevalue = fastmodevalue
7321+
self.fastautoonseconds = fastautoonseconds
73187322
self.deliver = deliver
73197323
self.originatingchannel = originatingchannel
73207324
self.originatingto = originatingto
@@ -7328,13 +7332,54 @@ public struct ChatSendParams: Codable, Sendable {
73287332
self.idempotencykey = idempotencykey
73297333
}
73307334

7335+
public init(
7336+
sessionkey: String,
7337+
agentid: String? = nil,
7338+
sessionid: String?,
7339+
message: String,
7340+
thinking: String?,
7341+
fastmode: Bool?,
7342+
deliver: Bool?,
7343+
originatingchannel: String?,
7344+
originatingto: String?,
7345+
originatingaccountid: String?,
7346+
originatingthreadid: String?,
7347+
attachments: [AnyCodable]?,
7348+
timeoutms: Int?,
7349+
systeminputprovenance: [String: AnyCodable]?,
7350+
systemprovenancereceipt: String?,
7351+
suppresscommandinterpretation: Bool?,
7352+
idempotencykey: String)
7353+
{
7354+
self.init(
7355+
sessionkey: sessionkey,
7356+
agentid: agentid,
7357+
sessionid: sessionid,
7358+
message: message,
7359+
thinking: thinking,
7360+
fastmodevalue: fastmode.map { AnyCodable($0) },
7361+
fastautoonseconds: nil,
7362+
deliver: deliver,
7363+
originatingchannel: originatingchannel,
7364+
originatingto: originatingto,
7365+
originatingaccountid: originatingaccountid,
7366+
originatingthreadid: originatingthreadid,
7367+
attachments: attachments,
7368+
timeoutms: timeoutms,
7369+
systeminputprovenance: systeminputprovenance,
7370+
systemprovenancereceipt: systemprovenancereceipt,
7371+
suppresscommandinterpretation: suppresscommandinterpretation,
7372+
idempotencykey: idempotencykey)
7373+
}
7374+
73317375
private enum CodingKeys: String, CodingKey {
73327376
case sessionkey = "sessionKey"
73337377
case agentid = "agentId"
73347378
case sessionid = "sessionId"
73357379
case message
73367380
case thinking
7337-
case fastmode = "fastMode"
7381+
case fastmodevalue = "fastMode"
7382+
case fastautoonseconds = "fastAutoOnSeconds"
73387383
case deliver
73397384
case originatingchannel = "originatingChannel"
73407385
case originatingto = "originatingTo"

docs/automation/cron-jobs.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,7 @@ Model-selection precedence for isolated jobs is:
183183
3. User-selected stored cron session model override
184184
4. Agent/default model selection
185185

186-
Fast mode follows the resolved live selection too. If the selected model config has `params.fastMode`, isolated cron uses that by default. A stored session `fastMode` override still wins over config in either direction.
186+
Fast mode follows the resolved live selection too. If the selected model config has `params.fastMode`, isolated cron uses that by default. A stored session `fastMode` override still wins over config in either direction. Auto mode uses the selected model's `params.fastAutoOnSeconds` cutoff when present, defaulting to 60 seconds.
187187

188188
If an isolated run hits a live model-switch handoff, cron retries with the switched provider/model and persists that live selection for the active run before retrying. When the switch also carries a new auth profile, cron persists that auth profile override for the active run too. Retries are bounded: after the initial attempt plus 2 switch retries, cron aborts instead of looping forever.
189189

docs/cli/cron.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ Isolated cron resolves the active model in this order:
197197

198198
### Fast mode
199199

200-
Isolated cron fast mode follows the resolved live model selection. Model config `params.fastMode` applies by default, but a stored session `fastMode` override still wins over config.
200+
Isolated cron fast mode follows the resolved live model selection. Model config `params.fastMode` applies by default, but a stored session `fastMode` override still wins over config. When the resolved mode is `auto`, the cutoff uses the selected model's `params.fastAutoOnSeconds` value, defaulting to 60 seconds.
201201

202202
### Live model switch retries
203203

docs/gateway/config-agents.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1099,7 +1099,7 @@ for provider examples and precedence.
10991099
- `skills`: optional per-agent skill allowlist. If omitted, the agent inherits `agents.defaults.skills` when set; an explicit list replaces defaults instead of merging, and `[]` means no skills.
11001100
- `thinkingDefault`: optional per-agent default thinking level (`off | minimal | low | medium | high | xhigh | adaptive | max`). Overrides `agents.defaults.thinkingDefault` for this agent when no per-message or session override is set. The selected provider/model profile controls which values are valid; for Google Gemini, `adaptive` keeps provider-owned dynamic thinking (`thinkingLevel` omitted on Gemini 3/3.1, `thinkingBudget: -1` on Gemini 2.5).
11011101
- `reasoningDefault`: optional per-agent default reasoning visibility (`on | off | stream`). Overrides `agents.defaults.reasoningDefault` for this agent when no per-message or session reasoning override is set.
1102-
- `fastModeDefault`: optional per-agent default for fast mode (`true | false`). Applies when no per-message or session fast-mode override is set.
1102+
- `fastModeDefault`: optional per-agent default for fast mode (`"auto" | true | false`). Applies when no per-message or session fast-mode override is set.
11031103
- `models`: optional per-agent model catalog/runtime overrides keyed by full `provider/model` ids. Use `models["provider/model"].agentRuntime` for per-agent runtime exceptions.
11041104
- `runtime`: optional per-agent runtime descriptor. Use `type: "acp"` with `runtime.acp` defaults (`agent`, `backend`, `mode`, `cwd`) when the agent should default to ACP harness sessions.
11051105
- `identity.avatar`: workspace-relative path, `http(s)` URL, or `data:` URI.

docs/gateway/protocol.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ enumeration of `src/gateway/server-methods/*.ts`.
445445
- `sessions.get` returns the full stored session row.
446446
- Chat execution still uses `chat.history`, `chat.send`, `chat.abort`, and `chat.inject`. `chat.history` is display-normalized for UI clients: inline directive tags are stripped from visible text, plain-text tool-call XML payloads (including `<tool_call>...</tool_call>`, `<function_call>...</function_call>`, `<tool_calls>...</tool_calls>`, `<function_calls>...</function_calls>`, and truncated tool-call blocks) and leaked ASCII/full-width model control tokens are stripped, pure silent-token assistant rows such as exact `NO_REPLY` / `no_reply` are omitted, and oversized rows can be replaced with placeholders.
447447
- `chat.message.get` is the additive bounded full-message reader for a single visible transcript entry. Clients pass `sessionKey`, optional `agentId` when the session selection is agent-scoped, plus a transcript `messageId` previously surfaced through `chat.history`, and the Gateway returns the same display-normalized projection without the lightweight history truncation cap when the stored entry is still available and not oversized.
448+
- `chat.send` accepts one-turn `fastMode: "auto"` to use fast mode for model calls started before the auto cutoff, then start later retry, fallback, tool-result, or continuation calls without fast mode. The cutoff defaults to 60 seconds and can be configured per model with `agents.defaults.models["<provider>/<model>"].params.fastAutoOnSeconds`. A `chat.send` caller can pass one-turn `fastAutoOnSeconds` to override the cutoff for that request.
448449

449450
</Accordion>
450451

docs/help/faq-models.md

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,7 @@ troubleshooting, see the main [FAQ](/help/faq).
174174

175175
- **Per session:** send `/fast on` while the session is using `openai/gpt-5.5`.
176176
- **Per model default:** set `agents.defaults.models["openai/gpt-5.5"].params.fastMode` to `true`.
177+
- **Automatic cutoff:** use `/fast auto` or `params.fastMode: "auto"` to start new model calls fast until the auto cutoff, then start later retry, fallback, tool-result, or continuation calls without fast mode. The cutoff defaults to 60 seconds; set `params.fastAutoOnSeconds` on the active model to change it.
177178

178179
Example:
179180

@@ -184,7 +185,8 @@ troubleshooting, see the main [FAQ](/help/faq).
184185
models: {
185186
"openai/gpt-5.5": {
186187
params: {
187-
fastMode: true,
188+
fastMode: "auto",
189+
fastAutoOnSeconds: 30,
188190
},
189191
},
190192
},
@@ -193,7 +195,7 @@ troubleshooting, see the main [FAQ](/help/faq).
193195
}
194196
```
195197

196-
For OpenAI, fast mode maps to `service_tier = "priority"` on supported native Responses requests. Session `/fast` overrides beat config defaults.
198+
For OpenAI, fast mode maps to `service_tier = "priority"` on supported native Responses requests. Session `/fast` overrides beat config defaults. Codex app-server turns can only receive the tier at turn start, so `auto` applies on the next OpenClaw-started model turn rather than inside one already-running app-server turn.
197199

198200
See [Thinking and fast mode](/tools/thinking) and [OpenAI fast mode](/providers/openai#fast-mode).
199201

docs/providers/openai.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -915,17 +915,17 @@ the Server-side compaction accordion below.
915915
<Accordion title="Fast mode">
916916
OpenClaw exposes a shared fast-mode toggle for `openai/*`:
917917

918-
- **Chat/UI:** `/fast status|on|off`
918+
- **Chat/UI:** `/fast status|auto|on|off`
919919
- **Config:** `agents.defaults.models["<provider>/<model>"].params.fastMode`
920920

921-
When enabled, OpenClaw maps fast mode to OpenAI priority processing (`service_tier = "priority"`). Existing `service_tier` values are preserved, and fast mode does not rewrite `reasoning` or `text.verbosity`.
921+
When enabled, OpenClaw maps fast mode to OpenAI priority processing (`service_tier = "priority"`). Existing `service_tier` values are preserved, and fast mode does not rewrite `reasoning` or `text.verbosity`. `fastMode: "auto"` starts new model calls fast until the auto cutoff, then starts later retry, fallback, tool-result, or continuation calls without fast mode. The cutoff defaults to 60 seconds; set `params.fastAutoOnSeconds` on the active model to change it.
922922

923923
```json5
924924
{
925925
agents: {
926926
defaults: {
927927
models: {
928-
"openai/gpt-5.5": { params: { fastMode: true } },
928+
"openai/gpt-5.5": { params: { fastMode: "auto", fastAutoOnSeconds: 30 } },
929929
},
930930
},
931931
},

docs/tools/slash-commands.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -198,7 +198,7 @@ plugins.
198198
| `/think <level\|default>` | Set the thinking level or clear the session override. Aliases: `/thinking`, `/t` |
199199
| `/verbose on\|off\|full` | Toggle verbose output. Alias: `/v` |
200200
| `/trace on\|off` | Toggle plugin trace output for the current session |
201-
| `/fast [status\|on\|off\|default]` | Show, set, or clear fast mode |
201+
| `/fast [status\|auto\|on\|off\|default]` | Show, set, or clear fast mode |
202202
| `/reasoning [on\|off\|stream]` | Toggle reasoning visibility. Alias: `/reason` |
203203
| `/elevated [on\|off\|ask\|full]` | Toggle elevated mode. Alias: `/elev` |
204204
| `/exec host=<auto\|sandbox\|gateway\|node> security=<deny\|allowlist\|full> ask=<off\|on-miss\|always> node=<id>` | Show or set exec defaults |
@@ -211,7 +211,7 @@ plugins.
211211
<Accordion title="verbose / trace / fast / reasoning safety">
212212
- `/verbose` is for debugging — keep it **off** in normal use.
213213
- `/trace` reveals only plugin-owned trace/debug lines; normal verbose chatter stays off.
214-
- `/fast on|off` persists a session override; use the Sessions UI `inherit` option to clear it.
214+
- `/fast auto|on|off` persists a session override; use the Sessions UI `inherit` option to clear it.
215215
- `/fast` is provider-specific: OpenAI/Codex map it to `service_tier=priority`; direct Anthropic requests map it to `service_tier=auto` or `standard_only`.
216216
- `/reasoning`, `/verbose`, and `/trace` are risky in group settings — they may reveal internal reasoning or plugin diagnostics. Keep them off in group chats.
217217

docs/tools/thinking.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -60,21 +60,22 @@ title: "Thinking levels"
6060

6161
## Fast mode (/fast)
6262

63-
- Levels: `on|off|default`.
64-
- Directive-only message toggles a session fast-mode override and replies `Fast mode enabled.` / `Fast mode disabled.`. Use `/fast default` to clear the session override and inherit the configured default; aliases include `inherit`, `clear`, `reset`, and `unpin`.
63+
- Levels: `auto|on|off|default`.
64+
- Directive-only message toggles a session fast-mode override and replies `Fast mode set to auto.`, `Fast mode enabled.`, or `Fast mode disabled.`. Use `/fast default` to clear the session override and inherit the configured default; aliases include `inherit`, `clear`, `reset`, and `unpin`.
6565
- Send `/fast` (or `/fast status`) with no mode to see the current effective fast-mode state.
6666
- OpenClaw resolves fast mode in this order:
67-
1. Inline/directive-only `/fast on|off` override (`/fast default` clears this layer)
67+
1. Inline/directive-only `/fast auto|on|off` override (`/fast default` clears this layer)
6868
2. Session override
6969
3. Per-agent default (`agents.list[].fastModeDefault`)
7070
4. Per-model config: `agents.defaults.models["<provider>/<model>"].params.fastMode`
7171
5. Fallback: `off`
72+
- `auto` keeps the session/config mode as auto but resolves each new model call independently. Calls that start before the auto cutoff have fast mode enabled; later retry, fallback, tool-result, or continuation calls start with fast mode disabled. The cutoff defaults to 60 seconds; set `agents.defaults.models["<provider>/<model>"].params.fastAutoOnSeconds` on the active model to change it.
7273
- For `openai/*`, fast mode maps to OpenAI priority processing by sending `service_tier=priority` on supported Responses requests.
73-
- For Codex-backed `openai/*` models, fast mode sends the same `service_tier=priority` flag on Codex Responses. OpenClaw keeps one shared `/fast` toggle across both auth paths.
74+
- For Codex-backed `openai/*` / `openai-codex/*` models, fast mode sends the same `service_tier=priority` flag on Codex Responses. Native Codex app-server turns receive the tier only on `turn/start` or thread start/resume, so `auto` cannot retier one already-running app-server turn; it applies to the next model turn OpenClaw starts.
7475
- For direct public `anthropic/*` requests, including OAuth-authenticated traffic sent to `api.anthropic.com`, fast mode maps to Anthropic service tiers: `/fast on` sets `service_tier=auto`, `/fast off` sets `service_tier=standard_only`.
7576
- For `minimax/*` on the Anthropic-compatible path, `/fast on` (or `params.fastMode: true`) rewrites `MiniMax-M2.7` to `MiniMax-M2.7-highspeed`.
7677
- Explicit Anthropic `serviceTier` / `service_tier` model params override the fast-mode default when both are set. OpenClaw still skips Anthropic service-tier injection for non-Anthropic proxy base URLs.
77-
- `/status` shows `Fast` only when fast mode is enabled.
78+
- `/status` shows `Fast` when fast mode is enabled and `Fast:auto` when the configured mode is auto.
7879

7980
## Verbose directives (/verbose or /v)
8081

0 commit comments

Comments
 (0)