Skip to content

Commit 900e679

Browse files
committed
fix(src): truncate tool reply with available context space left
1 parent 285880f commit 900e679

File tree

1 file changed

+50
-14
lines changed

1 file changed

+50
-14
lines changed

src/sqlite-agent.c

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,14 @@ static char* agent_get_tools_list(sqlite3 *db) {
8484
return NULL;
8585
}
8686

87+
// Check if the result contains an error (MCP not connected)
88+
if (strstr(tools_result, "\"error\"") != NULL ||
89+
strstr(tools_result, "Not connected") != NULL) {
90+
DF("MCP connection error detected: %s", tools_result);
91+
sqlite3_finalize(stmt);
92+
return NULL;
93+
}
94+
8795
char *formatted = malloc(32768);
8896
if (!formatted) {
8997
sqlite3_finalize(stmt);
@@ -456,6 +464,34 @@ static void agent_run_func(
456464
return;
457465
}
458466

467+
// Calculate dynamic truncation based on available context space
468+
int tools_list_len = (int)strlen(tools_list);
469+
int system_prompt_len = (int)strlen(system_prompt);
470+
int extraction_prompt_overhead = 2000; // Overhead for extraction prompt template
471+
int safety_margin = 1024; // Additional buffer for JSON overhead
472+
473+
// Context size (from agent_create_chat_context logic: tools_list_len * 2, min 4096)
474+
int ctx_size = tools_list_len * 2;
475+
if (ctx_size < 4096) ctx_size = 4096;
476+
477+
// Calculate available space for conversation history
478+
// ctx_size must accommodate: tools_list + system_prompt + conversation_history + extraction_prompt
479+
int available_for_conversation = ctx_size - tools_list_len - system_prompt_len
480+
- extraction_prompt_overhead - safety_margin;
481+
482+
// Ensure minimum reasonable space
483+
if (available_for_conversation < 8192) available_for_conversation = 8192;
484+
485+
// Assume average of max_iterations/2 tool calls, allocate space for each
486+
size_t dynamic_truncate_at = available_for_conversation / ((max_iterations + 1) / 2);
487+
488+
// Apply reasonable bounds
489+
if (dynamic_truncate_at < 4096) dynamic_truncate_at = 4096; // Minimum per tool
490+
if (dynamic_truncate_at > 50000) dynamic_truncate_at = 50000; // Maximum per tool
491+
492+
DF("Dynamic truncation: ctx_size=%d, tools=%d, system=%d, available=%d, truncate_at=%zu",
493+
ctx_size, tools_list_len, system_prompt_len, available_for_conversation, dynamic_truncate_at);
494+
459495
DF("Starting agent loop with max_iterations=%d", max_iterations);
460496
char conversation_history[32768] = {0};
461497
int consecutive_errors = 0;
@@ -589,12 +625,16 @@ static void agent_run_func(
589625
last_error[0] = '\0';
590626
}
591627

592-
char result_msg[8192];
593-
size_t truncate_at = 3000;
594-
if (strlen(tool_result) > truncate_at) {
595-
snprintf(result_msg, sizeof(result_msg),
596-
"Tool %s returned (truncated to %zu chars): %.3000s...\n",
597-
tool_name, truncate_at, tool_result);
628+
char result_msg[16384];
629+
// Use dynamic truncation calculated based on available context space
630+
if (strlen(tool_result) > dynamic_truncate_at) {
631+
// Dynamically create format string for truncation
632+
char format_str[128];
633+
snprintf(format_str, sizeof(format_str),
634+
"Tool %%s returned (truncated to %%zu chars): %%.%zus...\n",
635+
dynamic_truncate_at);
636+
snprintf(result_msg, sizeof(result_msg), format_str,
637+
tool_name, dynamic_truncate_at, tool_result);
598638
} else {
599639
snprintf(result_msg, sizeof(result_msg),
600640
"Tool %s returned: %s\n", tool_name, tool_result);
@@ -610,10 +650,8 @@ static void agent_run_func(
610650
}
611651
}
612652

613-
DF("Conversation history (length=%zu): %.500s%s",
614-
strlen(conversation_history),
615-
conversation_history,
616-
strlen(conversation_history) > 500 ? "..." : "");
653+
DF("Conversation history (length=%zu):", strlen(conversation_history));
654+
DF("=== FULL CONVERSATION HISTORY ===\n%s\n=== END CONVERSATION HISTORY ===", conversation_history);
617655

618656
char extraction_prompt[32768];
619657
snprintf(extraction_prompt, sizeof(extraction_prompt),
@@ -636,7 +674,7 @@ static void agent_run_func(
636674
"Return ONLY the JSON array:",
637675
schema_desc, schema_desc, conversation_history);
638676

639-
DF("Extraction prompt (first 500 chars): %.500s...", extraction_prompt);
677+
DF("=== FULL EXTRACTION PROMPT ===\n%s\n=== END EXTRACTION PROMPT ===", extraction_prompt);
640678

641679
sqlite3_stmt *ctx_size_stmt;
642680
int ctx_size_for_extraction = 0;
@@ -680,9 +718,7 @@ static void agent_run_func(
680718
json_copy[sizeof(json_copy) - 1] = '\0';
681719
sqlite3_finalize(stmt);
682720

683-
DF("LLM extracted JSON (first 1000 chars): %.1000s%s",
684-
json_copy,
685-
strlen(json_copy) > 1000 ? "..." : "");
721+
DF("=== FULL EXTRACTED JSON ===\n%s\n=== END EXTRACTED JSON ===", json_copy);
686722

687723
sqlite3_exec(db, "BEGIN TRANSACTION", 0, 0, 0);
688724

0 commit comments

Comments
 (0)