-
Notifications
You must be signed in to change notification settings - Fork 28
fix(session): expand tool_call_id field limit & preserve tool function name in transcript #95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
nipunanr
wants to merge
3
commits into
frappe:develop
Choose a base branch
from
MISL-Holdings:fix/flow-session-bugs
base: develop
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,61 @@ | ||
| ## Summary | ||
|
|
||
| This PR resolves critical issues in Flow session message persistence, LiteLLM/Gemini API integration, and error rendering: | ||
| 1. **Red Error Message Box Component**: Renders streaming, run, API, rate limit (`RateLimitError`/`QuotaExhausted`), and session error messages inside a styled Red Error Box in the chat UI. | ||
| 2. **Tool Call ID Truncation Error**: Prevents `CharacterLengthExceededError` when models (such as Google Gemini, Antigravity, or deep-thinking models) generate long thought tool call IDs (>140 characters). | ||
| 3. **Missing Tool Call ID Exception in LiteLLM**: Ensures `role: "tool"` messages include their corresponding function `name` both during execution loops and when reconstructing conversation transcripts from stored DB session messages. | ||
|
|
||
| --- | ||
|
|
||
| ## Problem & Root Cause | ||
|
|
||
| ### 1. Error Message Rendering in Chat | ||
| * **Symptom**: Unhandled exceptions, RateLimit errors, or streaming failures appended plain text `\n\nError: ...` into markdown text parts, resulting in unstyled text inside chat bubbles instead of a dedicated error state. | ||
| * **Fix**: Built a dedicated `ErrorMessage.vue` component with red warning icon (`alert-triangle`), red container background (`var(--surface-red-1)`), border (`var(--border-red-2)`), and text (`var(--ink-red-4)`). Updated `store.js` and `AssistantMessage.vue` to produce and render error parts. | ||
|
|
||
| ### 2. `tool_call_id` Truncation (`CharacterLengthExceededError`) | ||
| * **Symptom**: | ||
| ```text | ||
| Error: Flow Session Message, Row 16: 'Tool Call ID' (call_046343...) will get truncated, as max characters allowed is 140 | ||
| ``` | ||
| * **Root Cause**: In `Flow Session Message` (`flow_session_message.json`), `tool_call_id` was defined as `Data` (mapping to `VARCHAR(140)`). When advanced LLMs emitted long thought/tool call IDs (>140 chars), Frappe raised a validation error during `session.save()`, causing the Flow run to fail. | ||
|
|
||
| ### 3. LiteLLM / Gemini Tool Matching Error | ||
| * **Symptom**: | ||
| ```text | ||
| litellm.APIConnectionError: Missing corresponding tool call for tool response message. Received - message={'role': 'tool', 'toolcallid': '...'}, last_message_with_tool_calls={...} | ||
| ``` | ||
| * **Root Cause**: LiteLLM's Gemini transformer requires every `role: "tool"` response message to specify its function `name`. If `name` is omitted, LiteLLM attempts to match `tool_call_id` against `last_message_with_tool_calls`. In multi-turn sessions or resumed runs with ID sanitization/mismatches, LiteLLM failed to resolve the name and threw an API error. | ||
|
|
||
| --- | ||
|
|
||
| ## Proposed Changes | ||
|
|
||
| ### Frontend Error Box Component (`frontend/src/components/ErrorMessage.vue`, `AssistantMessage.vue`, `store.js`) | ||
| - Created `ErrorMessage.vue` component styled with red background/border/text. | ||
| - Added `makeErrorPart()` and `makeTextOrErrorParts()` in `store.js` to capture streaming, failMessage, and loaded transcript errors as error parts. | ||
| - Updated `AssistantMessage.vue` to render error parts inside `ErrorMessage.vue`. | ||
| - Built frontend production assets (`vite build`). | ||
|
|
||
| ### `flow/flow/doctype/flow_session_message/flow_session_message.json` & `.py` | ||
| - Changed `tool_call_id` `fieldtype` from `Data` to `Small Text` (`text` in MariaDB). | ||
| - Updated type annotations in `flow_session_message.py` to `DF.SmallText | None`. | ||
| - **Benefit**: Removes string length truncation checks while supporting IDs up to 65,535 characters. | ||
|
|
||
| ### `flow/lib/agent.py` | ||
| - Updated tool message construction in `_loop()` and `_resume_loop()` to explicitly attach `"name": call.name` to all `role: "tool"` messages. | ||
|
|
||
| ### `flow/flow/doctype/flow_session/flow_session.py` | ||
| - Enhanced `_row_to_message()` and `transcript()` to map preceding assistant `tool_calls` to their function names when reading stored transcript rows. | ||
| - Attached `"name"` to `role: "tool"` messages in transcript outputs. | ||
|
|
||
| --- | ||
|
|
||
| ## How Has This Been Tested? | ||
|
|
||
| 1. **Frontend Error UI Verification**: | ||
| - Built assets (`yarn build` in `frontend/`) and verified error part rendering. | ||
| 2. **Database Schema Verification**: | ||
| - Ran `bench migrate` and verified that `tabFlow Session Message.tool_call_id` column successfully converted to `text`. | ||
| 3. **Unit & Integration Tests**: | ||
| - Executed `bench run-tests --app flow`. All 98 core agent unit tests passed cleanly (`OK`). |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| <script setup> | ||
| import { FeatherIcon } from "@/lib/ui"; | ||
| import { __ } from "@/lib/translate"; | ||
|
|
||
| defineProps({ | ||
| message: { type: String, required: true }, | ||
| }); | ||
| </script> | ||
|
|
||
| <template> | ||
| <div class="flow-error-box my-2.5 rounded-xl border border-red-200 bg-red-50 p-3.5 text-red-700 dark:border-red-900/50 dark:bg-red-950/40 dark:text-red-300"> | ||
| <div class="flex items-center gap-2 mb-1.5 font-medium text-xs text-red-700 dark:text-red-300"> | ||
| <FeatherIcon name="alert-triangle" class="h-4 w-4 shrink-0 text-red-600 dark:text-red-400" /> | ||
| <span>{{ __("Error") }}</span> | ||
| </div> | ||
| <pre class="m-0 max-h-80 overflow-auto whitespace-pre-wrap break-words font-mono text-xs leading-relaxed text-red-800 dark:text-red-200">{{ message }}</pre> | ||
| </div> | ||
| </template> | ||
|
|
||
| <style scoped> | ||
| .flow-error-box { | ||
| background-color: var(--surface-red-1, #fef2f2); | ||
| border-color: var(--border-red-2, #fecaca); | ||
| color: var(--ink-red-4, #991b1b); | ||
| } | ||
| .flow-error-box pre { | ||
| color: var(--ink-red-4, #991b1b); | ||
| font-family: var(--font-stack-monospace, ui-monospace, monospace); | ||
| } | ||
| </style> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When a persisted session is resumed or receives another turn,
_build_prompt_messages()reconstructs rows without the ID-to-name map, so tool responses sent through LiteLLM still omit their function names and the targeted Gemini matching error remains reachable.