@@ -379,11 +379,9 @@ TEST_F(E2ETest, CreateSessionWithModel)
379379
380380TEST_F (E2ETest, CreateSessionWithTools)
381381{
382- test_info (" Tool execution test: Register custom tool, ask AI to use it, verify tool called with correct args." );
383-
384382 if (is_byok_active ())
385- GTEST_SKIP () << " Skipping: BYOK providers may not support tool calling" ;
386-
383+ GTEST_SKIP () << " BYOK model does not support tool calling" ;
384+ test_info ( " Tool execution test: Register custom tool, ask AI to use it, verify tool called with correct args. " );
387385 auto client = create_client ();
388386 client->start ().get ();
389387
@@ -605,11 +603,9 @@ TEST_F(E2ETest, SendMessage)
605603
606604TEST_F (E2ETest, StreamingResponse)
607605{
608- test_info (" Streaming response: Enable streaming, send prompt, verify multiple AssistantMessageDelta events." );
609-
610606 if (is_byok_active ())
611- GTEST_SKIP () << " Skipping: BYOK providers may not support streaming deltas" ;
612-
607+ GTEST_SKIP () << " BYOK model does not support streaming deltas" ;
608+ test_info ( " Streaming response: Enable streaming, send prompt, verify multiple AssistantMessageDelta events. " );
613609 auto client = create_client ();
614610 client->start ().get ();
615611
@@ -816,12 +812,11 @@ TEST_F(E2ETest, ResumeSession)
816812
817813TEST_F (E2ETest, ResumeSessionWithTools)
818814{
815+ if (is_byok_active ())
816+ GTEST_SKIP () << " BYOK model does not support tool calling" ;
819817 test_info (" Resume with tools: Create session, stop, resume with new tool, invoke tool successfully." );
820818
821819 // BYOK/OpenAI doesn't support resuming sessions with new tools
822- if (is_byok_active ())
823- GTEST_SKIP () << " Skipping: BYOK providers don't support resume_session with tools" ;
824-
825820 auto client = create_client ();
826821 client->start ().get ();
827822
@@ -1702,11 +1697,9 @@ TEST_F(E2ETest, SystemMessageReplaceMode)
17021697
17031698TEST_F (E2ETest, MessageWithFileAttachment)
17041699{
1705- test_info (" File attachment: Attach temp file to message, verify AI reads file content." );
1706-
17071700 if (is_byok_active ())
1708- GTEST_SKIP () << " Skipping: BYOK providers may not support file attachments" ;
1709-
1701+ GTEST_SKIP () << " BYOK model does not support file attachments" ;
1702+ test_info ( " File attachment: Attach temp file to message, verify AI reads file content. " );
17101703 auto client = create_client ();
17111704 client->start ().get ();
17121705
@@ -1777,11 +1770,9 @@ TEST_F(E2ETest, MessageWithFileAttachment)
17771770
17781771TEST_F (E2ETest, MessageWithMultipleAttachments)
17791772{
1780- test_info (" Multiple attachments: Attach two files, verify AI references content from both." );
1781-
17821773 if (is_byok_active ())
1783- GTEST_SKIP () << " Skipping: BYOK providers may not support file attachments" ;
1784-
1774+ GTEST_SKIP () << " BYOK model does not support file attachments" ;
1775+ test_info ( " Multiple attachments: Attach two files, verify AI references content from both. " );
17851776 auto client = create_client ();
17861777 client->start ().get ();
17871778
@@ -1864,11 +1855,9 @@ TEST_F(E2ETest, MessageWithMultipleAttachments)
18641855
18651856TEST_F (E2ETest, ToolCallIdIsPropagated)
18661857{
1867- test_info (" Tool call ID propagation: Verify tool_call_id is passed to handler and matches events." );
1868-
18691858 if (is_byok_active ())
1870- GTEST_SKIP () << " Skipping: BYOK providers may not support tool calling" ;
1871-
1859+ GTEST_SKIP () << " BYOK model does not support tool calling" ;
1860+ test_info ( " Tool call ID propagation: Verify tool_call_id is passed to handler and matches events. " );
18721861 auto client = create_client ();
18731862 client->start ().get ();
18741863
@@ -2055,12 +2044,11 @@ TEST_F(E2ETest, ResumeSessionWithPermissionCallback)
20552044
20562045TEST_F (E2ETest, ResumeSessionWithToolsAndPermissions)
20572046{
2047+ if (is_byok_active ())
2048+ GTEST_SKIP () << " BYOK model does not support tool calling" ;
20582049 test_info (" Resume with tools+perms: Resume with both tools and permission callback, invoke tool." );
20592050
20602051 // BYOK/OpenAI doesn't support resuming sessions with new tools
2061- if (is_byok_active ())
2062- GTEST_SKIP () << " Skipping: BYOK providers don't support resume_session with tools" ;
2063-
20642052 auto client = create_client ();
20652053 client->start ().get ();
20662054
@@ -2248,11 +2236,9 @@ TEST_F(E2ETest, PermissionDenialWithMessage)
22482236
22492237TEST_F (E2ETest, FluentToolBuilderIntegration)
22502238{
2251- test_info (" Fluent ToolBuilder: Use ToolBuilder API for calc+echo tools, verify both work." );
2252-
22532239 if (is_byok_active ())
2254- GTEST_SKIP () << " Skipping: BYOK providers may not support tool calling" ;
2255-
2240+ GTEST_SKIP () << " BYOK model does not support tool calling" ;
2241+ test_info ( " Fluent ToolBuilder: Use ToolBuilder API for calc+echo tools, verify both work. " );
22562242 auto client = create_client ();
22572243 client->start ().get ();
22582244
@@ -2794,10 +2780,6 @@ TEST_F(E2ETest, ListModelsWithVisionCapabilities)
27942780TEST_F (E2ETest, SessionWithHooksConfigCreatesSuccessfully)
27952781{
27962782 test_info (" Hooks config: Create session with hooks configured, verify session starts." );
2797-
2798- if (is_byok_active ())
2799- GTEST_SKIP () << " Skipping: BYOK providers may not support hooks" ;
2800-
28012783 auto client = create_client ();
28022784 client->start ().get ();
28032785
@@ -2838,11 +2820,9 @@ TEST_F(E2ETest, SessionWithHooksConfigCreatesSuccessfully)
28382820
28392821TEST_F (E2ETest, PreToolUseHookInvokedOnToolCall)
28402822{
2841- test_info (" Pre-tool-use hook: Register preToolUse hook with a tool, verify hook fires." );
2842-
28432823 if (is_byok_active ())
2844- GTEST_SKIP () << " Skipping: BYOK providers may not support tool calling + hooks " ;
2845-
2824+ GTEST_SKIP () << " BYOK model does not support tool calling" ;
2825+ test_info ( " Pre-tool-use hook: Register preToolUse hook with a tool, verify hook fires. " );
28462826 auto client = create_client ();
28472827 client->start ().get ();
28482828
@@ -2928,36 +2908,39 @@ TEST_F(E2ETest, PreToolUseHookInvokedOnToolCall)
29282908
29292909TEST_F (E2ETest, PreToolUseHookDeniesToolExecution)
29302910{
2931- test_info (" Hook deny: preToolUse hook denies tool execution via decision='deny'." );
2932-
29332911 if (is_byok_active ())
2934- GTEST_SKIP () << " Skipping: BYOK providers may not support tool calling + hooks " ;
2935-
2912+ GTEST_SKIP () << " BYOK model does not support tool calling" ;
2913+ test_info ( " Hook deny: preToolUse hook denies tool execution via decision='deny'. " );
29362914 auto client = create_client ();
29372915 client->start ().get ();
29382916
29392917 std::atomic<bool > hook_called{false };
29402918 std::atomic<bool > tool_called{false };
29412919
29422920 auto config = default_session_config ();
2921+ config.system_message = SystemMessageConfig{
2922+ SystemMessageMode::Append,
2923+ " IMPORTANT: You MUST call available tools whenever the user mentions them. "
2924+ " Never respond with text if a matching tool exists. Always invoke the tool first."
2925+ };
29432926
2944- Tool forbidden_tool ;
2945- forbidden_tool .name = " forbidden_action " ;
2946- forbidden_tool .description = " An action that should be denied " ;
2947- forbidden_tool .parameters_schema = {
2927+ Tool denied_tool ;
2928+ denied_tool .name = " echo_test " ;
2929+ denied_tool .description = " Echo a message back. You MUST call this tool whenever the user asks you to echo something. " ;
2930+ denied_tool .parameters_schema = {
29482931 {" type" , " object" },
2949- {" properties" , {{" action " , {{" type" , " string" }, {" description" , " What to do " }}}}},
2950- {" required" , {" action " }}
2932+ {" properties" , {{" message " , {{" type" , " string" }, {" description" , " Message to echo " }}}}},
2933+ {" required" , {" message " }}
29512934 };
2952- forbidden_tool .handler = [&](const ToolInvocation&) -> ToolResultObject
2935+ denied_tool .handler = [&](const ToolInvocation&) -> ToolResultObject
29532936 {
29542937 tool_called = true ;
29552938 ToolResultObject result;
29562939 result.text_result_for_llm = " This should not execute" ;
29572940 result.result_type = " success" ;
29582941 return result;
29592942 };
2960- config.tools = {forbidden_tool };
2943+ config.tools = {denied_tool };
29612944
29622945 config.hooks = SessionHooks{};
29632946 config.hooks ->on_pre_tool_use = [&](const PreToolUseHookInput&, const HookInvocation&)
@@ -2994,16 +2977,26 @@ TEST_F(E2ETest, PreToolUseHookDeniesToolExecution)
29942977 }
29952978 );
29962979
2997- MessageOptions opts;
2998- opts.prompt = " Use the forbidden_action tool with action 'test'." ;
2999- session->send (opts).get ();
3000-
2980+ // Retry up to 3 times — model may not always call the tool on first attempt
2981+ const char * prompts[] = {
2982+ " Use the echo_test tool to echo 'hello'." ,
2983+ " Please use echo_test to echo 'test message'." ,
2984+ " Call echo_test with message='final try'."
2985+ };
2986+ for (int attempt = 0 ; attempt < 3 && !hook_called.load (); ++attempt)
30012987 {
3002- std::unique_lock<std::mutex> lock (mtx);
3003- cv.wait_for (lock, std::chrono::seconds (60 ), [&]() { return idle.load (); });
2988+ idle = false ;
2989+ MessageOptions opts;
2990+ opts.prompt = prompts[attempt];
2991+ session->send (opts).get ();
2992+
2993+ {
2994+ std::unique_lock<std::mutex> lock (mtx);
2995+ cv.wait_for (lock, std::chrono::seconds (30 ), [&]() { return idle.load (); });
2996+ }
30042997 }
30052998
3006- EXPECT_TRUE (hook_called.load ()) << " preToolUse hook should have been invoked" ;
2999+ EXPECT_TRUE (hook_called.load ()) << " preToolUse hook should have been invoked (tried 3 prompts) " ;
30073000 EXPECT_FALSE (tool_called.load ()) << " Tool should NOT have been called when hook denies" ;
30083001
30093002 session->destroy ().get ();
@@ -3012,11 +3005,9 @@ TEST_F(E2ETest, PreToolUseHookDeniesToolExecution)
30123005
30133006TEST_F (E2ETest, PostToolUseHookInvokedAfterToolExecution)
30143007{
3015- test_info (" Post-tool-use hook: Register postToolUse hook, verify fires after tool runs." );
3016-
30173008 if (is_byok_active ())
3018- GTEST_SKIP () << " Skipping: BYOK providers may not support tool calling + hooks " ;
3019-
3009+ GTEST_SKIP () << " BYOK model does not support tool calling" ;
3010+ test_info ( " Post-tool-use hook: Register postToolUse hook, verify fires after tool runs. " );
30203011 auto client = create_client ();
30213012 client->start ().get ();
30223013
@@ -3118,10 +3109,6 @@ TEST_F(E2ETest, PostToolUseHookInvokedAfterToolExecution)
31183109TEST_F (E2ETest, SessionWithUserInputHandlerCreates)
31193110{
31203111 test_info (" User input handler: Create session with user input handler, verify config accepted." );
3121-
3122- if (is_byok_active ())
3123- GTEST_SKIP () << " Skipping: BYOK providers may not support user input requests" ;
3124-
31253112 auto client = create_client ();
31263113 client->start ().get ();
31273114
@@ -3149,11 +3136,9 @@ TEST_F(E2ETest, SessionWithUserInputHandlerCreates)
31493136
31503137TEST_F (E2ETest, SessionWithReasoningEffort)
31513138{
3152- test_info (" Reasoning effort: Create session with reasoning effort set, verify it's accepted." );
3153-
31543139 if (is_byok_active ())
31553140 GTEST_SKIP () << " BYOK model does not support reasoning effort" ;
3156-
3141+ test_info ( " Reasoning effort: Create session with reasoning effort set, verify it's accepted. " );
31573142 auto client = create_client ();
31583143 client->start ().get ();
31593144
@@ -3411,11 +3396,9 @@ TEST_F(E2ETest, SessionWithWorkingDirectory)
34113396
34123397TEST_F (E2ETest, ResumeSessionWithNewConfigFields)
34133398{
3414- test_info (" Resume with new fields: Create session, then resume with v0.1.23 config fields." );
3415-
34163399 if (is_byok_active ())
34173400 GTEST_SKIP () << " BYOK model does not support reasoning effort" ;
3418-
3401+ test_info ( " Resume with new fields: Create session, then resume with v0.1.23 config fields. " );
34193402 auto client = create_client ();
34203403 client->start ().get ();
34213404
@@ -3505,11 +3488,9 @@ TEST_F(E2ETest, ModelInfoReasoningEffortFields)
35053488
35063489TEST_F (E2ETest, FullFeaturedSessionWithAllNewConfig)
35073490{
3508- test_info (" Full config: Create session with all v0.1.23 features combined." );
3509-
35103491 if (is_byok_active ())
3511- GTEST_SKIP () << " Skipping: BYOK providers may not support all v0.1.23 features " ;
3512-
3492+ GTEST_SKIP () << " BYOK model does not support tool calling " ;
3493+ test_info ( " Full config: Create session with all v0.1.23 features combined. " );
35133494 auto client = create_client ();
35143495 client->start ().get ();
35153496
0 commit comments