Skip to content

gut(auto-reply): remove dead thinking-level resolution plumbing (#2334)#2335

Merged
alexey-pelykh merged 1 commit intomainfrom
gut/2334-thinking-model-sweep
Apr 13, 2026
Merged

gut(auto-reply): remove dead thinking-level resolution plumbing (#2334)#2335
alexey-pelykh merged 1 commit intomainfrom
gut/2334-thinking-model-sweep

Conversation

@alexey-pelykh
Copy link
Copy Markdown

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

  • createModelSelectionState was stripped of resolveDefaultThinkingLevel in prior gut sweeps, but runPreparedReply still called it on the modelState object.
  • TypeScript was blind because src/auto-reply/reply/model-selection.ts was a stub returning ({}) as any, and get-reply-run.ts imported the type from there (not from the real factory in get-reply-directives.ts).
  • Every test file fabricated modelState with an async () => … hook, so unit tests never exercised the production object shape. The only test that touched runPreparedReply hardcoded resolvedThinkLevel: "high", so the if (!resolvedThinkLevel) branch that contained the crashing call was never entered.
  • The error surfaces loudly in Slack's inbound debounce flush onError (src/slack/monitor/message-handler.ts:172) but fires on every channel that routes through runPreparedReply for a first-turn message without a /think directive.

See #2334 for the full five-shield test-layer analysis.

What's changed

Core deletions

  • runPreparedReply (src/auto-reply/reply/get-reply-run.ts):
    • Delete the modelState.resolveDefaultThinkingLevel() call (the bug).
    • Delete the XHigh gating block and the sessionEntry.thinkingLevel = "high" downgrade mutation.
    • Delete the body-token auto-detect (normalizeThinkLevel(parts[0])) that parsed low/medium/high/xhigh from message prefixes.
    • Delete modelState param + updateSessionStore + unused directives destructure + XHigh helper imports.
  • modelState threading across get-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.ts now inlines empty allowedModelKeys / allowedModelCatalog / resetModelOverride defaults where downstream directive handlers still read them.
  • resolveDefaultThinkingLevel removed from type declarations in commands-types.ts, commands-status.ts, directive-handling.ts.
  • Stub files:
    • Delete src/auto-reply/reply/model-selection.ts entirely.
    • Delete orphan createModelSelectionState stub line from src/agents/model-selection.ts.
    • Delete resolveStoredModelOverride re-export from src/plugin-sdk/mattermost.ts.
  • Dead consumers:
    • src/discord/monitor/native-command.tsresolveDiscordModelPickerCurrentModel no longer loads the session store looking for a stored override; returns the resolved default.
    • extensions/mattermost/src/mattermost/model-picker.tsresolveMattermostModelPickerCurrentModel same simplification.
  • Test fabrications deleted:
    • 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:

  • /think directive parsing (directive-handling.parse.ts), TUI handler (tui-command-handlers.ts), and gateway chat injection (server-methods/chat.ts:976).
  • supportsXHighThinking / normalizeThinkLevel / formatXHighModelHint in src/auto-reply/thinking.ts — still consumed by src/commands/agent/session.ts and src/cron/isolated-agent/run.test-harness.ts.
  • sessionEntry.thinkingLevel session state field + gateway schema.
  • thinkLevel dead passthrough through queue/types.ts, followup-runner.ts, agent-runner-utils.ts, agent-runner-execution.ts.
  • Display-layer audit in apps/android, apps/shared/RemoteClawKit, ui/src/ui.
  • /think references in docs/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 — green
  • pnpm lint — 0 warnings, 0 errors
  • pnpm format — clean
  • pnpm canvas:a2ui:bundle — green
  • pnpm test — 725 test files, 6341 tests pass, 2 skipped, 0 failures
  • LIVE=1 pnpm test:livenot 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.
  • Manual Slack first-turn message smoke test — recommend a reviewer validate on a dev account since the bug was specifically a first-turn/no-think case that no existing test covered.

Follow-up commitments

  • Open follow-up issue for the deferred sweep listed above.
  • Add a regression test that drives runPreparedReply with resolvedThinkLevel: undefined through the real resolveReplyDirectives chain (rather than fabricated fixtures) — needs coordinated cleanup of get-reply.test-mocks.ts's global runPreparedReply mock, which is outside the scope of this PR.

🤖 Generated with Claude Code

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 alexey-pelykh enabled auto-merge (squash) April 13, 2026 06:56
@alexey-pelykh alexey-pelykh merged commit 44b4f92 into main Apr 13, 2026
10 checks passed
@alexey-pelykh alexey-pelykh deleted the gut/2334-thinking-model-sweep branch April 13, 2026 07:03
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>
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>
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>
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

gut(auto-reply): remove dead thinking-level and model-selection plumbing — TypeError on first-turn messages

1 participant