gut(auto-reply): remove dead thinking-level resolution plumbing (#2334)#2335
Merged
alexey-pelykh merged 1 commit intomainfrom Apr 13, 2026
Merged
gut(auto-reply): remove dead thinking-level resolution plumbing (#2334)#2335alexey-pelykh merged 1 commit intomainfrom
alexey-pelykh merged 1 commit intomainfrom
Conversation
Fix silent first-turn message crash on every channel: `modelState.resolveDefaultThinkingLevel is not a function`. The call site was left behind after prior gut sweeps stripped the method from `createModelSelectionState`, but the caller and surrounding XHigh gating machinery were never swept — and the tests never caught it because every fixture fabricated a `modelState` object with the method. Core deletions: - Delete `modelState`/`createModelSelectionState` threading across `get-reply*`, `directive-handling.*`, `commands-*`. Inline empty defaults in `get-reply-directives-apply.ts` where downstream directive handlers still expect `allowedModelKeys`, `allowedModelCatalog`, and `resetModelOverride`. - Delete the crashing thinking-level resolution block and XHigh gating from `runPreparedReply` — including the `sessionEntry.thinkingLevel` downgrade mutation and the body-token auto-detect that parsed low/medium/high/xhigh from message prefixes. - Delete `resolveDefaultThinkingLevel` from all five test fabrications so tests stop validating a method that doesn't exist in production. - Delete `src/auto-reply/reply/model-selection.ts` (stub-only file) and the orphan `createModelSelectionState` in `src/agents/model-selection.ts`. - Delete the `resolveStoredModelOverride` re-export from `plugin-sdk/mattermost.ts` and simplify the two dead consumers in `discord/monitor/native-command.ts` and `extensions/mattermost/src/mattermost/model-picker.ts` — they now unconditionally return the resolved default. Scope boundary for this PR — the full sweep catalogued in #2334 has more follow-up work deliberately deferred to keep this change reviewable: - `/think` directive parsing + TUI handler + gateway chat injection - `supportsXHighThinking`/`normalizeThinkLevel`/`formatXHighModelHint` in `src/auto-reply/thinking.ts` (still consumed by `src/commands/agent/session.ts` and cron test harness) - `sessionEntry.thinkingLevel` session state + gateway schema field - `thinkLevel` dead-passthrough through queue / followup runner / `agent-runner-utils` - Display-layer audit in `apps/android`, `apps/shared`, `ui/` - `/think` references in `docs/` Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
alexey-pelykh
added a commit
that referenced
this pull request
Apr 22, 2026
…as 1+2+4 of #2336 Partial execution of #2336's full sweep. Covers Areas 1 (`/think` directive removal), 2 (`thinking.ts` helper deletion), and 4 (`thinkLevel` passthrough plumbing) plus an adjacent cleanup of `onModelSelected` callback and its `ModelSelectedContext` type. Areas 3, 5, 6, 7, 8 remain for follow-ups (see the end of this commit message). **Rationale**: thinking level and model selection are CLI-runtime concerns per the Middleware Boundary Principle — CLI runtimes (Claude, Gemini, Codex, OpenCode) own those decisions. Anything in the fork that resolves, gates, or stores thinking level / selected model is vestigial from upstream OpenClaw and was already no-op'd after PR #2335. `AgentRuntime.execute` (src/middleware/types.ts) accepts none of these fields — confirmed. ## Area 1: `/think` directive end-to-end removal - `src/auto-reply/reply/directive-handling.parse.ts`: removed `hasThinkDirective` and `thinkLevel` fields from `InlineDirectives`. - `src/tui/tui-command-handlers.ts`: deleted the `/think` command handler; removed `formatThinkingLevels` import; removed `opts.thinking` passthrough from `sendChat`. - `src/gateway/server-methods/chat.ts`: deleted the `injectThinking`-based `/think ${p.thinking} ${parsedMessage}` body rewrite and the `p.thinking` param. - `src/auto-reply/reply.triggers.trigger-handling.targets-active-session-native-stop.e2e.test.ts`: deleted the `thinkCases` block that asserted `/think:high` stripping (behavior replaced by no-op since directive parser is gone). - `src/cli/tui-cli.ts`: removed `--thinking <level>` CLI option. - `src/tui/gateway-chat.ts`, `src/tui/tui-types.ts`: removed `thinking` option / `ChatSendOptions.thinking` field. ## Area 2: `thinking.ts` helper deletion - `src/auto-reply/thinking.ts`: deleted `normalizeThinkLevel`, `supportsXHighThinking`, `formatXHighModelHint`, `listThinkingLevelLabels`, `formatThinkingLevels`, `resolveThinkingDefaultForModel`, `isBinaryThinkingProvider`, `XHIGH_MODEL_*` constants, `CLAUDE_46_MODEL_RE`, `ThinkingCatalogEntry` and `ThinkLevel` types. Kept and simplified `listThinkingLevels` (returns the static level list). Kept `normalizeVerboseLevel`, `normalizeNoticeLevel`, `normalizeUsageDisplay`, `normalizeElevatedLevel`, `resolveElevatedMode`, `normalizeReasoningLevel`, `normalizeFastMode` — these are RemoteClaw's own directive-normalization helpers (not thinking-specific) and are load-bearing for display/security layers. - `src/commands/agent/session.ts`: removed `normalizeThinkLevel` import, `persistedThinking` field, and its `ThinkLevel`-typed call on `sessionEntry.thinkingLevel`. ## Area 4: `thinkLevel` dead passthrough + adjacent cleanup - `src/auto-reply/reply/queue/types.ts`: removed `thinkLevel?: unknown` from `FollowupRun.run`. - `src/auto-reply/reply/agent-runner-utils.ts`: dropped `thinkLevel` from `buildEmbeddedRunBaseParams`' returned object (function itself is dead Pi-embedded plumbing — tracked for follow-up). - `src/auto-reply/reply/agent-runner-execution.ts`: deleted the `onModelSelected({provider, model, thinkLevel: undefined})` callback call and the now-unused `const model = params.followupRun.run.model` declaration. - `src/auto-reply/reply/get-reply-run.ts`: removed `resolvedThinkLevel` field from `RunPreparedReplyParams` and the `thinkLevel: resolvedThinkLevel` assignment in the `followupRun.run` builder. - `src/auto-reply/reply/get-reply.ts`, `get-reply-inline-actions.ts`, `get-reply-directives.ts`, `commands-types.ts`: dropped `resolvedThinkLevel` fields + passthrough destructures. - `src/auto-reply/types.ts`: deleted the whole `ModelSelectedContext` type and `GetReplyOptions.onModelSelected` callback (these echoed configured-value `provider`/`model`/`thinkLevel` — not actual CLI-reported selection; meaningful only when the Pi-embedded runtime owned dynamic fallback, which was gutted in #76/#77). - `src/channels/reply-prefix.ts`: replaced the mutation-based `onModelSelected` callback with a static read from `resolveAgentEffectiveModelPrimary(cfg, agentId)` at context-creation time. Response-prefix template interpolation (`{model}`, `{provider}`, `{modelFull}`) still works with configured values. `ResponsePrefixContext.thinkingLevel` dropped. - Removed `{ onModelSelected, ...rest } = createReplyPrefixOptions(...)` destructures and `onModelSelected` property spreads across ~16 channel integrations: bluebubbles, feishu, googlechat, matrix, mattermost (monitor + slash-http), msteams, twitch, zalo, zalouser, discord (agent-components + message-handler + native-command), gateway/chat, imessage, line, plugin-sdk/inbound-reply-dispatch, signal, slack (monitor/dispatch + slash), telegram (bot-message + native-commands), tui (command-handlers + gateway-chat), web (auto-reply/process-message). Plus 3 test fixtures (`get-reply-run.media-only.test.ts` — 2 stale think-hint tests deleted; `get-reply-inline-actions.skip-when-config-empty.test.ts`, `get-reply.reset-hooks-fallback.test.ts`; `agent-runner-utils.test.ts` — stale `toMatchObject` keys; `test-helpers.ts`, `agent-runner.*.test.ts` fixtures; `slack/monitor/slash.test-harness.ts` mock return value). ## Areas deferred to follow-up issues - **Area 3** (`SessionEntry.thinkingLevel` field removal + gateway schema + session.ts `persistedThinking`): still live in the session store, surfaced by TUI / status / Telegram / ACP / gateway session APIs. Mechanical but touches wire-format / session migration. - **Area 5** (directive handling model-state internals — `aliasIndex`, `allowedModelKeys`, `resetModelOverride`, `defaultProvider` / `defaultModel`, `initialModelLabel`, `formatModelSwitchEvent`): 4 files, significant refactoring. - **Area 6** (docs): `/think` references in slash-commands.md, context.md, tui.md, group-messages.md. - **Area 7** (display-layer audit): Android, iOS, macOS, web UI display references to `thinkingLevel`. Per-file judgment required (pass-through display = KEEP, state driver = REMOVE). Issue #2336 explicitly flagged: "Do NOT touch native apps without confirming". - **Area 8** (test-layer hardening): delete the global `runPreparedReply` shield mock at `get-reply.test-mocks.ts:39-40`; add regression test exercising the real resolveReplyDirectives → runPreparedReply chain. ## Additional finding (filed as follow-up) The `buildEmbeddedRunBaseParams` / `buildEmbeddedContextFromTemplate` / `buildEmbeddedRunContexts` / `buildTemplateSenderContext` / `resolveRunAuthProfile` / `resolveEnforceFinalTag` / `resolveProviderScopedAuthProfile` / `resolveModelFallbackOptions` / `buildThreadingToolContext` cluster in `src/auto-reply/reply/agent-runner-utils.ts` has zero production callers — dead Pi-embedded plumbing that threads verboseLevel / reasoningLevel / elevatedLevel / bashElevated / execOverrides for nothing. Tracked as a separate follow-up. ## Verification - `pnpm check` (format + tsgo + oxlint + project-specific lints) → exit 0. - `pnpm test` (full parallel suite) → **800 files / 7010 passed / 3 skipped** — no regression. - Rescan: `git grep "/think\|hasThinkDirective\|thinkLevel\|supportsXHighThinking\|normalizeThinkLevel\|formatXHighModelHint"` in `src/` / `extensions/` returns only: `thinkingLevel` (stored in session, Area 3 deferred), display-layer native-app references (Area 7 deferred), and docs mentions (Area 6 deferred) — all scoped to follow-ups. Refs: #2336, #2334, #2335, #2089 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
3 tasks
alexey-pelykh
added a commit
that referenced
this pull request
Apr 22, 2026
…as 1+2+4 of #2336 (#2463) Partial execution of #2336's full sweep. Covers Areas 1 (`/think` directive removal), 2 (`thinking.ts` helper deletion), and 4 (`thinkLevel` passthrough plumbing) plus an adjacent cleanup of `onModelSelected` callback and its `ModelSelectedContext` type. Areas 3, 5, 6, 7, 8 remain for follow-ups (see the end of this commit message). **Rationale**: thinking level and model selection are CLI-runtime concerns per the Middleware Boundary Principle — CLI runtimes (Claude, Gemini, Codex, OpenCode) own those decisions. Anything in the fork that resolves, gates, or stores thinking level / selected model is vestigial from upstream OpenClaw and was already no-op'd after PR #2335. `AgentRuntime.execute` (src/middleware/types.ts) accepts none of these fields — confirmed. ## Area 1: `/think` directive end-to-end removal - `src/auto-reply/reply/directive-handling.parse.ts`: removed `hasThinkDirective` and `thinkLevel` fields from `InlineDirectives`. - `src/tui/tui-command-handlers.ts`: deleted the `/think` command handler; removed `formatThinkingLevels` import; removed `opts.thinking` passthrough from `sendChat`. - `src/gateway/server-methods/chat.ts`: deleted the `injectThinking`-based `/think ${p.thinking} ${parsedMessage}` body rewrite and the `p.thinking` param. - `src/auto-reply/reply.triggers.trigger-handling.targets-active-session-native-stop.e2e.test.ts`: deleted the `thinkCases` block that asserted `/think:high` stripping (behavior replaced by no-op since directive parser is gone). - `src/cli/tui-cli.ts`: removed `--thinking <level>` CLI option. - `src/tui/gateway-chat.ts`, `src/tui/tui-types.ts`: removed `thinking` option / `ChatSendOptions.thinking` field. ## Area 2: `thinking.ts` helper deletion - `src/auto-reply/thinking.ts`: deleted `normalizeThinkLevel`, `supportsXHighThinking`, `formatXHighModelHint`, `listThinkingLevelLabels`, `formatThinkingLevels`, `resolveThinkingDefaultForModel`, `isBinaryThinkingProvider`, `XHIGH_MODEL_*` constants, `CLAUDE_46_MODEL_RE`, `ThinkingCatalogEntry` and `ThinkLevel` types. Kept and simplified `listThinkingLevels` (returns the static level list). Kept `normalizeVerboseLevel`, `normalizeNoticeLevel`, `normalizeUsageDisplay`, `normalizeElevatedLevel`, `resolveElevatedMode`, `normalizeReasoningLevel`, `normalizeFastMode` — these are RemoteClaw's own directive-normalization helpers (not thinking-specific) and are load-bearing for display/security layers. - `src/commands/agent/session.ts`: removed `normalizeThinkLevel` import, `persistedThinking` field, and its `ThinkLevel`-typed call on `sessionEntry.thinkingLevel`. ## Area 4: `thinkLevel` dead passthrough + adjacent cleanup - `src/auto-reply/reply/queue/types.ts`: removed `thinkLevel?: unknown` from `FollowupRun.run`. - `src/auto-reply/reply/agent-runner-utils.ts`: dropped `thinkLevel` from `buildEmbeddedRunBaseParams`' returned object (function itself is dead Pi-embedded plumbing — tracked for follow-up). - `src/auto-reply/reply/agent-runner-execution.ts`: deleted the `onModelSelected({provider, model, thinkLevel: undefined})` callback call and the now-unused `const model = params.followupRun.run.model` declaration. - `src/auto-reply/reply/get-reply-run.ts`: removed `resolvedThinkLevel` field from `RunPreparedReplyParams` and the `thinkLevel: resolvedThinkLevel` assignment in the `followupRun.run` builder. - `src/auto-reply/reply/get-reply.ts`, `get-reply-inline-actions.ts`, `get-reply-directives.ts`, `commands-types.ts`: dropped `resolvedThinkLevel` fields + passthrough destructures. - `src/auto-reply/types.ts`: deleted the whole `ModelSelectedContext` type and `GetReplyOptions.onModelSelected` callback (these echoed configured-value `provider`/`model`/`thinkLevel` — not actual CLI-reported selection; meaningful only when the Pi-embedded runtime owned dynamic fallback, which was gutted in #76/#77). - `src/channels/reply-prefix.ts`: replaced the mutation-based `onModelSelected` callback with a static read from `resolveAgentEffectiveModelPrimary(cfg, agentId)` at context-creation time. Response-prefix template interpolation (`{model}`, `{provider}`, `{modelFull}`) still works with configured values. `ResponsePrefixContext.thinkingLevel` dropped. - Removed `{ onModelSelected, ...rest } = createReplyPrefixOptions(...)` destructures and `onModelSelected` property spreads across ~16 channel integrations: bluebubbles, feishu, googlechat, matrix, mattermost (monitor + slash-http), msteams, twitch, zalo, zalouser, discord (agent-components + message-handler + native-command), gateway/chat, imessage, line, plugin-sdk/inbound-reply-dispatch, signal, slack (monitor/dispatch + slash), telegram (bot-message + native-commands), tui (command-handlers + gateway-chat), web (auto-reply/process-message). Plus 3 test fixtures (`get-reply-run.media-only.test.ts` — 2 stale think-hint tests deleted; `get-reply-inline-actions.skip-when-config-empty.test.ts`, `get-reply.reset-hooks-fallback.test.ts`; `agent-runner-utils.test.ts` — stale `toMatchObject` keys; `test-helpers.ts`, `agent-runner.*.test.ts` fixtures; `slack/monitor/slash.test-harness.ts` mock return value). ## Areas deferred to follow-up issues - **Area 3** (`SessionEntry.thinkingLevel` field removal + gateway schema + session.ts `persistedThinking`): still live in the session store, surfaced by TUI / status / Telegram / ACP / gateway session APIs. Mechanical but touches wire-format / session migration. - **Area 5** (directive handling model-state internals — `aliasIndex`, `allowedModelKeys`, `resetModelOverride`, `defaultProvider` / `defaultModel`, `initialModelLabel`, `formatModelSwitchEvent`): 4 files, significant refactoring. - **Area 6** (docs): `/think` references in slash-commands.md, context.md, tui.md, group-messages.md. - **Area 7** (display-layer audit): Android, iOS, macOS, web UI display references to `thinkingLevel`. Per-file judgment required (pass-through display = KEEP, state driver = REMOVE). Issue #2336 explicitly flagged: "Do NOT touch native apps without confirming". - **Area 8** (test-layer hardening): delete the global `runPreparedReply` shield mock at `get-reply.test-mocks.ts:39-40`; add regression test exercising the real resolveReplyDirectives → runPreparedReply chain. ## Additional finding (filed as follow-up) The `buildEmbeddedRunBaseParams` / `buildEmbeddedContextFromTemplate` / `buildEmbeddedRunContexts` / `buildTemplateSenderContext` / `resolveRunAuthProfile` / `resolveEnforceFinalTag` / `resolveProviderScopedAuthProfile` / `resolveModelFallbackOptions` / `buildThreadingToolContext` cluster in `src/auto-reply/reply/agent-runner-utils.ts` has zero production callers — dead Pi-embedded plumbing that threads verboseLevel / reasoningLevel / elevatedLevel / bashElevated / execOverrides for nothing. Tracked as a separate follow-up. ## Verification - `pnpm check` (format + tsgo + oxlint + project-specific lints) → exit 0. - `pnpm test` (full parallel suite) → **800 files / 7010 passed / 3 skipped** — no regression. - Rescan: `git grep "/think\|hasThinkDirective\|thinkLevel\|supportsXHighThinking\|normalizeThinkLevel\|formatXHighModelHint"` in `src/` / `extensions/` returns only: `thinkingLevel` (stored in session, Area 3 deferred), display-layer native-app references (Area 7 deferred), and docs mentions (Area 6 deferred) — all scoped to follow-ups. Refs: #2336, #2334, #2335, #2089 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
7 tasks
alexey-pelykh
added a commit
that referenced
this pull request
Apr 22, 2026
…ea 5 of #2336 Follow-up to PR #2463 (Areas 1+2+4 of #2336). Completes the directive-handling portion of the sweep by removing model-state plumbing that was already empty/ trivial after #2335's `createModelSelectionState` removal. Per the Middleware Boundary Principle: RemoteClaw does NOT control model selection — CLI runtimes (Claude, Gemini, Codex, OpenCode) own those decisions. `handleDirectiveOnly` and `applyInlineDirectivesFastLane` carried 10 fields (`aliasIndex`, `allowedModelKeys`, `allowedModelCatalog`, `resetModelOverride`, `defaultProvider`, `defaultModel`, `initialModelLabel`, `formatModelSwitchEvent`, `provider`, `model`) that are now fully dead. ## Changes - `src/auto-reply/reply/directive-handling.params.ts`: delete all 10 model-state fields from `HandleDirectiveOnlyCoreParams`; delete unused `surface?: string` from `HandleDirectiveOnlyParams`. - `src/auto-reply/reply/directive-handling.impl.ts`: queue-validation `channel` semantic fix — switch from misused `params.provider` (AI provider, e.g. "anthropic") to `params.messageProviderKey ?? ""` (actual message channel, e.g. "telegram"). Aligns with `get-reply-run.ts:382` which already passes `sessionCtx.Provider` correctly. User-visible effect is limited to channel-specific queue config display when running `/queue` without args. - `src/auto-reply/reply/directive-handling.fast-lane.ts`: drop model-state destructures; drop dead `sessionEntry.providerOverride`/`modelOverride` reads; simplify return type `{directiveAck?; provider; model}` → `{directiveAck?}`. *Note*: `providerOverride`/`modelOverride` ARE written by `src/gateway/sessions-patch.ts:213-214` and `src/agents/tools/session-status-tool.ts:254-255`, but their downstream consumption via this fast-lane path reaches only `isReasoningTagProvider` at `get-reply-run.ts:453` (`enforceFinalTag` for google/google-gemini-cli/ minimax) — vestigial Pi-era plumbing per #2336's gut thesis. - `src/auto-reply/reply/get-reply-directives-apply.ts`: delete inline empty- default `directiveModelState` compat shim (introduced in #2335); delete `aliasIndex`/`initialModelLabel`/`formatModelSwitchEvent` threading; inline single-call `createDirectiveHandlingBase` factory; drop `provider`/`model` from `ApplyDirectiveResult.continue` variant (pure pass-through of inputs post-gut). - `src/auto-reply/reply/get-reply-directives.ts` (required cascade): delete dead `initialModelLabel`/`formatModelSwitchEvent` constructions and their two param passes (orphaned by the scope reduction in apply.ts); collapse `let provider`/`let model` to `const` (no longer reassigned). ## Deferred - `resolveDefaultModel` stub in `directive-handling.ts` still returns `allowedModelKeys`/`allowedModelCatalog`/`resetModelOverride` — never read by callers. Separate cleanup wave. - `aliasIndex` still threaded through `get-reply.ts` → `resolveReplyDirectives` (dead throughout). Separate cleanup wave. - Adjacent Areas 3 (`SessionEntry.thinkingLevel`), 6 (docs), 7 (display audit), 8 (test-layer hardening) of #2336 remain as separate follow-ups. ## Verification - `pnpm check`: exit 0 (format + tsgo + oxlint + project-specific lints) - `pnpm test`: 800 files / 7010 passed / 3 skipped — matches #2463 baseline - Grep across the 4 target files: zero hits for all 10 gutted symbols Refs: #2465, #2336, #2335, #2463 Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
4 tasks
alexey-pelykh
added a commit
that referenced
this pull request
Apr 22, 2026
…ea 5 of #2336 (#2475) Follow-up to PR #2463 (Areas 1+2+4 of #2336). Completes the directive-handling portion of the sweep by removing model-state plumbing that was already empty/ trivial after #2335's `createModelSelectionState` removal. Per the Middleware Boundary Principle: RemoteClaw does NOT control model selection — CLI runtimes (Claude, Gemini, Codex, OpenCode) own those decisions. `handleDirectiveOnly` and `applyInlineDirectivesFastLane` carried 10 fields (`aliasIndex`, `allowedModelKeys`, `allowedModelCatalog`, `resetModelOverride`, `defaultProvider`, `defaultModel`, `initialModelLabel`, `formatModelSwitchEvent`, `provider`, `model`) that are now fully dead. ## Changes - `src/auto-reply/reply/directive-handling.params.ts`: delete all 10 model-state fields from `HandleDirectiveOnlyCoreParams`; delete unused `surface?: string` from `HandleDirectiveOnlyParams`. - `src/auto-reply/reply/directive-handling.impl.ts`: queue-validation `channel` semantic fix — switch from misused `params.provider` (AI provider, e.g. "anthropic") to `params.messageProviderKey ?? ""` (actual message channel, e.g. "telegram"). Aligns with `get-reply-run.ts:382` which already passes `sessionCtx.Provider` correctly. User-visible effect is limited to channel-specific queue config display when running `/queue` without args. - `src/auto-reply/reply/directive-handling.fast-lane.ts`: drop model-state destructures; drop dead `sessionEntry.providerOverride`/`modelOverride` reads; simplify return type `{directiveAck?; provider; model}` → `{directiveAck?}`. *Note*: `providerOverride`/`modelOverride` ARE written by `src/gateway/sessions-patch.ts:213-214` and `src/agents/tools/session-status-tool.ts:254-255`, but their downstream consumption via this fast-lane path reaches only `isReasoningTagProvider` at `get-reply-run.ts:453` (`enforceFinalTag` for google/google-gemini-cli/ minimax) — vestigial Pi-era plumbing per #2336's gut thesis. - `src/auto-reply/reply/get-reply-directives-apply.ts`: delete inline empty- default `directiveModelState` compat shim (introduced in #2335); delete `aliasIndex`/`initialModelLabel`/`formatModelSwitchEvent` threading; inline single-call `createDirectiveHandlingBase` factory; drop `provider`/`model` from `ApplyDirectiveResult.continue` variant (pure pass-through of inputs post-gut). - `src/auto-reply/reply/get-reply-directives.ts` (required cascade): delete dead `initialModelLabel`/`formatModelSwitchEvent` constructions and their two param passes (orphaned by the scope reduction in apply.ts); collapse `let provider`/`let model` to `const` (no longer reassigned). ## Deferred - `resolveDefaultModel` stub in `directive-handling.ts` still returns `allowedModelKeys`/`allowedModelCatalog`/`resetModelOverride` — never read by callers. Separate cleanup wave. - `aliasIndex` still threaded through `get-reply.ts` → `resolveReplyDirectives` (dead throughout). Separate cleanup wave. - Adjacent Areas 3 (`SessionEntry.thinkingLevel`), 6 (docs), 7 (display audit), 8 (test-layer hardening) of #2336 remain as separate follow-ups. ## Verification - `pnpm check`: exit 0 (format + tsgo + oxlint + project-specific lints) - `pnpm test`: 800 files / 7010 passed / 3 skipped — matches #2463 baseline - Grep across the 4 target files: zero hits for all 10 gutted symbols Refs: #2465, #2336, #2335, #2463 Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fix silent first-turn message crash on every channel (
modelState.resolveDefaultThinkingLevel is not a function) by removing the dead call site and adjacent thinking-level / model-selection plumbing that prior gut sweeps had stubbed but never swept.Closes #2334 (scope-bounded — deferred items tracked below).
Root cause recap
createModelSelectionStatewas stripped ofresolveDefaultThinkingLevelin prior gut sweeps, butrunPreparedReplystill called it on themodelStateobject.src/auto-reply/reply/model-selection.tswas a stub returning({}) as any, andget-reply-run.tsimported the type from there (not from the real factory inget-reply-directives.ts).modelStatewith anasync () => …hook, so unit tests never exercised the production object shape. The only test that touchedrunPreparedReplyhardcodedresolvedThinkLevel: "high", so theif (!resolvedThinkLevel)branch that contained the crashing call was never entered.src/slack/monitor/message-handler.ts:172) but fires on every channel that routes throughrunPreparedReplyfor a first-turn message without a/thinkdirective.See #2334 for the full five-shield test-layer analysis.
What's changed
Core deletions
runPreparedReply(src/auto-reply/reply/get-reply-run.ts):modelState.resolveDefaultThinkingLevel()call (the bug).sessionEntry.thinkingLevel = "high"downgrade mutation.normalizeThinkLevel(parts[0])) that parsed low/medium/high/xhigh from message prefixes.modelStateparam +updateSessionStore+ unuseddirectivesdestructure + XHigh helper imports.modelStatethreading acrossget-reply.ts,get-reply-inline-actions.ts,get-reply-directives.ts,get-reply-directives-apply.ts,directive-handling.fast-lane.ts,directive-handling.params.ts: removed the parameter, fields, and factory wiring.get-reply-directives-apply.tsnow inlines emptyallowedModelKeys/allowedModelCatalog/resetModelOverridedefaults where downstream directive handlers still read them.resolveDefaultThinkingLevelremoved from type declarations incommands-types.ts,commands-status.ts,directive-handling.ts.src/auto-reply/reply/model-selection.tsentirely.createModelSelectionStatestub line fromsrc/agents/model-selection.ts.resolveStoredModelOverridere-export fromsrc/plugin-sdk/mattermost.ts.src/discord/monitor/native-command.ts—resolveDiscordModelPickerCurrentModelno longer loads the session store looking for a stored override; returns the resolved default.extensions/mattermost/src/mattermost/model-picker.ts—resolveMattermostModelPickerCurrentModelsame simplification.get-reply-run.media-only.test.ts(lines 137-139)get-reply.reset-hooks-fallback.test.ts(lines 90-92)get-reply-inline-actions.skip-when-config-empty.test.ts(line 77)commands.test.ts(line 301)commands.test-harness.ts(line 47)20 files changed, 9 insertions, 169 deletions.
Deferred to follow-up (scope limit for reviewability)
The #2334 issue catalogs a broader sweep. These items are deliberately NOT in this PR:
/thinkdirective parsing (directive-handling.parse.ts), TUI handler (tui-command-handlers.ts), and gateway chat injection (server-methods/chat.ts:976).supportsXHighThinking/normalizeThinkLevel/formatXHighModelHintinsrc/auto-reply/thinking.ts— still consumed bysrc/commands/agent/session.tsandsrc/cron/isolated-agent/run.test-harness.ts.sessionEntry.thinkingLevelsession state field + gateway schema.thinkLeveldead passthrough throughqueue/types.ts,followup-runner.ts,agent-runner-utils.ts,agent-runner-execution.ts.apps/android,apps/shared/RemoteClawKit,ui/src/ui./thinkreferences indocs/tools/slash-commands.md,docs/concepts/context.md,docs/web/tui.md,docs/channels/group-messages.md.I'll open a follow-up issue for these once this lands. The cut line was drawn where compile errors stopped cascading without touching the deeper directive-handling internals or the multi-platform display layers.
Test plan
pnpm tsgo— greenpnpm lint— 0 warnings, 0 errorspnpm format— cleanpnpm canvas:a2ui:bundle— greenpnpm test— 725 test files, 6341 tests pass, 2 skipped, 0 failuresLIVE=1 pnpm test:live— not run in this session (no LIVE credentials configured). CI or reviewer should run this since the PR touches reply-path runtime code. If LIVE setup is expected for this reviewer, happy to re-run in a follow-up.Follow-up commitments
runPreparedReplywithresolvedThinkLevel: undefinedthrough the realresolveReplyDirectiveschain (rather than fabricated fixtures) — needs coordinated cleanup ofget-reply.test-mocks.ts's globalrunPreparedReplymock, which is outside the scope of this PR.🤖 Generated with Claude Code