Summary
The model catalog system (OpenClaw's model registry for API providers), model selection logic, vision capability checks, and thinking mode defaults were gutted but stubs remain. RemoteClaw doesn't manage models — CLI runtimes handle their own model selection.
Stub Files (3 entire files are stubs)
src/agents/model-catalog.ts (entire file — 9 lines, all stubs)
Exports 5 stub functions and 1 stub type:
ModelCatalogEntry type (line 3)
resolveModelCatalog (line 4)
resolveModelCatalogEntry (line 5)
findModelInCatalog (lines 6-7) — imported by bot-message-dispatch.ts:4
loadModelCatalog (line 8) — imported by bot-message-dispatch.ts:5; mocked in ~10 test files
modelSupportsVision (line 9) — imported by bot-message-dispatch.ts:6
Live importers: src/telegram/bot-message-dispatch.ts:7 (3 imports), src/gateway/server-methods/types.ts:2 (commented-out import).
src/agents/model-selection.ts (entire file — 64 lines, 20+ exports, all stubs)
Types:
ModelSelectionResult (lines 3-8)
ThinkLevel (line 15) — also defined in auto-reply/thinking.ts:1 (duplicate)
ModelRef (line 16) — also defined in agents/provider-utils.ts:11 (duplicate)
ModelRefStatus (line 17)
ModelAliasIndex (line 18)
AllowedModelSetResult (lines 44-48)
Functions:
resolveModelSelection (line 10)
resolveModelSelectionForCron (line 11)
resolveDefaultModelForAgent (lines 12-13) — imported by bot-message-dispatch.ts:8
modelKey (lines 20-22) — local re-stub in onboard-custom.ts:14
isCliProvider (lines 24-26)
normalizeModelRef (lines 28-30) — DUPLICATE of live function in provider-utils.ts:157
parseModelRef (lines 32-34) — DUPLICATE of live function in provider-utils.ts:166; imported by gateway-cli-backend.live.test.ts:6
normalizeProviderId (lines 36-38) — DUPLICATE of live function in provider-utils.ts
resolveConfiguredModelRef (lines 40-42) — imported by status.summary.ts:2; local re-stubs in status.ts:19, commands-registry.ts:8
buildAllowedModelSet (lines 50-52)
getModelRefStatus (lines 54-56)
resolveThinkingDefault (lines 58-60) — imported by server-methods/chat.ts:4
resolveHooksGmailModel (lines 62-64)
Live importers:
src/telegram/bot-message-dispatch.ts:8 — resolveDefaultModelForAgent
src/commands/status.summary.ts:2 — resolveConfiguredModelRef
src/gateway/server-methods/chat.ts:4 — resolveThinkingDefault
src/gateway/gateway-cli-backend.live.test.ts:6 — parseModelRef (should import from provider-utils.ts instead)
src/discord/monitor/native-command.ts:36 — resolveStoredModelOverride (from auto-reply/reply/model-selection.ts, not this file)
src/auto-reply/reply/model-selection.ts (entire file — 3 lines, 1 stub)
resolveStoredModelOverride (line 3) — imported by discord/monitor/native-command.ts:36, called at line 433
Stubs in src/gateway/server.impl.ts
loadGatewayModelCatalog (line 114) — called at lines 796, referenced in server-methods/nodes.ts:827, server-methods/chat.ts:618
maybeSeedControlUiAllowedOriginsAtStartup (lines 138-141) — dead no-op
__resetModelCatalogCacheForTest (line 144) — exported via server.ts:3, called in test-helpers.server.ts:162
Local Re-Stubs (inline stubs replacing deleted imports)
src/auto-reply/reply/get-reply.ts (lines 6-39, ~7 local stubs)
resolveModelRefFromString (lines 7-8) — called at lines 71, 189
DEFAULT_AGENT_WORKSPACE_DIR (line 12)
applyLinkUnderstanding (line 16) — dead no-op
applyMediaUnderstanding (line 17) — dead no-op
resolveDefaultModel (lines 25-29) — called in body
emitPreAgentMessageHooks (line 35) — dead no-op
applyResetModelOverride (line 36) — called at line 155
stageSandboxMedia (line 39) — dead no-op
src/auto-reply/status.ts (lines 17-27, 4 stubs)
buildModelAliasIndex (line 17) — called at line 567
resolveConfiguredModelRef (line 19) — called at line 407
resolveModelRefFromString (line 21) — called at line 571
resolveSandboxRuntimeStatus (lines 25-27) — called in body (sandbox-related, not model)
src/auto-reply/commands-registry.ts (lines 4-8, 3 stubs)
DEFAULT_MODEL (line 4) — used in body
DEFAULT_PROVIDER (line 5) — used in body
resolveConfiguredModelRef (line 8) — called at line 268
src/commands/onboard-custom.ts (lines 8-36, 5 stubs)
DEFAULT_PROVIDER (line 8)
buildModelAliasIndex (line 12) — called at line 224
modelKey (line 14) — called in body
ensureApiKeyFromEnvOrPrompt (line 28) — called in body
applyPrimaryModel (line 32) — called in body
normalizeAlias (line 36) — called in body
src/auto-reply/reply/get-reply-directives.ts (lines 24-36, 2 stubs)
createModelSelectionState (lines 24-34) — called at line 383, type referenced in get-reply-directives-apply.ts:15
resolveContextTokens (line 36) — called in body
src/agents/subagent-spawn.ts:19 — resolveSubagentSpawnModelSelection
Stub, called at line 394.
src/agents/tools/sessions-helpers.ts:32 — sanitizeUserFacingText
Local re-stub (returns text unchanged). The REAL implementation exists at src/agents/agent-helpers/errors.ts:537 (50+ lines). This local stub shadows the real function. The import should be rewired to the real implementation.
Stubs with Live Callers (require caller fixes, not simple deletion)
src/gateway/device-auth.ts:4-5 — normalizeDeviceMetadataForAuth
Stub (returns undefined), but called by buildDeviceAuthPayloadV3 (real function, line 42-43) and imported by message-handler.ts:38 (called at lines 220-223). Removal requires fixing the callers — either inline the normalization or remove the calls.
src/gateway/server-http.ts:50-53 — 3 canvas/plugin auth stubs
authorizeCanvasRequest (lines 50-51) — returns true no-op; called at lines 531, 644
enforcePluginRouteGatewayAuth (line 52) — returns true no-op; called at line 199
isCanvasPath (line 53) — returns false no-op; called at line 528
These stubs have live callers that safely consume the no-op returns. The callers will need to be simplified when the stubs are removed (e.g., remove the if (!isCanvasPath(...)) guard).
Test Files Requiring Mock Cleanup
Test files that mock model-catalog.js:
src/agents/remoteclaw-tools.session-status.test.ts:41
src/commands/agent.test.ts:19
src/auto-reply/reply/commands.test.ts:64
src/auto-reply/reply/session.test.ts:18
src/auto-reply/reply.block-streaming.test.ts:40
src/auto-reply/reply.directive.directive-behavior.e2e-mocks.ts:14
src/auto-reply/reply.triggers.trigger-handling.test-harness.ts:99-125
src/auto-reply/reply.directive.directive-behavior.e2e-harness.ts:122
src/cron/isolated-agent/run.test-harness.ts:69
src/cron/isolated-agent/run.channel-bridge.test.ts:80
src/cron/isolated-agent/run.auth-retry.test.ts:59
src/cron/isolated-agent.mocks.ts:3
Test files that mock model-selection.js:
src/auto-reply/reply/get-reply.reset-hooks-fallback.test.ts:18
src/cron/isolated-agent/run.test-harness.ts:73-82
src/cron/isolated-agent/run.channel-bridge.test.ts:84
src/cron/isolated-agent/run.auth-retry.test.ts:63
NOT in Scope (alive functions incorrectly listed in prior version)
The following are NOT stubs — they are real, working implementations:
sanitizeUserFacingText in agents/agent-helpers/errors.ts:537 — 50+ line real implementation
buildOauthProviderAuthResult in plugin-sdk/provider-auth-result.ts:17 — 67-line real implementation, re-exported from plugin-sdk/index.ts:166
validateVoiceCredentials in channels/voice-credentials.ts:55 — real function with tests in voice-credentials.test.ts
runConfigUnset in cli/config-cli.ts:310 — real function, imported by routes.ts:121
runModelDirectiveText in reply.directive.directive-behavior.model-directive-test-utils.ts:8 — real test utility
Duplicate Type/Function Exports to Consolidate
model-selection.ts re-exports stub versions of types/functions that have live implementations in provider-utils.ts:
ModelRef type — live in provider-utils.ts:11
normalizeModelRef — live in provider-utils.ts:157
parseModelRef — live in provider-utils.ts:166
normalizeProviderId — live in provider-utils.ts
ThinkLevel type — live in auto-reply/thinking.ts:1, duplicated as stub in model-selection.ts:15
Importers of these from model-selection.ts should be redirected to the canonical source.
Acceptance Criteria
src/agents/model-catalog.ts deleted
src/agents/model-selection.ts deleted
src/auto-reply/reply/model-selection.ts deleted
- All local re-stubs removed, callers simplified or rewired
- Importers of duplicate types/functions redirected to
provider-utils.ts or thinking.ts
normalizeDeviceMetadataForAuth callers fixed (not just stub deleted)
server-http.ts canvas/plugin auth stub callers simplified
- No
modelCatalog, ModelCatalog, modelAliasIndex, ModelAlias, modelSupportsVision, findModelInCatalog, resolveDefaultModelForAgent, loadModelCatalog, resolveModelCatalog, resolveModelCatalogEntry, resolveModelSelection, resolveModelSelectionForCron, loadGatewayModelCatalog, __resetModelCatalogCacheForTest, resolveStoredModelOverride, resolveSubagentSpawnModelSelection references in source (grep exit criterion — excluding live provider-utils.ts and thinking.ts exports)
- All test mocks for
model-catalog.js and model-selection.js cleaned up
pnpm check passes
Summary
The model catalog system (OpenClaw's model registry for API providers), model selection logic, vision capability checks, and thinking mode defaults were gutted but stubs remain. RemoteClaw doesn't manage models — CLI runtimes handle their own model selection.
Stub Files (3 entire files are stubs)
src/agents/model-catalog.ts(entire file — 9 lines, all stubs)Exports 5 stub functions and 1 stub type:
ModelCatalogEntrytype (line 3)resolveModelCatalog(line 4)resolveModelCatalogEntry(line 5)findModelInCatalog(lines 6-7) — imported bybot-message-dispatch.ts:4loadModelCatalog(line 8) — imported bybot-message-dispatch.ts:5; mocked in ~10 test filesmodelSupportsVision(line 9) — imported bybot-message-dispatch.ts:6Live importers:
src/telegram/bot-message-dispatch.ts:7(3 imports),src/gateway/server-methods/types.ts:2(commented-out import).src/agents/model-selection.ts(entire file — 64 lines, 20+ exports, all stubs)Types:
ModelSelectionResult(lines 3-8)ThinkLevel(line 15) — also defined inauto-reply/thinking.ts:1(duplicate)ModelRef(line 16) — also defined inagents/provider-utils.ts:11(duplicate)ModelRefStatus(line 17)ModelAliasIndex(line 18)AllowedModelSetResult(lines 44-48)Functions:
resolveModelSelection(line 10)resolveModelSelectionForCron(line 11)resolveDefaultModelForAgent(lines 12-13) — imported bybot-message-dispatch.ts:8modelKey(lines 20-22) — local re-stub inonboard-custom.ts:14isCliProvider(lines 24-26)normalizeModelRef(lines 28-30) — DUPLICATE of live function inprovider-utils.ts:157parseModelRef(lines 32-34) — DUPLICATE of live function inprovider-utils.ts:166; imported bygateway-cli-backend.live.test.ts:6normalizeProviderId(lines 36-38) — DUPLICATE of live function inprovider-utils.tsresolveConfiguredModelRef(lines 40-42) — imported bystatus.summary.ts:2; local re-stubs instatus.ts:19,commands-registry.ts:8buildAllowedModelSet(lines 50-52)getModelRefStatus(lines 54-56)resolveThinkingDefault(lines 58-60) — imported byserver-methods/chat.ts:4resolveHooksGmailModel(lines 62-64)Live importers:
src/telegram/bot-message-dispatch.ts:8—resolveDefaultModelForAgentsrc/commands/status.summary.ts:2—resolveConfiguredModelRefsrc/gateway/server-methods/chat.ts:4—resolveThinkingDefaultsrc/gateway/gateway-cli-backend.live.test.ts:6—parseModelRef(should import fromprovider-utils.tsinstead)src/discord/monitor/native-command.ts:36—resolveStoredModelOverride(fromauto-reply/reply/model-selection.ts, not this file)src/auto-reply/reply/model-selection.ts(entire file — 3 lines, 1 stub)resolveStoredModelOverride(line 3) — imported bydiscord/monitor/native-command.ts:36, called at line 433Stubs in
src/gateway/server.impl.tsloadGatewayModelCatalog(line 114) — called at lines 796, referenced inserver-methods/nodes.ts:827,server-methods/chat.ts:618maybeSeedControlUiAllowedOriginsAtStartup(lines 138-141) — dead no-op__resetModelCatalogCacheForTest(line 144) — exported viaserver.ts:3, called intest-helpers.server.ts:162Local Re-Stubs (inline stubs replacing deleted imports)
src/auto-reply/reply/get-reply.ts(lines 6-39, ~7 local stubs)resolveModelRefFromString(lines 7-8) — called at lines 71, 189DEFAULT_AGENT_WORKSPACE_DIR(line 12)applyLinkUnderstanding(line 16) — dead no-opapplyMediaUnderstanding(line 17) — dead no-opresolveDefaultModel(lines 25-29) — called in bodyemitPreAgentMessageHooks(line 35) — dead no-opapplyResetModelOverride(line 36) — called at line 155stageSandboxMedia(line 39) — dead no-opsrc/auto-reply/status.ts(lines 17-27, 4 stubs)buildModelAliasIndex(line 17) — called at line 567resolveConfiguredModelRef(line 19) — called at line 407resolveModelRefFromString(line 21) — called at line 571resolveSandboxRuntimeStatus(lines 25-27) — called in body (sandbox-related, not model)src/auto-reply/commands-registry.ts(lines 4-8, 3 stubs)DEFAULT_MODEL(line 4) — used in bodyDEFAULT_PROVIDER(line 5) — used in bodyresolveConfiguredModelRef(line 8) — called at line 268src/commands/onboard-custom.ts(lines 8-36, 5 stubs)DEFAULT_PROVIDER(line 8)buildModelAliasIndex(line 12) — called at line 224modelKey(line 14) — called in bodyensureApiKeyFromEnvOrPrompt(line 28) — called in bodyapplyPrimaryModel(line 32) — called in bodynormalizeAlias(line 36) — called in bodysrc/auto-reply/reply/get-reply-directives.ts(lines 24-36, 2 stubs)createModelSelectionState(lines 24-34) — called at line 383, type referenced inget-reply-directives-apply.ts:15resolveContextTokens(line 36) — called in bodysrc/agents/subagent-spawn.ts:19—resolveSubagentSpawnModelSelectionStub, called at line 394.
src/agents/tools/sessions-helpers.ts:32—sanitizeUserFacingTextLocal re-stub (returns text unchanged). The REAL implementation exists at
src/agents/agent-helpers/errors.ts:537(50+ lines). This local stub shadows the real function. The import should be rewired to the real implementation.Stubs with Live Callers (require caller fixes, not simple deletion)
src/gateway/device-auth.ts:4-5—normalizeDeviceMetadataForAuthStub (returns
undefined), but called bybuildDeviceAuthPayloadV3(real function, line 42-43) and imported bymessage-handler.ts:38(called at lines 220-223). Removal requires fixing the callers — either inline the normalization or remove the calls.src/gateway/server-http.ts:50-53— 3 canvas/plugin auth stubsauthorizeCanvasRequest(lines 50-51) — returnstrueno-op; called at lines 531, 644enforcePluginRouteGatewayAuth(line 52) — returnstrueno-op; called at line 199isCanvasPath(line 53) — returnsfalseno-op; called at line 528These stubs have live callers that safely consume the no-op returns. The callers will need to be simplified when the stubs are removed (e.g., remove the
if (!isCanvasPath(...))guard).Test Files Requiring Mock Cleanup
Test files that mock
model-catalog.js:src/agents/remoteclaw-tools.session-status.test.ts:41src/commands/agent.test.ts:19src/auto-reply/reply/commands.test.ts:64src/auto-reply/reply/session.test.ts:18src/auto-reply/reply.block-streaming.test.ts:40src/auto-reply/reply.directive.directive-behavior.e2e-mocks.ts:14src/auto-reply/reply.triggers.trigger-handling.test-harness.ts:99-125src/auto-reply/reply.directive.directive-behavior.e2e-harness.ts:122src/cron/isolated-agent/run.test-harness.ts:69src/cron/isolated-agent/run.channel-bridge.test.ts:80src/cron/isolated-agent/run.auth-retry.test.ts:59src/cron/isolated-agent.mocks.ts:3Test files that mock
model-selection.js:src/auto-reply/reply/get-reply.reset-hooks-fallback.test.ts:18src/cron/isolated-agent/run.test-harness.ts:73-82src/cron/isolated-agent/run.channel-bridge.test.ts:84src/cron/isolated-agent/run.auth-retry.test.ts:63NOT in Scope (alive functions incorrectly listed in prior version)
The following are NOT stubs — they are real, working implementations:
sanitizeUserFacingTextinagents/agent-helpers/errors.ts:537— 50+ line real implementationbuildOauthProviderAuthResultinplugin-sdk/provider-auth-result.ts:17— 67-line real implementation, re-exported fromplugin-sdk/index.ts:166validateVoiceCredentialsinchannels/voice-credentials.ts:55— real function with tests invoice-credentials.test.tsrunConfigUnsetincli/config-cli.ts:310— real function, imported byroutes.ts:121runModelDirectiveTextinreply.directive.directive-behavior.model-directive-test-utils.ts:8— real test utilityDuplicate Type/Function Exports to Consolidate
model-selection.tsre-exports stub versions of types/functions that have live implementations inprovider-utils.ts:ModelReftype — live inprovider-utils.ts:11normalizeModelRef— live inprovider-utils.ts:157parseModelRef— live inprovider-utils.ts:166normalizeProviderId— live inprovider-utils.tsThinkLeveltype — live inauto-reply/thinking.ts:1, duplicated as stub inmodel-selection.ts:15Importers of these from
model-selection.tsshould be redirected to the canonical source.Acceptance Criteria
src/agents/model-catalog.tsdeletedsrc/agents/model-selection.tsdeletedsrc/auto-reply/reply/model-selection.tsdeletedprovider-utils.tsorthinking.tsnormalizeDeviceMetadataForAuthcallers fixed (not just stub deleted)server-http.tscanvas/plugin auth stub callers simplifiedmodelCatalog,ModelCatalog,modelAliasIndex,ModelAlias,modelSupportsVision,findModelInCatalog,resolveDefaultModelForAgent,loadModelCatalog,resolveModelCatalog,resolveModelCatalogEntry,resolveModelSelection,resolveModelSelectionForCron,loadGatewayModelCatalog,__resetModelCatalogCacheForTest,resolveStoredModelOverride,resolveSubagentSpawnModelSelectionreferences in source (grep exit criterion — excluding liveprovider-utils.tsandthinking.tsexports)model-catalog.jsandmodel-selection.jscleaned uppnpm checkpasses