( messages: Message[], systemPrompt: SystemPrompt, thinkingConfig: ThinkingConfig, tools: Tools, signal: AbortSignal, options: Options, )
| 1015 | } |
| 1016 | |
| 1017 | async function* queryModel( |
| 1018 | messages: Message[], |
| 1019 | systemPrompt: SystemPrompt, |
| 1020 | thinkingConfig: ThinkingConfig, |
| 1021 | tools: Tools, |
| 1022 | signal: AbortSignal, |
| 1023 | options: Options, |
| 1024 | ): AsyncGenerator< |
| 1025 | StreamEvent | AssistantMessage | SystemAPIErrorMessage, |
| 1026 | void |
| 1027 | > { |
| 1028 | // Check cheap conditions first — the off-switch await blocks on GrowthBook |
| 1029 | // init (~10ms). For non-Opus models (haiku, sonnet) this skips the await |
| 1030 | // entirely. Subscribers don't hit this path at all. |
| 1031 | if ( |
| 1032 | !isClaudeAISubscriber() && |
| 1033 | isNonCustomOpusModel(options.model) && |
| 1034 | ( |
| 1035 | await getDynamicConfig_BLOCKS_ON_INIT<{ activated: boolean }>( |
| 1036 | 'tengu-off-switch', |
| 1037 | { |
| 1038 | activated: false, |
| 1039 | }, |
| 1040 | ) |
| 1041 | ).activated |
| 1042 | ) { |
| 1043 | logEvent('tengu_off_switch_query', {}) |
| 1044 | yield getAssistantMessageFromError( |
| 1045 | new Error(CUSTOM_OFF_SWITCH_MESSAGE), |
| 1046 | options.model, |
| 1047 | ) |
| 1048 | return |
| 1049 | } |
| 1050 | |
| 1051 | // Derive previous request ID from the last assistant message in this query chain. |
| 1052 | // This is scoped per message array (main thread, subagent, teammate each have their own), |
| 1053 | // so concurrent agents don't clobber each other's request chain tracking. |
| 1054 | // Also naturally handles rollback/undo since removed messages won't be in the array. |
| 1055 | const previousRequestId = getPreviousRequestIdFromMessages(messages) |
| 1056 | |
| 1057 | const resolvedModel = |
| 1058 | getAPIProvider() === 'bedrock' && |
| 1059 | options.model.includes('application-inference-profile') |
| 1060 | ? ((await getInferenceProfileBackingModel(options.model)) ?? |
| 1061 | options.model) |
| 1062 | : options.model |
| 1063 | |
| 1064 | queryCheckpoint('query_tool_schema_build_start') |
| 1065 | const isAgenticQuery = |
| 1066 | options.querySource.startsWith('repl_main_thread') || |
| 1067 | options.querySource.startsWith('agent:') || |
| 1068 | options.querySource === 'sdk' || |
| 1069 | options.querySource === 'hook_agent' || |
| 1070 | options.querySource === 'verification_agent' |
| 1071 | const betas = getMergedBetas(options.model, { isAgenticQuery }) |
| 1072 | |
| 1073 | // Always send the advisor beta header when advisor is enabled, so |
| 1074 | // non-agentic queries (compact, side_question, extract_memories, etc.) |
no test coverage detected