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