( messages: Message[], systemPrompt: SystemPrompt, thinkingConfig: ThinkingConfig, tools: Tools, signal: AbortSignal, options: Options, )
| 1047 | const lastAnnouncedDeferredTools = new Set<string>() |
| 1048 | |
| 1049 | async function* queryModel( |
| 1050 | messages: Message[], |
| 1051 | systemPrompt: SystemPrompt, |
| 1052 | thinkingConfig: ThinkingConfig, |
| 1053 | tools: Tools, |
| 1054 | signal: AbortSignal, |
| 1055 | options: Options, |
| 1056 | ): AsyncGenerator< |
| 1057 | StreamEvent | AssistantMessage | SystemAPIErrorMessage, |
| 1058 | void |
| 1059 | > { |
| 1060 | // Check cheap conditions first — the off-switch await blocks on GrowthBook |
| 1061 | // init (~10ms). For non-Opus models (haiku, sonnet) this skips the await |
| 1062 | // entirely. Subscribers don't hit this path at all. |
| 1063 | if ( |
| 1064 | !isClaudeAISubscriber() && |
| 1065 | isNonCustomOpusModel(options.model) && |
| 1066 | ( |
| 1067 | await getDynamicConfig_BLOCKS_ON_INIT<{ activated: boolean }>( |
| 1068 | 'tengu-off-switch', |
| 1069 | { |
| 1070 | activated: false, |
| 1071 | }, |
| 1072 | ) |
| 1073 | ).activated |
| 1074 | ) { |
| 1075 | logEvent('tengu_off_switch_query', {}) |
| 1076 | yield getAssistantMessageFromError( |
| 1077 | new Error(CUSTOM_OFF_SWITCH_MESSAGE), |
| 1078 | options.model, |
| 1079 | ) |
| 1080 | return |
| 1081 | } |
| 1082 | |
| 1083 | // Derive previous request ID from the last assistant message in this query chain. |
| 1084 | // This is scoped per message array (main thread, subagent, teammate each have their own), |
| 1085 | // so concurrent agents don't clobber each other's request chain tracking. |
| 1086 | // Also naturally handles rollback/undo since removed messages won't be in the array. |
| 1087 | const previousRequestId = getPreviousRequestIdFromMessages(messages) |
| 1088 | |
| 1089 | const resolvedModel = |
| 1090 | getAPIProvider() === 'bedrock' && |
| 1091 | options.model.includes('application-inference-profile') |
| 1092 | ? ((await getInferenceProfileBackingModel(options.model)) ?? |
| 1093 | options.model) |
| 1094 | : options.model |
| 1095 | |
| 1096 | queryCheckpoint('query_tool_schema_build_start') |
| 1097 | const isAgenticQuery = |
| 1098 | options.querySource.startsWith('repl_main_thread') || |
| 1099 | options.querySource.startsWith('agent:') || |
| 1100 | options.querySource === 'sdk' || |
| 1101 | options.querySource === 'hook_agent' || |
| 1102 | options.querySource === 'verification_agent' |
| 1103 | const betas = getMergedBetas(options.model, { isAgenticQuery }) |
| 1104 | |
| 1105 | // Always send the advisor beta header when advisor is enabled, so |
| 1106 | // non-agentic queries (compact, side_question, extract_memories, etc.) |
no test coverage detected