feat: add MiniMax provider support#12655
Conversation
- Add MiniMaxModelComponent with OpenAI-compatible API (api.minimax.io/v1) - Support MiniMax-M2.7 (default) and MiniMax-M2.7-highspeed models - Add MINIMAX_API_KEY environment variable support - Temperature constrained to (0.0, 1.0] as required by MiniMax API - Add MiniMax icon for UI display - Add 16 unit tests covering build_model, temperature handling, model fetching
WalkthroughThe PR standardizes data type handling across starter project flows by removing JSON and Table from ChatOutput's accepted input types, renames Table outputs to DataFrame and JSON outputs to Data throughout multiple starter projects, downgrades pydantic dependencies to 2.11.10, introduces a new MiniMax language model component with frontend icons and unit tests, and updates related module exports. Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~30 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Important Pre-merge checks failedPlease resolve all errors before merging. Addressing warnings is optional. ❌ Failed checks (1 error, 4 warnings)
✅ Passed checks (2 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 13
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (18)
src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting.json (1)
83-88:⚠️ Potential issue | 🟡 MinorKeep edge
idcontract in sync with updatedtargetHandle.Line [83] still encodes
JSON/Tablein the edgeid, while Line [88] removes them fromtargetHandle.inputTypes. Please regenerate/update the edge id to match the new contract.Proposed fix
- "id": "reactflow__edge-LanguageModelComponent-FLeYF{œdataTypeœ:œLanguageModelComponentœ,œidœ:œLanguageModelComponent-FLeYFœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-yK0AU{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-yK0AUœ,œinputTypesœ:[œDataœ,œJSONœ,œDataFrameœ,œTableœ,œMessageœ],œtypeœ:œstrœ}", + "id": "reactflow__edge-LanguageModelComponent-FLeYF{œdataTypeœ:œLanguageModelComponentœ,œidœ:œLanguageModelComponent-FLeYFœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-yK0AU{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-yK0AUœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Basic` Prompting.json around lines 83 - 88, Edge id string for the React Flow edge (the value of "id" that starts with "reactflow__edge-LanguageModelComponent-FLeYF-...-ChatOutput-yK0AU") still encodes JSON and Table in its embedded inputTypes while the "targetHandle" for ChatOutput-yK0AU now lists inputTypes as [Data, DataFrame, Message]; update/regenerate that edge id to reflect the new contract so the embedded inputTypes match targetHandle (remove JSON and Table from the encoded id), ensuring the identifiers LanguageModelComponent-FLeYF and ChatOutput-yK0AU remain unchanged.src/backend/base/langflow/initial_setup/starter_projects/Social Media Agent.json (1)
111-116:⚠️ Potential issue | 🟡 MinorUpdate the serialized edge
idtoo.Line 111 still embeds the removed
JSON/Tabletypes even though Line 116 now exposes onlyData/DataFrame/Message. Leaving those out of sync makes the flow JSON internally inconsistent.🧩 Suggested fix
- "id": "reactflow__edge-Agent-0vMrI{œdataTypeœ:œAgentœ,œidœ:œAgent-0vMrIœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-Lgpwq{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-Lgpwqœ,œinputTypesœ:[œDataœ,œJSONœ,œDataFrameœ,œTableœ,œMessageœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-Agent-0vMrI{œdataTypeœ:œAgentœ,œidœ:œAgent-0vMrIœ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-Lgpwq{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-Lgpwqœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œotherœ}",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Social` Media Agent.json around lines 111 - 116, The serialized edge "id" is inconsistent with the updated targetHandle inputTypes; update the edge id string that begins with "reactflow__edge-Agent-0vMrI{…}-ChatOutput-Lgpwq{…}" so its embedded metadata matches the sourceHandle/targetHandle values (Agent-0vMrI and ChatOutput-Lgpwq) — specifically remove the now-removed JSON and Table types from the embedded output_types/inputTypes in the id so it lists only Data, DataFrame, Message to match sourceHandle and targetHandle.src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json (1)
190-194:⚠️ Potential issue | 🟡 MinorKeep the edge
idaligned with the new handle types.Line 190 still serializes the old
inputTypes(JSON/Tableincluded) while Line 194 has the narrowed contract. That leaves two conflicting sources of truth inside the same edge object and can cause stale round-trips if any importer/parser derives handle metadata fromid.🧩 Suggested fix
- "id": "xy-edge__LanguageModelComponent-YIUOh{œdataTypeœ:œLanguageModelComponentœ,œidœ:œLanguageModelComponent-YIUOhœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-WSW39{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-WSW39œ,œinputTypesœ:[œDataœ,œJSONœ,œDataFrameœ,œTableœ,œMessageœ],œtypeœ:œstrœ}", + "id": "xy-edge__LanguageModelComponent-YIUOh{œdataTypeœ:œLanguageModelComponentœ,œidœ:œLanguageModelComponent-YIUOhœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-WSW39{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-WSW39œ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œstrœ}",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Basic` Prompt Chaining.json around lines 190 - 194, The edge object's serialized "id" currently encodes outdated handle metadata (it includes inputTypes JSON/Table) that conflicts with the updated "sourceHandle"/"targetHandle"; update the "id" string for the edge with the same handle metadata as "sourceHandle" and "targetHandle" (remove JSON and Table from inputTypes, match the exact field names/types and ordering used in targetHandle/sourceHandle) so the edge id, sourceHandle and targetHandle are consistent (refer to the existing "id" value, "sourceHandle" and "targetHandle" fields to align the encoded handle representation).src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json (1)
2345-2362:⚠️ Potential issue | 🟡 MinorFinish the
JSON/Table→Data/DataFramerename in the surrounding copy.This block now exports
DataandDataFrame, but the same starter template still calls the parser inputJSON or Tableat Line 762 and says it produces “structured JSON” at Line 3001. Importing the project will show both naming schemes side by side.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Portfolio` Website Code Generator.json around lines 2345 - 2362, The starter template still uses the old wording "JSON / Table" and "structured JSON" while the runtime now emits "Data" and "DataFrame"; update all user-facing copy in this JSON file to the new names: rename any input label or help text that says "JSON" or "JSON or Table" to "Data" (or "Data input") and change any occurrences of "structured JSON" to "structured DataFrame" (or "structured Data") so they match the method name build_structured_dataframe and the output node dataframe_output; search for display_name, description, title, help_text, and any parser/input label strings and replace accordingly.src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json (1)
55-60:⚠️ Potential issue | 🟡 MinorRegenerate the edge ID after narrowing the handle types.
Line 60 updates the serialized
targetHandle, but Line 55 still bakes the old["Data","JSON","DataFrame","Table","Message"]signature into the edgeid. That leaves this flow internally inconsistent and can create stale or duplicate edge identities when the project is loaded or re-saved.🩹 Suggested fix
- "id": "reactflow__edge-Agent-9dON7{œdataTypeœ:œAgentœ,œidœ:œAgent-9dON7œ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-o3obj{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-o3objœ,œinputTypesœ:[œDataœ,œJSONœ,œDataFrameœ,œTableœ,œMessageœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-Agent-9dON7{œdataTypeœ:œAgentœ,œidœ:œAgent-9dON7œ,œnameœ:œresponseœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-o3obj{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-o3objœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œotherœ}",🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Nvidia` Remix.json around lines 55 - 60, The edge object has an outdated id that still encodes the old targetHandle types; regenerate the "id" for the edge connecting source "Agent-9dON7" to target "ChatOutput-o3obj" so it reflects the updated "targetHandle" signature (the trimmed inputTypes removing JSON/Table), using the same id-generation logic the app uses for edges (i.e., compose id from source, sourceHandle, target, targetHandle) so the serialized id and the "targetHandle"/"sourceHandle" stay consistent and avoid stale/duplicate edge identities.src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json (1)
111-116:⚠️ Potential issue | 🟡 MinorRegenerate the edge IDs after changing
targetHandle.inputTypes.
targetHandlenow advertises["Data", "DataFrame", "Message"], but both serialized edgeidvalues still embed the removedJSON/Tabletypes. That leaves this snapshot internally inconsistent and can cause the editor to recreate these edges with new IDs the next time the flow is regenerated or re-saved.Suggested fix
- "id": "reactflow__edge-LanguageModelComponent-ZLKtg{œdataTypeœ:œLanguageModelComponentœ,œidœ:œLanguageModelComponent-ZLKtgœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-h5fAd{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-h5fAdœ,œinputTypesœ:[œDataœ,œJSONœ,œDataFrameœ,œTableœ,œMessageœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-LanguageModelComponent-ZLKtg{œdataTypeœ:œLanguageModelComponentœ,œidœ:œLanguageModelComponent-ZLKtgœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-h5fAd{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-h5fAdœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œotherœ}", - "id": "reactflow__edge-LanguageModelComponent-dZixZ{œdataTypeœ:œLanguageModelComponentœ,œidœ:œLanguageModelComponent-dZixZœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-DVXkn{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-DVXknœ,œinputTypesœ:[œDataœ,œJSONœ,œDataFrameœ,œTableœ,œMessageœ],œtypeœ:œotherœ}", + "id": "reactflow__edge-LanguageModelComponent-dZixZ{œdataTypeœ:œLanguageModelComponentœ,œidœ:œLanguageModelComponent-dZixZœ,œnameœ:œtext_outputœ,œoutput_typesœ:[œMessageœ]}-ChatOutput-DVXkn{œfieldNameœ:œinput_valueœ,œidœ:œChatOutput-DVXknœ,œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ],œtypeœ:œotherœ}",Also applies to: 169-174
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Text` Sentiment Analysis.json around lines 111 - 116, The serialized edge objects contain stale IDs that embed old inputTypes (e.g., the "id" field starting with "reactflow__edge-LanguageModelComponent-ZLKtg...-ChatOutput-h5fAd") which no longer match the updated targetHandle.inputTypes (now ["Data","DataFrame","Message"]); update/regenerate the edge IDs for these edges so the embedded handle/type lists reflect the current sourceHandle/targetHandle values (search for edges referencing LanguageModelComponent-ZLKtg and ChatOutput-h5fAd and replace their "id" strings to match the current serialized sourceHandle/targetHandle), and apply the same fix to the other occurrence noted (the block around the second edge at the later lines).src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json (1)
83-88:⚠️ Potential issue | 🟡 MinorEdge ID contains stale type information.
The edge
idat line 83 still references the oldinputTypeslist includingJSONandTable, while thetargetHandleat line 88 anddata.targetHandle.inputTypes(lines 75-79) have been correctly updated to["Data", "DataFrame", "Message"].While ReactFlow edge IDs are typically used only as unique identifiers, this inconsistency could cause confusion during maintenance. Consider regenerating the edge ID to match the updated type contract, or leaving a note if this is expected behavior for backward compatibility.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Document` Q&A.json around lines 83 - 88, The edge id string for the reactflow edge connecting LanguageModelComponent-htMuI -> ChatOutput-bcQIH still includes the old inputTypes (JSON, Table); update/regenerate the "id" value to reflect the current inputTypes ("Data", "DataFrame", "Message") so it matches the targetHandle and data.targetHandle.inputTypes, i.e., replace the stale type list inside the id (the long string starting with reactflow__edge-LanguageModelComponent-htMuI…) or, if you intentionally preserve the old id for compatibility, add a brief inline comment in the JSON indicating that the id is intentionally versioned/stale.src/backend/base/langflow/initial_setup/starter_projects/Search agent.json (1)
25-29:⚠️ Potential issue | 🟡 MinorUpdate the edge
idto match the narrowedtargetHandle.The handle contract was reduced to
Data/DataFrame/Message, but the serialized edgeidstill containsJSONandTable. Keeping both forms out of sync makes the exported graph inconsistent and can cause round-trip save noise.♻️ Proposed fix
- "id": "...œinputTypesœ:[œDataœ,œJSONœ,œDataFrameœ,œTableœ,œMessageœ]..." + "id": "...œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ]..."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Search` agent.json around lines 25 - 29, The serialized edge id string for the edge "xy-edge__Agent-9JGgQ...-ChatOutput-Pygov" is out of sync with its narrowed targetHandle (ChatOutput-Pygov) — it still lists JSON and Table in the embedded inputTypes; update the edge "id" value to match the targetHandle's inputTypes ([Data, DataFrame, Message]) by removing JSON and Table so the embedded handle in the id exactly mirrors the "targetHandle" field (ensure the same fieldName/id/inputTypes/type tokens are used).src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json (1)
56-61:⚠️ Potential issue | 🟡 MinorRegenerate the serialized edge ID after changing the handle types.
targetHandlenow advertises onlyData/DataFrame/Message, but the edgeidstill embedsJSONandTable. That leaves this saved flow internally inconsistent and can cause needless diff churn or a duplicate edge on the next round-trip save.♻️ Proposed fix
- "id": "...œinputTypesœ:[œDataœ,œJSONœ,œDataFrameœ,œTableœ,œMessageœ]..." + "id": "...œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ]..."🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Instagram` Copywriter.json around lines 56 - 61, The serialized edge "id" for the edge between source Prompt-vj0Ef and target ChatOutput-xm3UQ embeds obsolete handle types (JSON, Table) and must be regenerated to match the current targetHandle's inputTypes ([Data, DataFrame, Message]); update the value of the "id" string that starts with "reactflow__edge-Prompt-vj0Ef{...}-ChatOutput-xm3UQ{...}" so its embedded serialized handle section for the target matches the targetHandle field (remove JSON and Table and keep the canonical ordering/format), ensuring the edge id, "source": "Prompt-vj0Ef" and "target": "ChatOutput-xm3UQ" stay consistent with the handle serialization to avoid diff churn/duplicate edges on save.src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json (1)
96-112:⚠️ Potential issue | 🟡 MinorRegenerate the
ChatOutputserialization.This update changes
input_valueto aHandleInput, but the same node still serializestemplate.input_valueas_input_type: "MessageInput"/type: "str", and the connected edge still usestype: "str"with the old handle signature embedded in itsid. That leaves the starter flow with conflicting definitions for the same input and can break round-tripping or editing after import.Also applies to: 397-484
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Invoice` Summarizer.json around lines 96 - 112, The ChatOutput node serialization is out of date: template.input_value was converted to a HandleInput but the node still emits _input_type/ type as the old MessageInput/str and the connecting edge id/targetHandle retains the old handle signature; update the ChatOutput serialization (the node with id "ChatOutput-Acmbw" and its template.input_value) to emit the correct HandleInput metadata (set _input_type to HandleInput and adjust type/field descriptors accordingly) and regenerate the connected edge representation (the edge whose source is "Agent-CBCVT" and id containing "xy-edge__Agent-CBCVT...-ChatOutput-Acmbw") so its id, targetHandle, and inputTypes reflect the new handle signature and inputTypes list; apply the same fix to the other occurrences referenced around lines 397-484 to ensure consistent round-trippable definitions.src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json (1)
27-32:⚠️ Potential issue | 🟡 MinorRegenerate this edge ID too.
Line 27 still serializes the old ChatOutput handle types, but Line 32 narrows the actual
targetHandleto["Data","DataFrame","Message"]. That mismatch leaves stale edge metadata in the starter project and is likely to be rewritten later anyway.♻️ Proposed fix
- œinputTypesœ:[œDataœ,œJSONœ,œDataFrameœ,œTableœ,œMessageœ] + œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Simple` Agent.json around lines 27 - 32, The edge ID string for the connection between Agent-oYRYa and ChatOutput-z90NZ embeds stale handle metadata (sourceHandle includes JSON/Table while targetHandle is narrowed to ["Data","DataFrame","Message"]); regenerate the edge identifier and its serialized handle fields so they match the actual targetHandle (remove JSON and Table from the serialized types) — update the "id" value and the "sourceHandle"/"targetHandle" entries for the Agent-oYRYa -> ChatOutput-z90NZ edge so all embedded handle/type lists are consistent.src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.json (1)
171-176:⚠️ Potential issue | 🟡 MinorUpdate the serialized edge ID to match the new handle signature.
Line 171 still encodes the old
["Data","JSON","DataFrame","Table","Message"]payload, while Line 176 now uses["Data","DataFrame","Message"]. Leaving those out of sync makes the saved flow internally contradictory and can cause unnecessary edge churn on the next import/save cycle.♻️ Proposed fix
- œinputTypesœ:[œDataœ,œJSONœ,œDataFrameœ,œTableœ,œMessageœ] + œinputTypesœ:[œDataœ,œDataFrameœ,œMessageœ]🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Custom` Component Generator.json around lines 171 - 176, The serialized edge id value for the edge connecting LanguageModelComponent-SCqm9 -> ChatOutput-VoIob is out of sync with the updated handle signature: update the "id" field that begins with reactflow__edge-LanguageModelComponent-SCqm9... so its embedded source/target handle payload matches the new sourceHandle/targetHandle arrays (i.e., remove "JSON" and "Table" from the encoded inputTypes/output_types so it reflects ["Data","DataFrame","Message"] / ["Message"] as used by the sourceHandle and targetHandle), ensuring the id payload for LanguageModelComponent-SCqm9 and ChatOutput-VoIob is consistent with the new handle representation.src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json (1)
27-32:⚠️ Potential issue | 🟡 MinorKeep the serialized edge IDs in sync with the updated handle metadata.
The connection metadata was updated from
JSON/TabletoData/DataFrame, but both edgeidstrings still encode the old signatures. That mismatch can leave the starter flow in a stale state the next time the editor rehydrates or rewrites the graph.Also applies to: 58-63
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Image` Sentiment Analysis.json around lines 27 - 32, The serialized edge id strings still encode the old handle metadata (JSON/Table) for the edge connecting parser-IFSS9 -> ChatOutput-Ou5RJ; update those edge "id" and any other serialized edge identifiers (e.g., the entry at lines referencing parser-IFSS9 and ChatOutput-Ou5RJ, including the ones noted at 58-63) so their encoded signatures match the current handle metadata (replace JSON/Table with Data/DataFrame and ensure inputTypes/output_types arrays and field/type names match the target/source handle objects exactly) to keep the editor rehydration consistent.src/backend/base/langflow/initial_setup/starter_projects/Market Research.json (1)
83-88:⚠️ Potential issue | 🟡 MinorRegenerate the edge IDs after renaming the handle types.
These edges now serialize
sourceHandle/targetHandleasData/DataFrame, but the persistedidstrings still embed the oldJSON/Tablesignatures. That leaves the saved graph internally inconsistent and can cause reconnect/duplicate-edge issues when the flow is edited again.Also applies to: 140-145
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Market` Research.json around lines 83 - 88, Edge objects have mismatched serialized handle type names: sourceHandle/targetHandle were renamed to Data/DataFrame but the embedded id string (e.g., the "id" value containing ParserComponent-8lfAE and ChatOutput-tjFWM) still contains old JSON/Table signatures; update the edge id strings to reflect the current handle types so they match sourceHandle/targetHandle (for example regenerate the id for the edge linking ParserComponent-8lfAE -> ChatOutput-tjFWM to include Data/DataFrame instead of JSON/Table), and apply the same fix to the other affected edges mentioned (lines 140-145) so saved graph IDs are consistent with the handle definitions.src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json (2)
532-672:⚠️ Potential issue | 🟠 MajorFinish regenerating the
ChatOutputnode snapshot.The embedded code now defines
input_valueas aHandleInput, but the serialized field below is still a plain string input (type: "str"with no_input_type). That means this starter project can load with aChatOutputschema that disagrees with its own component snapshot, and it explains why theLanguageModel -> ChatOutputedge still carries a stale string handle type. Compare this withsrc/backend/base/langflow/initial_setup/starter_projects/Research Agent.json:1888-1908, where the same field is serialized as_input_type: "HandleInput"/type: "other".🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Blog` Writer.json around lines 532 - 672, The snapshot for the ChatOutput component has a mismatch: the component's inputs declare a HandleInput named "input_value" but the serialized snapshot field "input_value" is still a plain string (type: "str"); update the snapshot to match the component by serializing "input_value" with "_input_type": "HandleInput" and the appropriate serialized type (e.g., "type": "other") and preserve the input metadata (input_types, required, display_name, trace flags) so the component schema and snapshot agree; look for the ChatOutput class and the snapshot entry for input_value to make this change.
63-89:⚠️ Potential issue | 🟠 MajorRegenerate the edge ID when you rewrite the handle types.
This edge now advertises
page_results -> input_dataasDataFrame/Data, but the persistedidstill bakes in the oldTable/JSONmetadata. That mismatch leaves the saved graph inconsistent and can create a second edge when the editor rewrites the connection.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Blog` Writer.json around lines 63 - 89, The persisted edge id string (the "id" field for the edge connecting source "URLComponent-DFXG5" to target "ParserComponent-YRRd0") still contains the old handle metadata (e.g. "Table"/"JSON") while the live sourceHandle/targetHandle objects have been rewritten to "DataFrame"/"Data", causing an inconsistent graph and duplicate edges; fix this by regenerating the edge id whenever you update handle types: when modifying URLComponent-DFXG5.sourceHandle or ParserComponent-YRRd0.targetHandle, construct the canonical handle serialization (the same format used for sourceHandle and targetHandle string fields) from the new output_types/inputTypes and include it in the edge id and in the sourceHandle/targetHandle string representations so the "id" value, "sourceHandle" string, and "targetHandle" string remain in sync with the handle objects and prevent creation of a second edge.src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json (1)
186-202:⚠️ Potential issue | 🟠 MajorRegenerate this edge ID after narrowing the handle contract.
The
idstring still encodes the old["Data", "JSON", "DataFrame", "Table", "Message"]target types, while the actualtargetHandlenow advertises["Data", "DataFrame", "Message"]. That leaves the saved flow internally inconsistent and can create duplicate/recreated edges once the graph is edited or re-saved.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Research` Agent.json around lines 186 - 202, The edge's serialized "id" is inconsistent with the updated targetHandle.inputTypes; update the reactflow edge id string (the value of "id" that begins with "reactflow__edge-LanguageModelComponent-80mt4...-ChatOutput-gZuRk...") so it encodes the current targetHandle inputTypes ["Data","DataFrame","Message"] (and matches the sourceHandle payload for LanguageModelComponent-80mt4 and the target ChatOutput-gZuRk) to avoid duplicate/recreated edges; ensure the "id", "sourceHandle" and "targetHandle" serialized fragments are regenerated together so all encoded type lists and handle ids (LanguageModelComponent-80mt4, ChatOutput-gZuRk, output_types/message) stay consistent.src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json (1)
75-79:⚠️ Potential issue | 🟡 MinorEdge ID and targetHandle mismatch could cause deserialization or edge-matching issues.
The edge
idon line 75 still embeds the oldinputTypesarray including"JSON"and"Table":œinputTypesœ:[œDataœ,œJSONœ,œDataFrameœ,œTableœ,œMessageœ]However, the
targetHandleon line 79 has been updated to only["Data", "DataFrame", "Message"]. If the application uses edge IDs for validation or matching against handle definitions, this inconsistency could cause edge resolution failures or warnings during flow loading.Consider regenerating the edge ID to match the updated targetHandle, or verify that edge IDs are not used for strict matching against handle metadata.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/base/langflow/initial_setup/starter_projects/Pokédex` Agent.json around lines 75 - 79, The edge ID string for the connection between Agent-R27kt and ChatOutput-lbrgJ embeds an outdated inputTypes list (includes "JSON" and "Table") that no longer matches the targetHandle inputTypes ["Data","DataFrame","Message"]; update/regenerate the edge id value (the long string beginning with xy-edge__Agent-R27kt{…}-ChatOutput-lbrgJ) so its embedded metadata's inputTypes exactly mirror the targetHandle, and scan for any other references to the old edge id to update them or confirm edge IDs are not relied upon for strict matching.
🧹 Nitpick comments (1)
src/backend/tests/unit/components/languagemodels/test_minimax.py (1)
25-28: Avoid coupling the template test to private_code.Rebuilding the component from
component._codemakes this test brittle to internal representation changes. Prefer exercising the public frontend-node/template path directly so the test tracks the same contract the UI uses. As per coding guidelines, component frontend/build-config tests should be driven from the component’s frontend node rather than private internals.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@src/backend/tests/unit/components/languagemodels/test_minimax.py` around lines 25 - 28, The test is brittle because it reconstructs a Component from the private MiniMaxModelComponent._code; instead, obtain the component's public frontend node/template and pass that to build_custom_component_template. Replace use of Component(_code=component._code) with the component's public API (e.g., component.frontend_node or component.build_frontend_node()/to_frontend_node()) and call build_custom_component_template(frontend_node) using that value so the test exercises the same frontend contract as the UI (references: MiniMaxModelComponent, Component, build_custom_component_template, frontend_node).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@src/backend/base/langflow/initial_setup/starter_projects/Financial` Report
Parser.json:
- Line 1442: The convert_to_string method wrongly coerces inputs with "or False"
and uses self.clean_data or False; update both usages to pass the original
object and use getattr to read the optional clean_data attribute: in
convert_to_string replace safe_convert(item, clean_data=self.clean_data or
False) with safe_convert(item, clean_data=getattr(self, "clean_data", False))
and replace safe_convert(self.input_data or False) with
safe_convert(self.input_data, clean_data=getattr(self, "clean_data", False));
ensure Message creation and self.status assignment remain the same.
In `@src/backend/base/langflow/initial_setup/starter_projects/Meeting`
Summary.json:
- Around line 1755-1762: The visible Memory output label "display_name":
"Dataframe" is inconsistent with the migrated type "DataFrame"; update the
display_name (and any embedded component definition labels) to "DataFrame" so
the UI matches the metadata (look for entries with name: "dataframe", method:
"retrieve_messages_dataframe", selected: "DataFrame" and change display_name
from "Dataframe" to "DataFrame", also apply the same change at the other
occurrence around the embedded component definition referenced in the diff).
In `@src/backend/base/langflow/initial_setup/starter_projects/Memory`
Chatbot.json:
- Around line 960-967: Replace the inconsistent lowercase label "Dataframe" with
the canonical "DataFrame" wherever the Message History output is defined (e.g.,
the JSON property "display_name": "Dataframe" in the starter project and any
embedded component definitions tied to the node with "method":
"retrieve_messages_dataframe" and "name": "dataframe"); ensure the visible label
matches the "selected": "DataFrame" value and update the other occurrence noted
near the embedded component so both places use "DataFrame" exactly.
In `@src/backend/base/langflow/initial_setup/starter_projects/SEO` Keyword
Generator.json:
- Line 60: The targetHandle value is malformed using non-JSON delimiters (œ)
which breaks downstream parsing; locate the "targetHandle" entry (contains
"ChatOutput-S7Bzs", "œfieldNameœ", "œinput_valueœ") and replace the œ delimiters
with proper JSON-escaped double quotes so the value is a valid JSON string
(matching the other escaped JSON handle payloads in this file), preserving the
same keys ("fieldName", "id", "inputTypes", "type") and array contents.
In `@src/backend/base/langflow/initial_setup/starter_projects/Sequential` Tasks
Agents.json:
- Line 314: The ChatOutput alias usage in this snapshot is inconsistent: the
targetHandle and other serialized places (e.g., edge ID and
YfinanceComponent.base_classes) use the new narrowed set
["Data","DataFrame","Message"] while other parts still serialize legacy aliases
("JSON","Table"), causing runtime contract mismatch with
src/lfx/src/lfx/components/input_output/chat_output.py; fix by migrating the
entire snapshot to a consistent alias set or preserve backward compatibility by
including both sets wherever ChatOutput appears (update the "targetHandle"
entries, the edge ids, and YfinanceComponent.base_classes to either the new
canonical aliases or a combined array
["Data","DataFrame","Message","JSON","Table"] so the embedded components match
the canonical ChatOutput contract).
In `@src/backend/base/langflow/initial_setup/starter_projects/Travel` Planning
Agents.json:
- Line 144: The patch only updates the serialized targetHandle string but leaves
the edge object’s other fields (notably the edge "id" that encodes the old
JSON/Table signature) inconsistent; regenerate the entire edge object for this
connection so all fields are consistent (update the edge "id", "targetHandle",
and any related signature/meta in the same edge block) instead of editing only
targetHandle, locating the edge by its current id and the "targetHandle"
property in the Travel Planning Agents.json file and replacing the whole edge
entry atomically.
- Line 573: The ChatOutput embedded snapshot's input handle types are out of
sync with the real component; update the HandleInput named "input_value" in
class ChatOutput to include the same input_types as the real component (Data,
JSON, DataFrame, Table, Message) instead of only ["Data", "DataFrame",
"Message"], and ensure any serialized/embedded edge metadata or handle signature
stored in this JSON (the old handle signature referenced in the comment) is
updated to reflect the new input_types so starter flows import with the correct
contract.
In `@src/backend/base/langflow/initial_setup/starter_projects/Youtube`
Analysis.json:
- Line 60: The flow's serialized edge payloads were updated to use handle types
"Data"/"DataFrame" but some sibling edge IDs still encode the old "JSON"/"Table"
signature (e.g., the targetHandle entry with "ChatOutput-JZAp9"); regenerate the
affected edge IDs so their serialized signatures reflect the new handle types.
Locate entries that contain "targetHandle" and edge id strings (like
"ChatOutput-JZAp9") and re-create or re-hash those edge IDs so they include the
updated handle type names (Data/DataFrame) instead of the old JSON/Table tokens,
ensuring all sibling edges referencing the same handle payloads use the same
regenerated IDs for consistency.
In `@src/backend/tests/unit/components/languagemodels/test_minimax.py`:
- Around line 230-238: Replace the no-op assertions in
test_minimax_update_build_config with assertions that verify real mutations:
instantiate MiniMaxModelComponent, call its to_frontend_node() to obtain the
initial build_config/node template, then call
component.update_build_config(build_config, "test-key", "api_key") and assert
the specific option/value changes inside the returned config (e.g., that the
"api_key" option exists/was added under the correct model key and contains
"test-key"); repeat similarly for update_build_config(build_config,
"MiniMax-M2.7", "model_name") and assert the model_name option was set/updated
to "MiniMax-M2.7". Ensure you reference MiniMaxModelComponent,
to_frontend_node(), and update_build_config() when locating where to change the
test.
- Around line 11-255: The test suite should be converted to use the standard
component test harness by creating a test class that inherits from
ComponentTestBaseWithoutClient and providing the required fixtures:
component_class (pointing to MiniMaxModelComponent), default_kwargs (a dict with
minimal valid kwargs like api_key, model_name, base_url, etc.), and
file_names_mapping (as required by the harness). Move the existing standalone
pytest functions into methods on that class (or keep them as module-level tests
that reuse the provided fixtures) and update any direct construction of
MiniMaxModelComponent() to rely on the component_class/default_kwargs fixtures
where appropriate; keep special-case tests (like get_models HTTP mocks,
json_mode, and error handling) but adapt them to use the harness fixtures and
ensure names reference MiniMaxModelComponent, build_model, get_models,
update_build_config, and MINIMAX_MODELS so the harness runs the standard
version/backward-compat checks.
In `@src/frontend/src/icons/MiniMax/MiniMaxIcon.jsx`:
- Line 16: The SVG fill uses the same color for both branches so dark mode never
changes; update the conditional in the MiniMaxIcon component (where it uses
props.isDark) to choose different colors for dark vs light (for example
fill={props.isDark ? "#ffffff" : "#0A0A0A"}), and apply the same fix to the
second occurrence referenced (the other fill at the same component), ensuring
both places use distinct dark and light hex values or design tokens.
In `@src/lfx/src/lfx/components/minimax/minimax.py`:
- Around line 100-108: In get_models(), Ruff flags TRY300 because the try block
contains a return; move the success-path return out of the try by computing the
response, parsing data and building models inside the try (keeping
response.raise_for_status()), then add an else: block after the except to return
models if present or MINIMAX_MODELS; keep the except handling setting
self.status and returning MINIMAX_MODELS unchanged. Reference: function
get_models, MINIMAX_MODELS, requests.get, requests.RequestException,
response.raise_for_status(), data = response.json().
- Around line 91-108: The Authorization header is using a masked SecretStr
instead of the real API key; in get_models (and similarly in build_model) detect
if self.api_key is a pydantic SecretStr and call .get_secret_value() to unwrap
it before interpolating into headers (use isinstance(self.api_key, SecretStr) or
similar), do not re-wrap an already-SecretStr value with SecretStr()—always
extract the raw string when making network requests and then set
headers={"Authorization": f"Bearer {unwrapped_api_key}", ...}; update
build_model to also unwrap any provided api_key parameter via
.get_secret_value() if it's a SecretStr.
---
Outside diff comments:
In `@src/backend/base/langflow/initial_setup/starter_projects/Basic` Prompt
Chaining.json:
- Around line 190-194: The edge object's serialized "id" currently encodes
outdated handle metadata (it includes inputTypes JSON/Table) that conflicts with
the updated "sourceHandle"/"targetHandle"; update the "id" string for the edge
with the same handle metadata as "sourceHandle" and "targetHandle" (remove JSON
and Table from inputTypes, match the exact field names/types and ordering used
in targetHandle/sourceHandle) so the edge id, sourceHandle and targetHandle are
consistent (refer to the existing "id" value, "sourceHandle" and "targetHandle"
fields to align the encoded handle representation).
In `@src/backend/base/langflow/initial_setup/starter_projects/Basic`
Prompting.json:
- Around line 83-88: Edge id string for the React Flow edge (the value of "id"
that starts with
"reactflow__edge-LanguageModelComponent-FLeYF-...-ChatOutput-yK0AU") still
encodes JSON and Table in its embedded inputTypes while the "targetHandle" for
ChatOutput-yK0AU now lists inputTypes as [Data, DataFrame, Message];
update/regenerate that edge id to reflect the new contract so the embedded
inputTypes match targetHandle (remove JSON and Table from the encoded id),
ensuring the identifiers LanguageModelComponent-FLeYF and ChatOutput-yK0AU
remain unchanged.
In `@src/backend/base/langflow/initial_setup/starter_projects/Blog` Writer.json:
- Around line 532-672: The snapshot for the ChatOutput component has a mismatch:
the component's inputs declare a HandleInput named "input_value" but the
serialized snapshot field "input_value" is still a plain string (type: "str");
update the snapshot to match the component by serializing "input_value" with
"_input_type": "HandleInput" and the appropriate serialized type (e.g., "type":
"other") and preserve the input metadata (input_types, required, display_name,
trace flags) so the component schema and snapshot agree; look for the ChatOutput
class and the snapshot entry for input_value to make this change.
- Around line 63-89: The persisted edge id string (the "id" field for the edge
connecting source "URLComponent-DFXG5" to target "ParserComponent-YRRd0") still
contains the old handle metadata (e.g. "Table"/"JSON") while the live
sourceHandle/targetHandle objects have been rewritten to "DataFrame"/"Data",
causing an inconsistent graph and duplicate edges; fix this by regenerating the
edge id whenever you update handle types: when modifying
URLComponent-DFXG5.sourceHandle or ParserComponent-YRRd0.targetHandle, construct
the canonical handle serialization (the same format used for sourceHandle and
targetHandle string fields) from the new output_types/inputTypes and include it
in the edge id and in the sourceHandle/targetHandle string representations so
the "id" value, "sourceHandle" string, and "targetHandle" string remain in sync
with the handle objects and prevent creation of a second edge.
In `@src/backend/base/langflow/initial_setup/starter_projects/Custom` Component
Generator.json:
- Around line 171-176: The serialized edge id value for the edge connecting
LanguageModelComponent-SCqm9 -> ChatOutput-VoIob is out of sync with the updated
handle signature: update the "id" field that begins with
reactflow__edge-LanguageModelComponent-SCqm9... so its embedded source/target
handle payload matches the new sourceHandle/targetHandle arrays (i.e., remove
"JSON" and "Table" from the encoded inputTypes/output_types so it reflects
["Data","DataFrame","Message"] / ["Message"] as used by the sourceHandle and
targetHandle), ensuring the id payload for LanguageModelComponent-SCqm9 and
ChatOutput-VoIob is consistent with the new handle representation.
In `@src/backend/base/langflow/initial_setup/starter_projects/Document` Q&A.json:
- Around line 83-88: The edge id string for the reactflow edge connecting
LanguageModelComponent-htMuI -> ChatOutput-bcQIH still includes the old
inputTypes (JSON, Table); update/regenerate the "id" value to reflect the
current inputTypes ("Data", "DataFrame", "Message") so it matches the
targetHandle and data.targetHandle.inputTypes, i.e., replace the stale type list
inside the id (the long string starting with
reactflow__edge-LanguageModelComponent-htMuI…) or, if you intentionally preserve
the old id for compatibility, add a brief inline comment in the JSON indicating
that the id is intentionally versioned/stale.
In `@src/backend/base/langflow/initial_setup/starter_projects/Image` Sentiment
Analysis.json:
- Around line 27-32: The serialized edge id strings still encode the old handle
metadata (JSON/Table) for the edge connecting parser-IFSS9 -> ChatOutput-Ou5RJ;
update those edge "id" and any other serialized edge identifiers (e.g., the
entry at lines referencing parser-IFSS9 and ChatOutput-Ou5RJ, including the ones
noted at 58-63) so their encoded signatures match the current handle metadata
(replace JSON/Table with Data/DataFrame and ensure inputTypes/output_types
arrays and field/type names match the target/source handle objects exactly) to
keep the editor rehydration consistent.
In `@src/backend/base/langflow/initial_setup/starter_projects/Instagram`
Copywriter.json:
- Around line 56-61: The serialized edge "id" for the edge between source
Prompt-vj0Ef and target ChatOutput-xm3UQ embeds obsolete handle types (JSON,
Table) and must be regenerated to match the current targetHandle's inputTypes
([Data, DataFrame, Message]); update the value of the "id" string that starts
with "reactflow__edge-Prompt-vj0Ef{...}-ChatOutput-xm3UQ{...}" so its embedded
serialized handle section for the target matches the targetHandle field (remove
JSON and Table and keep the canonical ordering/format), ensuring the edge id,
"source": "Prompt-vj0Ef" and "target": "ChatOutput-xm3UQ" stay consistent with
the handle serialization to avoid diff churn/duplicate edges on save.
In `@src/backend/base/langflow/initial_setup/starter_projects/Invoice`
Summarizer.json:
- Around line 96-112: The ChatOutput node serialization is out of date:
template.input_value was converted to a HandleInput but the node still emits
_input_type/ type as the old MessageInput/str and the connecting edge
id/targetHandle retains the old handle signature; update the ChatOutput
serialization (the node with id "ChatOutput-Acmbw" and its template.input_value)
to emit the correct HandleInput metadata (set _input_type to HandleInput and
adjust type/field descriptors accordingly) and regenerate the connected edge
representation (the edge whose source is "Agent-CBCVT" and id containing
"xy-edge__Agent-CBCVT...-ChatOutput-Acmbw") so its id, targetHandle, and
inputTypes reflect the new handle signature and inputTypes list; apply the same
fix to the other occurrences referenced around lines 397-484 to ensure
consistent round-trippable definitions.
In `@src/backend/base/langflow/initial_setup/starter_projects/Market`
Research.json:
- Around line 83-88: Edge objects have mismatched serialized handle type names:
sourceHandle/targetHandle were renamed to Data/DataFrame but the embedded id
string (e.g., the "id" value containing ParserComponent-8lfAE and
ChatOutput-tjFWM) still contains old JSON/Table signatures; update the edge id
strings to reflect the current handle types so they match
sourceHandle/targetHandle (for example regenerate the id for the edge linking
ParserComponent-8lfAE -> ChatOutput-tjFWM to include Data/DataFrame instead of
JSON/Table), and apply the same fix to the other affected edges mentioned (lines
140-145) so saved graph IDs are consistent with the handle definitions.
In `@src/backend/base/langflow/initial_setup/starter_projects/Nvidia` Remix.json:
- Around line 55-60: The edge object has an outdated id that still encodes the
old targetHandle types; regenerate the "id" for the edge connecting source
"Agent-9dON7" to target "ChatOutput-o3obj" so it reflects the updated
"targetHandle" signature (the trimmed inputTypes removing JSON/Table), using the
same id-generation logic the app uses for edges (i.e., compose id from source,
sourceHandle, target, targetHandle) so the serialized id and the
"targetHandle"/"sourceHandle" stay consistent and avoid stale/duplicate edge
identities.
In `@src/backend/base/langflow/initial_setup/starter_projects/Pokédex` Agent.json:
- Around line 75-79: The edge ID string for the connection between Agent-R27kt
and ChatOutput-lbrgJ embeds an outdated inputTypes list (includes "JSON" and
"Table") that no longer matches the targetHandle inputTypes
["Data","DataFrame","Message"]; update/regenerate the edge id value (the long
string beginning with xy-edge__Agent-R27kt{…}-ChatOutput-lbrgJ) so its embedded
metadata's inputTypes exactly mirror the targetHandle, and scan for any other
references to the old edge id to update them or confirm edge IDs are not relied
upon for strict matching.
In `@src/backend/base/langflow/initial_setup/starter_projects/Portfolio` Website
Code Generator.json:
- Around line 2345-2362: The starter template still uses the old wording "JSON /
Table" and "structured JSON" while the runtime now emits "Data" and "DataFrame";
update all user-facing copy in this JSON file to the new names: rename any input
label or help text that says "JSON" or "JSON or Table" to "Data" (or "Data
input") and change any occurrences of "structured JSON" to "structured
DataFrame" (or "structured Data") so they match the method name
build_structured_dataframe and the output node dataframe_output; search for
display_name, description, title, help_text, and any parser/input label strings
and replace accordingly.
In `@src/backend/base/langflow/initial_setup/starter_projects/Research`
Agent.json:
- Around line 186-202: The edge's serialized "id" is inconsistent with the
updated targetHandle.inputTypes; update the reactflow edge id string (the value
of "id" that begins with
"reactflow__edge-LanguageModelComponent-80mt4...-ChatOutput-gZuRk...") so it
encodes the current targetHandle inputTypes ["Data","DataFrame","Message"] (and
matches the sourceHandle payload for LanguageModelComponent-80mt4 and the target
ChatOutput-gZuRk) to avoid duplicate/recreated edges; ensure the "id",
"sourceHandle" and "targetHandle" serialized fragments are regenerated together
so all encoded type lists and handle ids (LanguageModelComponent-80mt4,
ChatOutput-gZuRk, output_types/message) stay consistent.
In `@src/backend/base/langflow/initial_setup/starter_projects/Search` agent.json:
- Around line 25-29: The serialized edge id string for the edge
"xy-edge__Agent-9JGgQ...-ChatOutput-Pygov" is out of sync with its narrowed
targetHandle (ChatOutput-Pygov) — it still lists JSON and Table in the embedded
inputTypes; update the edge "id" value to match the targetHandle's inputTypes
([Data, DataFrame, Message]) by removing JSON and Table so the embedded handle
in the id exactly mirrors the "targetHandle" field (ensure the same
fieldName/id/inputTypes/type tokens are used).
In `@src/backend/base/langflow/initial_setup/starter_projects/Simple` Agent.json:
- Around line 27-32: The edge ID string for the connection between Agent-oYRYa
and ChatOutput-z90NZ embeds stale handle metadata (sourceHandle includes
JSON/Table while targetHandle is narrowed to ["Data","DataFrame","Message"]);
regenerate the edge identifier and its serialized handle fields so they match
the actual targetHandle (remove JSON and Table from the serialized types) —
update the "id" value and the "sourceHandle"/"targetHandle" entries for the
Agent-oYRYa -> ChatOutput-z90NZ edge so all embedded handle/type lists are
consistent.
In `@src/backend/base/langflow/initial_setup/starter_projects/Social` Media
Agent.json:
- Around line 111-116: The serialized edge "id" is inconsistent with the updated
targetHandle inputTypes; update the edge id string that begins with
"reactflow__edge-Agent-0vMrI{…}-ChatOutput-Lgpwq{…}" so its embedded metadata
matches the sourceHandle/targetHandle values (Agent-0vMrI and ChatOutput-Lgpwq)
— specifically remove the now-removed JSON and Table types from the embedded
output_types/inputTypes in the id so it lists only Data, DataFrame, Message to
match sourceHandle and targetHandle.
In `@src/backend/base/langflow/initial_setup/starter_projects/Text` Sentiment
Analysis.json:
- Around line 111-116: The serialized edge objects contain stale IDs that embed
old inputTypes (e.g., the "id" field starting with
"reactflow__edge-LanguageModelComponent-ZLKtg...-ChatOutput-h5fAd") which no
longer match the updated targetHandle.inputTypes (now
["Data","DataFrame","Message"]); update/regenerate the edge IDs for these edges
so the embedded handle/type lists reflect the current sourceHandle/targetHandle
values (search for edges referencing LanguageModelComponent-ZLKtg and
ChatOutput-h5fAd and replace their "id" strings to match the current serialized
sourceHandle/targetHandle), and apply the same fix to the other occurrence noted
(the block around the second edge at the later lines).
---
Nitpick comments:
In `@src/backend/tests/unit/components/languagemodels/test_minimax.py`:
- Around line 25-28: The test is brittle because it reconstructs a Component
from the private MiniMaxModelComponent._code; instead, obtain the component's
public frontend node/template and pass that to build_custom_component_template.
Replace use of Component(_code=component._code) with the component's public API
(e.g., component.frontend_node or
component.build_frontend_node()/to_frontend_node()) and call
build_custom_component_template(frontend_node) using that value so the test
exercises the same frontend contract as the UI (references:
MiniMaxModelComponent, Component, build_custom_component_template,
frontend_node).
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f5ee8c7a-396d-4151-90c8-5049a5ae6536
📒 Files selected for processing (36)
src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Basic Prompting.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Blog Writer.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Document Q&A.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Financial Report Parser.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Hybrid Search RAG.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Market Research.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Memory Chatbot.jsonsrc/backend/base/langflow/initial_setup/starter_projects/News Aggregator.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Research Agent.jsonsrc/backend/base/langflow/initial_setup/starter_projects/SEO Keyword Generator.jsonsrc/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Search agent.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Simple Agent.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Social Media Agent.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Twitter Thread Generator.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.jsonsrc/backend/tests/unit/components/languagemodels/test_minimax.pysrc/frontend/src/icons/MiniMax/MiniMaxIcon.jsxsrc/frontend/src/icons/MiniMax/index.tsxsrc/frontend/src/icons/lazyIconImports.tssrc/lfx/src/lfx/components/__init__.pysrc/lfx/src/lfx/components/minimax/__init__.pysrc/lfx/src/lfx/components/minimax/minimax.py
| "title_case": false, | ||
| "type": "code", | ||
| "value": "from lfx.custom.custom_component.component import Component\nfrom lfx.helpers.data import safe_convert\nfrom lfx.inputs.inputs import BoolInput, HandleInput, MessageTextInput, MultilineInput, TabInput\nfrom lfx.schema.data import Data\nfrom lfx.schema.dataframe import DataFrame\nfrom lfx.schema.message import Message\nfrom lfx.template.field.base import Output\n\n\nclass ParserComponent(Component):\n display_name = \"Parser\"\n description = \"Extracts text using a template.\"\n documentation: str = \"https://docs.langflow.org/parser\"\n icon = \"braces\"\n\n inputs = [\n HandleInput(\n name=\"input_data\",\n display_name=\"JSON or Table\",\n input_types=[\"DataFrame\", \"Table\", \"Data\", \"JSON\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n # Use format_map with a dict that returns default_value for missing keys\n class DefaultDict(dict):\n def __missing__(self, key):\n return data.default_value or \"\"\n\n formatted_text = self.pattern.format_map(DefaultDict(data.data))\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([safe_convert(item, clean_data=self.clean_data or False) for item in self.input_data])\n else:\n result = safe_convert(self.input_data or False)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" | ||
| "value": "from lfx.custom.custom_component.component import Component\nfrom lfx.helpers.data import safe_convert\nfrom lfx.inputs.inputs import BoolInput, HandleInput, MessageTextInput, MultilineInput, TabInput\nfrom lfx.schema.data import Data\nfrom lfx.schema.dataframe import DataFrame\nfrom lfx.schema.message import Message\nfrom lfx.template.field.base import Output\n\n\nclass ParserComponent(Component):\n display_name = \"Parser\"\n description = \"Extracts text using a template.\"\n documentation: str = \"https://docs.langflow.org/parser\"\n icon = \"braces\"\n\n inputs = [\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n # Use format_map with a dict that returns default_value for missing keys\n class DefaultDict(dict):\n def __missing__(self, key):\n return data.default_value or \"\"\n\n formatted_text = self.pattern.format_map(DefaultDict(data.data))\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([safe_convert(item, clean_data=self.clean_data or False) for item in self.input_data])\n else:\n result = safe_convert(self.input_data or False)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== DataFrame implementation =="
fd -i 'dataframe.py' | xargs -r rg -n -C3 'class\s+DataFrame\b|__bool__|__nonzero__|pandas|pd\.DataFrame'
echo
echo "== Embedded/source Parser convert_to_string implementations =="
rg -n -C4 'def convert_to_string|safe_convert\(self\.input_data.*False|clean_data=self\.clean_data' --glob '*.py' --glob '*.json'Repository: langflow-ai/langflow
Length of output: 50379
Fix boolean-coercion logic in convert_to_string() method.
Line 143 uses safe_convert(self.input_data or False), which evaluates truthiness of self.input_data before conversion. This breaks Stringify mode for valid DataFrame-like inputs. Additionally, the dynamic clean_data field access uses self.clean_data or False instead of proper attribute checking.
The codebase already contains the correct pattern in ChatOutput (src/lfx/src/lfx/components/input_output/chat_output.py), which uses getattr(self, "clean_data", False) and passes the original object directly to safe_convert without boolean coercion.
Update the source ParserComponent and regenerate the starter JSON:
Suggested fix
def convert_to_string(self) -> Message:
"""Convert input data to string with proper error handling."""
result = ""
+ clean_data = getattr(self, "clean_data", False)
if isinstance(self.input_data, list):
- result = "\n".join([safe_convert(item, clean_data=self.clean_data or False) for item in self.input_data])
+ result = "\n".join([safe_convert(item, clean_data=clean_data) for item in self.input_data])
else:
- result = safe_convert(self.input_data or False)
+ result = safe_convert(self.input_data, clean_data=clean_data)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "value": "from lfx.custom.custom_component.component import Component\nfrom lfx.helpers.data import safe_convert\nfrom lfx.inputs.inputs import BoolInput, HandleInput, MessageTextInput, MultilineInput, TabInput\nfrom lfx.schema.data import Data\nfrom lfx.schema.dataframe import DataFrame\nfrom lfx.schema.message import Message\nfrom lfx.template.field.base import Output\n\n\nclass ParserComponent(Component):\n display_name = \"Parser\"\n description = \"Extracts text using a template.\"\n documentation: str = \"https://docs.langflow.org/parser\"\n icon = \"braces\"\n\n inputs = [\n HandleInput(\n name=\"input_data\",\n display_name=\"Data or DataFrame\",\n input_types=[\"DataFrame\", \"Data\"],\n info=\"Accepts either a DataFrame or a Data object.\",\n required=True,\n ),\n TabInput(\n name=\"mode\",\n display_name=\"Mode\",\n options=[\"Parser\", \"Stringify\"],\n value=\"Parser\",\n info=\"Convert into raw string instead of using a template.\",\n real_time_refresh=True,\n ),\n MultilineInput(\n name=\"pattern\",\n display_name=\"Template\",\n info=(\n \"Use variables within curly brackets to extract column values for DataFrames \"\n \"or key values for Data.\"\n \"For example: `Name: {Name}, Age: {Age}, Country: {Country}`\"\n ),\n value=\"Text: {text}\", # Example default\n dynamic=True,\n show=True,\n required=True,\n ),\n MessageTextInput(\n name=\"sep\",\n display_name=\"Separator\",\n advanced=True,\n value=\"\\n\",\n info=\"String used to separate rows/items.\",\n ),\n ]\n\n outputs = [\n Output(\n display_name=\"Parsed Text\",\n name=\"parsed_text\",\n info=\"Formatted text output.\",\n method=\"parse_combined_text\",\n ),\n ]\n\n def update_build_config(self, build_config, field_value, field_name=None):\n \"\"\"Dynamically hide/show `template` and enforce requirement based on `stringify`.\"\"\"\n if field_name == \"mode\":\n build_config[\"pattern\"][\"show\"] = self.mode == \"Parser\"\n build_config[\"pattern\"][\"required\"] = self.mode == \"Parser\"\n if field_value:\n clean_data = BoolInput(\n name=\"clean_data\",\n display_name=\"Clean Data\",\n info=(\n \"Enable to clean the data by removing empty rows and lines \"\n \"in each cell of the DataFrame/ Data object.\"\n ),\n value=True,\n advanced=True,\n required=False,\n )\n build_config[\"clean_data\"] = clean_data.to_dict()\n else:\n build_config.pop(\"clean_data\", None)\n\n return build_config\n\n def _clean_args(self):\n \"\"\"Prepare arguments based on input type.\"\"\"\n input_data = self.input_data\n\n match input_data:\n case list() if all(isinstance(item, Data) for item in input_data):\n msg = \"List of Data objects is not supported.\"\n raise ValueError(msg)\n case DataFrame():\n return input_data, None\n case Data():\n return None, input_data\n case dict() if \"data\" in input_data:\n try:\n if \"columns\" in input_data: # Likely a DataFrame\n return DataFrame.from_dict(input_data), None\n # Likely a Data object\n return None, Data(**input_data)\n except (TypeError, ValueError, KeyError) as e:\n msg = f\"Invalid structured input provided: {e!s}\"\n raise ValueError(msg) from e\n case _:\n msg = f\"Unsupported input type: {type(input_data)}. Expected DataFrame or Data.\"\n raise ValueError(msg)\n\n def parse_combined_text(self) -> Message:\n \"\"\"Parse all rows/items into a single text or convert input to string if `stringify` is enabled.\"\"\"\n # Early return for stringify option\n if self.mode == \"Stringify\":\n return self.convert_to_string()\n\n df, data = self._clean_args()\n\n lines = []\n if df is not None:\n for _, row in df.iterrows():\n formatted_text = self.pattern.format(**row.to_dict())\n lines.append(formatted_text)\n elif data is not None:\n # Use format_map with a dict that returns default_value for missing keys\n class DefaultDict(dict):\n def __missing__(self, key):\n return data.default_value or \"\"\n\n formatted_text = self.pattern.format_map(DefaultDict(data.data))\n lines.append(formatted_text)\n\n combined_text = self.sep.join(lines)\n self.status = combined_text\n return Message(text=combined_text)\n\n def convert_to_string(self) -> Message:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n result = \"\"\n if isinstance(self.input_data, list):\n result = \"\\n\".join([safe_convert(item, clean_data=self.clean_data or False) for item in self.input_data])\n else:\n result = safe_convert(self.input_data or False)\n self.log(f\"Converted to string with length: {len(result)}\")\n\n message = Message(text=result)\n self.status = message\n return message\n" | |
| def convert_to_string(self) -> Message: | |
| """Convert input data to string with proper error handling.""" | |
| result = "" | |
| clean_data = getattr(self, "clean_data", False) | |
| if isinstance(self.input_data, list): | |
| result = "\n".join([safe_convert(item, clean_data=clean_data) for item in self.input_data]) | |
| else: | |
| result = safe_convert(self.input_data, clean_data=clean_data) | |
| self.log(f"Converted to string with length: {len(result)}") | |
| message = Message(text=result) | |
| self.status = message | |
| return message |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/backend/base/langflow/initial_setup/starter_projects/Financial` Report
Parser.json at line 1442, The convert_to_string method wrongly coerces inputs
with "or False" and uses self.clean_data or False; update both usages to pass
the original object and use getattr to read the optional clean_data attribute:
in convert_to_string replace safe_convert(item, clean_data=self.clean_data or
False) with safe_convert(item, clean_data=getattr(self, "clean_data", False))
and replace safe_convert(self.input_data or False) with
safe_convert(self.input_data, clean_data=getattr(self, "clean_data", False));
ensure Message creation and self.status assignment remain the same.
| "display_name": "Dataframe", | ||
| "group_outputs": false, | ||
| "method": "retrieve_messages_dataframe", | ||
| "name": "dataframe", | ||
| "selected": "Table", | ||
| "selected": "DataFrame", | ||
| "tool_mode": true, | ||
| "types": [ | ||
| "Table" | ||
| "DataFrame" |
There was a problem hiding this comment.
Use DataFrame consistently in the Memory output label.
The type metadata was migrated to DataFrame, but the visible label is still Dataframe here and in the embedded component definition. That leaves the starter flow with a stale UI string after the rename.
Suggested fix
- "display_name": "Dataframe",
+ "display_name": "DataFrame",- Output(display_name="Dataframe", name="dataframe", method="retrieve_messages_dataframe", dynamic=True),
+ Output(display_name="DataFrame", name="dataframe", method="retrieve_messages_dataframe", dynamic=True),Also applies to: 1786-1786
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/backend/base/langflow/initial_setup/starter_projects/Meeting`
Summary.json around lines 1755 - 1762, The visible Memory output label
"display_name": "Dataframe" is inconsistent with the migrated type "DataFrame";
update the display_name (and any embedded component definition labels) to
"DataFrame" so the UI matches the metadata (look for entries with name:
"dataframe", method: "retrieve_messages_dataframe", selected: "DataFrame" and
change display_name from "Dataframe" to "DataFrame", also apply the same change
at the other occurrence around the embedded component definition referenced in
the diff).
| "display_name": "Dataframe", | ||
| "group_outputs": false, | ||
| "method": "retrieve_messages_dataframe", | ||
| "name": "dataframe", | ||
| "selected": "Table", | ||
| "selected": "DataFrame", | ||
| "tool_mode": true, | ||
| "types": [ | ||
| "Table" | ||
| "DataFrame" |
There was a problem hiding this comment.
Use DataFrame consistently for the Message History output label.
The output is now typed/selected as DataFrame, but the visible label is still Dataframe here and in the embedded component code. That leaves the starter-project UI inconsistent with the rest of the rename.
Also applies to: 992-992
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/backend/base/langflow/initial_setup/starter_projects/Memory` Chatbot.json
around lines 960 - 967, Replace the inconsistent lowercase label "Dataframe"
with the canonical "DataFrame" wherever the Message History output is defined
(e.g., the JSON property "display_name": "Dataframe" in the starter project and
any embedded component definitions tied to the node with "method":
"retrieve_messages_dataframe" and "name": "dataframe"); ensure the visible label
matches the "selected": "DataFrame" value and update the other occurrence noted
near the embedded component so both places use "DataFrame" exactly.
| "sourceHandle": "{\"dataType\": \"LanguageModelComponent\", \"id\": \"LanguageModelComponent-zY7m0\", \"name\": \"text_output\", \"output_types\": [\"Message\"]}", | ||
| "target": "ChatOutput-S7Bzs", | ||
| "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-S7Bzsœ, œinputTypesœ: [œDataœ, œJSONœ, œDataFrameœ, œTableœ, œMessageœ], œtypeœ: œstrœ}" | ||
| "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-S7Bzsœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" |
There was a problem hiding this comment.
Fix malformed serialized targetHandle payload.
Line [60] uses non-JSON delimiters (œ...œ) and is inconsistent with other escaped JSON handle payloads in this file. This can break downstream parsing of edge handle metadata.
Proposed fix
- "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-S7Bzsœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}"
+ "targetHandle": "{\"fieldName\": \"input_value\", \"id\": \"ChatOutput-S7Bzs\", \"inputTypes\": [\"Data\", \"DataFrame\", \"Message\"], \"type\": \"str\"}"📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-S7Bzsœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œstrœ}" | |
| "targetHandle": "{\"fieldName\": \"input_value\", \"id\": \"ChatOutput-S7Bzs\", \"inputTypes\": [\"Data\", \"DataFrame\", \"Message\"], \"type\": \"str\"}" |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/backend/base/langflow/initial_setup/starter_projects/SEO` Keyword
Generator.json at line 60, The targetHandle value is malformed using non-JSON
delimiters (œ) which breaks downstream parsing; locate the "targetHandle" entry
(contains "ChatOutput-S7Bzs", "œfieldNameœ", "œinput_valueœ") and replace the œ
delimiters with proper JSON-escaped double quotes so the value is a valid JSON
string (matching the other escaped JSON handle payloads in this file),
preserving the same keys ("fieldName", "id", "inputTypes", "type") and array
contents.
| "sourceHandle": "{œdataTypeœ: œAgentœ, œidœ: œAgent-X1iATœ, œnameœ: œresponseœ, œoutput_typesœ: [œMessageœ]}", | ||
| "target": "ChatOutput-gbqPo", | ||
| "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-gbqPoœ, œinputTypesœ: [œDataœ, œJSONœ, œDataFrameœ, œTableœ, œMessageœ], œtypeœ: œotherœ}" | ||
| "targetHandle": "{œfieldNameœ: œinput_valueœ, œidœ: œChatOutput-gbqPoœ, œinputTypesœ: [œDataœ, œDataFrameœ, œMessageœ], œtypeœ: œotherœ}" |
There was a problem hiding this comment.
Finish the ChatOutput alias migration or keep the legacy aliases for now.
This snapshot now narrows ChatOutput to ["Data", "DataFrame", "Message"], but the same template still serializes the old "JSON" / "Table" aliases elsewhere, e.g. the edge ID at Line 309 and YfinanceComponent.base_classes at Lines 2945-2950. Because starter projects embed component code directly, importing this flow creates a one-off ChatOutput contract that no longer matches the canonical src/lfx/src/lfx/components/input_output/chat_output.py, so rewiring the template can reject components that still advertise the legacy aliases. Please migrate the whole snapshot together or keep both alias sets accepted here for backward compatibility.
Also applies to: 3863-3863
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/backend/base/langflow/initial_setup/starter_projects/Sequential` Tasks
Agents.json at line 314, The ChatOutput alias usage in this snapshot is
inconsistent: the targetHandle and other serialized places (e.g., edge ID and
YfinanceComponent.base_classes) use the new narrowed set
["Data","DataFrame","Message"] while other parts still serialize legacy aliases
("JSON","Table"), causing runtime contract mismatch with
src/lfx/src/lfx/components/input_output/chat_output.py; fix by migrating the
entire snapshot to a consistent alias set or preserve backward compatibility by
including both sets wherever ChatOutput appears (update the "targetHandle"
entries, the edge ids, and YfinanceComponent.base_classes to either the new
canonical aliases or a combined array
["Data","DataFrame","Message","JSON","Table"] so the embedded components match
the canonical ChatOutput contract).
| def test_minimax_initialization(): | ||
| component = MiniMaxModelComponent() | ||
| assert component.display_name == "MiniMax" | ||
| assert component.description == "Generate text using MiniMax LLMs." | ||
| assert component.icon == "MiniMax" | ||
| assert component.name == "MiniMaxModel" | ||
|
|
||
|
|
||
| def test_minimax_default_models(): | ||
| assert "MiniMax-M2.7" in MINIMAX_MODELS | ||
| assert "MiniMax-M2.7-highspeed" in MINIMAX_MODELS | ||
| assert len(MINIMAX_MODELS) == 2 | ||
|
|
||
|
|
||
| def test_minimax_template(): | ||
| component = MiniMaxModelComponent() | ||
| comp = Component(_code=component._code) | ||
| frontend_node, _ = build_custom_component_template(comp) | ||
|
|
||
| assert isinstance(frontend_node, dict) | ||
| assert "template" in frontend_node | ||
|
|
||
| input_names = [inp["name"] for inp in frontend_node["template"].values() if isinstance(inp, dict)] | ||
| expected_inputs = [ | ||
| "max_tokens", | ||
| "model_kwargs", | ||
| "json_mode", | ||
| "model_name", | ||
| "base_url", | ||
| "api_key", | ||
| "temperature", | ||
| "seed", | ||
| ] | ||
| for input_name in expected_inputs: | ||
| assert input_name in input_names | ||
|
|
||
|
|
||
| @pytest.fixture | ||
| def mock_chat_openai(mocker): | ||
| return mocker.patch("lfx.components.minimax.minimax.ChatOpenAI") | ||
|
|
||
|
|
||
| @pytest.mark.parametrize( | ||
| ("temperature", "max_tokens"), | ||
| [ | ||
| (0.5, 100), | ||
| (1.0, 500), | ||
| (0.7, 1000), | ||
| ], | ||
| ) | ||
| def test_minimax_build_model(mock_chat_openai, temperature, max_tokens): | ||
| component = MiniMaxModelComponent() | ||
| component.temperature = temperature | ||
| component.max_tokens = max_tokens | ||
| component.api_key = "test-key" | ||
| component.model_name = "MiniMax-M2.7" | ||
| component.model_kwargs = {} | ||
| component.base_url = "https://api.minimax.io/v1" | ||
| component.seed = 1 | ||
| component.json_mode = False | ||
|
|
||
| mock_instance = MagicMock() | ||
| mock_chat_openai.return_value = mock_instance | ||
|
|
||
| model = component.build_model() | ||
|
|
||
| mock_chat_openai.assert_called_once_with( | ||
| max_tokens=max_tokens, | ||
| model_kwargs={}, | ||
| model="MiniMax-M2.7", | ||
| base_url="https://api.minimax.io/v1", | ||
| api_key="test-key", | ||
| temperature=temperature, | ||
| seed=1, | ||
| ) | ||
| assert model == mock_instance | ||
|
|
||
|
|
||
| def test_minimax_build_model_highspeed(mocker): | ||
| component = MiniMaxModelComponent() | ||
| component.temperature = 1.0 | ||
| component.max_tokens = 0 | ||
| component.api_key = "test-key" | ||
| component.model_name = "MiniMax-M2.7-highspeed" | ||
| component.model_kwargs = {} | ||
| component.base_url = "https://api.minimax.io/v1" | ||
| component.seed = 42 | ||
| component.json_mode = False | ||
|
|
||
| mock_chat_openai = mocker.patch("lfx.components.minimax.minimax.ChatOpenAI", return_value=MagicMock()) | ||
| component.build_model() | ||
| mock_chat_openai.assert_called_once_with( | ||
| max_tokens=None, | ||
| model_kwargs={}, | ||
| model="MiniMax-M2.7-highspeed", | ||
| base_url="https://api.minimax.io/v1", | ||
| api_key="test-key", | ||
| temperature=1.0, | ||
| seed=42, | ||
| ) | ||
|
|
||
|
|
||
| def test_minimax_temperature_zero_becomes_one(mocker): | ||
| """MiniMax requires temperature in (0.0, 1.0], so 0 should become 1.0.""" | ||
| component = MiniMaxModelComponent() | ||
| component.temperature = 0 | ||
| component.max_tokens = 100 | ||
| component.api_key = "test-key" | ||
| component.model_name = "MiniMax-M2.7" | ||
| component.model_kwargs = {} | ||
| component.base_url = "https://api.minimax.io/v1" | ||
| component.seed = 1 | ||
| component.json_mode = False | ||
|
|
||
| mock_chat_openai = mocker.patch("lfx.components.minimax.minimax.ChatOpenAI", return_value=MagicMock()) | ||
| component.build_model() | ||
| call_kwargs = mock_chat_openai.call_args[1] | ||
| assert call_kwargs["temperature"] == 1.0 | ||
|
|
||
|
|
||
| def test_minimax_temperature_none_becomes_one(mocker): | ||
| """MiniMax requires temperature in (0.0, 1.0], so None should become 1.0.""" | ||
| component = MiniMaxModelComponent() | ||
| component.temperature = None | ||
| component.max_tokens = 100 | ||
| component.api_key = "test-key" | ||
| component.model_name = "MiniMax-M2.7" | ||
| component.model_kwargs = {} | ||
| component.base_url = "https://api.minimax.io/v1" | ||
| component.seed = 1 | ||
| component.json_mode = False | ||
|
|
||
| mock_chat_openai = mocker.patch("lfx.components.minimax.minimax.ChatOpenAI", return_value=MagicMock()) | ||
| component.build_model() | ||
| call_kwargs = mock_chat_openai.call_args[1] | ||
| assert call_kwargs["temperature"] == 1.0 | ||
|
|
||
|
|
||
| def test_minimax_default_base_url_when_empty(mocker): | ||
| """When base_url is empty, should default to https://api.minimax.io/v1.""" | ||
| component = MiniMaxModelComponent() | ||
| component.temperature = 1.0 | ||
| component.max_tokens = 100 | ||
| component.api_key = "test-key" | ||
| component.model_name = "MiniMax-M2.7" | ||
| component.model_kwargs = {} | ||
| component.base_url = "" | ||
| component.seed = 1 | ||
| component.json_mode = False | ||
|
|
||
| mock_chat_openai = mocker.patch("lfx.components.minimax.minimax.ChatOpenAI", return_value=MagicMock()) | ||
| component.build_model() | ||
| call_kwargs = mock_chat_openai.call_args[1] | ||
| assert call_kwargs["base_url"] == "https://api.minimax.io/v1" | ||
|
|
||
|
|
||
| def test_minimax_json_mode(mocker): | ||
| component = MiniMaxModelComponent() | ||
| component.api_key = "test-key" | ||
| component.json_mode = True | ||
| component.temperature = 0.7 | ||
| component.max_tokens = 100 | ||
| component.model_name = "MiniMax-M2.7" | ||
| component.model_kwargs = {} | ||
| component.base_url = "https://api.minimax.io/v1" | ||
| component.seed = 1 | ||
|
|
||
| mock_instance = MagicMock() | ||
| mock_bound_instance = MagicMock() | ||
| mock_instance.bind.return_value = mock_bound_instance | ||
| mocker.patch("lfx.components.minimax.minimax.ChatOpenAI", return_value=mock_instance) | ||
|
|
||
| model = component.build_model() | ||
| mock_instance.bind.assert_called_once_with(response_format={"type": "json_object"}) | ||
| assert model == mock_bound_instance | ||
|
|
||
|
|
||
| def test_minimax_get_models_no_api_key(): | ||
| component = MiniMaxModelComponent() | ||
| component.api_key = None | ||
| models = component.get_models() | ||
| assert models == MINIMAX_MODELS | ||
|
|
||
|
|
||
| def test_minimax_get_models(mocker): | ||
| component = MiniMaxModelComponent() | ||
| mock_get = mocker.patch("requests.get") | ||
| mock_response = MagicMock() | ||
| mock_response.json.return_value = { | ||
| "data": [ | ||
| {"id": "MiniMax-M2.7"}, | ||
| {"id": "MiniMax-M2.7-highspeed"}, | ||
| ] | ||
| } | ||
| mock_get.return_value = mock_response | ||
|
|
||
| component.api_key = "test-key" | ||
| component.base_url = "https://api.minimax.io/v1" | ||
| models = component.get_models() | ||
| assert models == ["MiniMax-M2.7", "MiniMax-M2.7-highspeed"] | ||
| mock_get.assert_called_once_with( | ||
| "https://api.minimax.io/v1/models", | ||
| headers={"Authorization": "Bearer test-key", "Accept": "application/json"}, | ||
| timeout=10, | ||
| ) | ||
|
|
||
|
|
||
| def test_minimax_get_models_request_error(mocker): | ||
| import requests as req | ||
|
|
||
| component = MiniMaxModelComponent() | ||
| component.api_key = "test-key" | ||
| component.base_url = "https://api.minimax.io/v1" | ||
|
|
||
| mocker.patch("requests.get", side_effect=req.RequestException("Connection error")) | ||
| models = component.get_models() | ||
| assert models == MINIMAX_MODELS | ||
|
|
||
|
|
||
| def test_minimax_update_build_config(): | ||
| component = MiniMaxModelComponent() | ||
| build_config = {"model_name": {"options": []}} | ||
|
|
||
| updated = component.update_build_config(build_config, "test-key", "api_key") | ||
| assert "model_name" in updated | ||
|
|
||
| updated = component.update_build_config(build_config, "MiniMax-M2.7", "model_name") | ||
| assert "model_name" in updated | ||
|
|
||
|
|
||
| def test_minimax_error_handling(mock_chat_openai): | ||
| component = MiniMaxModelComponent() | ||
| component.api_key = "invalid-key" | ||
| component.model_name = "MiniMax-M2.7" | ||
| component.temperature = 1.0 | ||
| component.max_tokens = 100 | ||
| component.model_kwargs = {} | ||
| component.base_url = "https://api.minimax.io/v1" | ||
| component.seed = 1 | ||
| component.json_mode = False | ||
|
|
||
| mock_chat_openai.side_effect = Exception("Invalid API key") | ||
|
|
||
| with pytest.raises(Exception, match="Invalid API key"): | ||
| component.build_model() |
There was a problem hiding this comment.
🛠️ Refactor suggestion | 🟠 Major
Move this suite onto ComponentTestBaseWithoutClient.
These backend component tests are written as ad-hoc pytest functions, so they skip the repo’s required component_class, default_kwargs, and file_names_mapping fixtures and miss the standard version/backward-compat checks that come with the component test harness. As per coding guidelines, src/backend/tests/unit/components/**/*.py tests should inherit from the appropriate ComponentTestBase family and provide component_class, default_kwargs, and file_names_mapping fixtures.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/backend/tests/unit/components/languagemodels/test_minimax.py` around
lines 11 - 255, The test suite should be converted to use the standard component
test harness by creating a test class that inherits from
ComponentTestBaseWithoutClient and providing the required fixtures:
component_class (pointing to MiniMaxModelComponent), default_kwargs (a dict with
minimal valid kwargs like api_key, model_name, base_url, etc.), and
file_names_mapping (as required by the harness). Move the existing standalone
pytest functions into methods on that class (or keep them as module-level tests
that reuse the provided fixtures) and update any direct construction of
MiniMaxModelComponent() to rely on the component_class/default_kwargs fixtures
where appropriate; keep special-case tests (like get_models HTTP mocks,
json_mode, and error handling) but adapt them to use the harness fixtures and
ensure names reference MiniMaxModelComponent, build_model, get_models,
update_build_config, and MINIMAX_MODELS so the harness runs the standard
version/backward-compat checks.
| def test_minimax_update_build_config(): | ||
| component = MiniMaxModelComponent() | ||
| build_config = {"model_name": {"options": []}} | ||
|
|
||
| updated = component.update_build_config(build_config, "test-key", "api_key") | ||
| assert "model_name" in updated | ||
|
|
||
| updated = component.update_build_config(build_config, "MiniMax-M2.7", "model_name") | ||
| assert "model_name" in updated |
There was a problem hiding this comment.
test_minimax_update_build_config isn't asserting any behavior.
"model_name" already exists in build_config, so both assertions still pass if update_build_config() is a no-op. Build the config from to_frontend_node() and assert the expected option/value changes instead. As per coding guidelines, component build-config tests should call to_frontend_node() to get the node template and then verify the mutations made by update_build_config().
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/backend/tests/unit/components/languagemodels/test_minimax.py` around
lines 230 - 238, Replace the no-op assertions in
test_minimax_update_build_config with assertions that verify real mutations:
instantiate MiniMaxModelComponent, call its to_frontend_node() to obtain the
initial build_config/node template, then call
component.update_build_config(build_config, "test-key", "api_key") and assert
the specific option/value changes inside the returned config (e.g., that the
"api_key" option exists/was added under the correct model key and contains
"test-key"); repeat similarly for update_build_config(build_config,
"MiniMax-M2.7", "model_name") and assert the model_name option was set/updated
to "MiniMax-M2.7". Ensure you reference MiniMaxModelComponent,
to_frontend_node(), and update_build_config() when locating where to change the
test.
| height="90" | ||
| rx="18" | ||
| ry="18" | ||
| fill={props.isDark ? "#1a1a2e" : "#1a1a2e"} |
There was a problem hiding this comment.
isDark branch currently does not switch theme colors.
The fill color uses the same value for both modes, so dark-mode support is effectively inactive.
🎨 Suggested fix
- fill={props.isDark ? "#1a1a2e" : "#1a1a2e"}
+ fill={props.isDark ? "#1a1a2e" : "#f3f4f6"}
...
- fill="#ffffff"
+ fill={props.isDark ? "#ffffff" : "#1a1a2e"}As per coding guidelines: "In SVG components, use the isDark prop to switch between light and dark color schemes (e.g., fill={props.isDark ? "#ffffff" : "#0A0A0A"})."
Also applies to: 25-25
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/frontend/src/icons/MiniMax/MiniMaxIcon.jsx` at line 16, The SVG fill uses
the same color for both branches so dark mode never changes; update the
conditional in the MiniMaxIcon component (where it uses props.isDark) to choose
different colors for dark vs light (for example fill={props.isDark ? "#ffffff" :
"#0A0A0A"}), and apply the same fix to the second occurrence referenced (the
other fill at the same component), ensuring both places use distinct dark and
light hex values or design tokens.
| def get_models(self) -> list[str]: | ||
| """Return the list of available MiniMax models.""" | ||
| if not self.api_key: | ||
| return MINIMAX_MODELS | ||
|
|
||
| base_url = self.base_url or "https://api.minimax.io/v1" | ||
| url = f"{base_url}/models" | ||
| headers = {"Authorization": f"Bearer {self.api_key}", "Accept": "application/json"} | ||
|
|
||
| try: | ||
| response = requests.get(url, headers=headers, timeout=10) | ||
| response.raise_for_status() | ||
| data = response.json() | ||
| models = [model["id"] for model in data.get("data", [])] | ||
| return models if models else MINIMAX_MODELS | ||
| except requests.RequestException as e: | ||
| self.status = f"Error fetching models: {e}" | ||
| return MINIMAX_MODELS |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python - <<'PY'
from pydantic.v1 import SecretStr
secret = SecretStr("sk-test-123")
print("masked_header:", f"Bearer {secret}")
print("raw_header: ", f"Bearer {secret.get_secret_value()}")
PY
echo
echo "MiniMax implementation:"
sed -n '91,142p' src/lfx/src/lfx/components/minimax/minimax.py
echo
echo "Existing OpenAI sibling pattern:"
sed -n '91,140p' src/lfx/src/lfx/components/openai/openai.pyRepository: langflow-ai/langflow
Length of output: 2687
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check the class definition and field types
echo "=== MiniMax Component Class Definition ==="
head -n 90 src/lfx/src/lfx/components/minimax/minimax.py | tail -n 40
echo
echo "=== Full MiniMax Component (first 150 lines) ==="
head -n 150 src/lfx/src/lfx/components/minimax/minimax.py
echo
echo "=== Check imports in minimax.py ==="
head -n 20 src/lfx/src/lfx/components/minimax/minimax.pyRepository: langflow-ai/langflow
Length of output: 7031
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check if api_key is inherited and what type it is
echo "=== Base class LCModelComponent to understand api_key type ==="
fd -t f "model.py" src/lfx/src/lfx/base/ 2>/dev/null | head -5 | xargs ls -la
# Search for api_key field definition in base class
rg -A 3 "api_key.*:" src/lfx/src/lfx/base/ --max-count=10
echo
echo "=== Check OpenAI get_models() implementation ==="
sed -n '50,120p' src/lfx/src/lfx/components/openai/openai.py | grep -A 20 "def get_models"Repository: langflow-ai/langflow
Length of output: 10824
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check for Ruff TRY300 warning in the file
echo "=== Check for any Ruff comments or issues around lines 100-108 ==="
sed -n '95,110p' src/lfx/src/lfx/components/minimax/minimax.py
# Also check if there's a pyproject.toml or ruff config
echo
echo "=== Ruff configuration ==="
rg "TRY300\|bare-except" . --max-count=5 2>/dev/null || echo "No TRY300 references found"Repository: langflow-ai/langflow
Length of output: 813
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Find the complete OpenAI component to check get_models()
echo "=== OpenAI Component get_models() method ==="
rg -A 15 "def get_models" src/lfx/src/lfx/components/openai/openai.py
echo
echo "=== Check if OpenAI wraps api_key in Authorization header ==="
rg -B 5 -A 10 "Authorization.*Bearer" src/lfx/src/lfx/components/openai/openai.py || echo "No Bearer pattern found in OpenAI"Repository: langflow-ai/langflow
Length of output: 108
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Verify the exact type returned by get_secret_value()
python - <<'PY'
from pydantic.v1 import SecretStr
# Test what type self.api_key would be
class TestInput:
def __init__(self):
self.api_key = SecretStr("sk-test-123")
def test_direct_interpolation(self):
# This is what minimax.py line 98 does
header = f"Bearer {self.api_key}"
return header
def test_unwrapped(self):
# This is what build_model() does
api_key = SecretStr(self.api_key).get_secret_value() if self.api_key else None
header = f"Bearer {api_key}"
return header
t = TestInput()
print(f"Direct interpolation: {t.test_direct_interpolation()}")
print(f"After unwrap: {t.test_unwrapped()}")
print(f"Type of self.api_key: {type(t.api_key).__name__}")
PYRepository: langflow-ai/langflow
Length of output: 167
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Test the actual unwrap behavior more carefully
python - <<'PY'
from pydantic.v1 import SecretStr
class TestComponent:
def __init__(self):
self.api_key = SecretStr("sk-test-123")
def test_build_model_pattern(self):
# Mimics build_model() at line 126-127
api_key = self.api_key
api_key = SecretStr(api_key).get_secret_value() if api_key else None
return api_key
t = TestComponent()
result = t.test_build_model_pattern()
print(f"Result from build_model pattern: {result}")
print(f"Type: {type(result).__name__}")
# Now test in a header
header = f"Bearer {result}"
print(f"Header with result: {header}")
# Test direct get_secret_value()
header2 = f"Bearer {t.api_key.get_secret_value()}"
print(f"Header with get_secret_value(): {header2}")
PYRepository: langflow-ai/langflow
Length of output: 212
🏁 Script executed:
#!/bin/bash
set -euo pipefail
# Check if there's a parent class with api_key field definition
echo "=== Check LCModelComponent base class ==="
cat src/lfx/src/lfx/base/models/model.py | head -100Repository: langflow-ai/langflow
Length of output: 3929
Unwrap the API key before using it in network requests.
get_models() at line 98 interpolates self.api_key directly into the Authorization header. If this field is a Pydantic SecretStr, the string representation is masked, so the request sends Bearer ********** and silently falls back to MINIMAX_MODELS.
Additionally, build_model() at line 127 has a related issue: wrapping an already-SecretStr object in SecretStr() again doesn't unwrap it—SecretStr(api_key).get_secret_value() still returns a masked value. Call .get_secret_value() directly on the instance instead.
🔧 Proposed fix
def get_models(self) -> list[str]:
"""Return the list of available MiniMax models."""
- if not self.api_key:
+ api_key_value = self.api_key.get_secret_value() if isinstance(self.api_key, SecretStr) else self.api_key
+ if not api_key_value:
return MINIMAX_MODELS
base_url = self.base_url or "https://api.minimax.io/v1"
url = f"{base_url}/models"
- headers = {"Authorization": f"Bearer {self.api_key}", "Accept": "application/json"}
+ headers = {"Authorization": f"Bearer {api_key_value}", "Accept": "application/json"}
try:
response = requests.get(url, headers=headers, timeout=10)
def build_model(self) -> LanguageModel:
api_key = self.api_key
- api_key = SecretStr(api_key).get_secret_value() if api_key else None
+ api_key = api_key.get_secret_value() if isinstance(api_key, SecretStr) else api_key🧰 Tools
🪛 GitHub Actions: Ruff Style Check
[error] 105-105: ruff check failed (TRY300): Consider moving this statement to an else block.
🪛 GitHub Check: Ruff Style Check (3.13)
[failure] 105-105: Ruff (TRY300)
src/lfx/src/lfx/components/minimax/minimax.py:105:13: TRY300 Consider moving this statement to an else block
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/lfx/src/lfx/components/minimax/minimax.py` around lines 91 - 108, The
Authorization header is using a masked SecretStr instead of the real API key; in
get_models (and similarly in build_model) detect if self.api_key is a pydantic
SecretStr and call .get_secret_value() to unwrap it before interpolating into
headers (use isinstance(self.api_key, SecretStr) or similar), do not re-wrap an
already-SecretStr value with SecretStr()—always extract the raw string when
making network requests and then set headers={"Authorization": f"Bearer
{unwrapped_api_key}", ...}; update build_model to also unwrap any provided
api_key parameter via .get_secret_value() if it's a SecretStr.
| try: | ||
| response = requests.get(url, headers=headers, timeout=10) | ||
| response.raise_for_status() | ||
| data = response.json() | ||
| models = [model["id"] for model in data.get("data", [])] | ||
| return models if models else MINIMAX_MODELS | ||
| except requests.RequestException as e: | ||
| self.status = f"Error fetching models: {e}" | ||
| return MINIMAX_MODELS |
There was a problem hiding this comment.
Fix the Ruff TRY300 failure in get_models().
This block currently fails CI. Move the success-path return into an else block to satisfy Ruff without changing behavior.
🧹 Minimal fix
try:
response = requests.get(url, headers=headers, timeout=10)
response.raise_for_status()
data = response.json()
models = [model["id"] for model in data.get("data", [])]
- return models if models else MINIMAX_MODELS
except requests.RequestException as e:
self.status = f"Error fetching models: {e}"
return MINIMAX_MODELS
+ else:
+ return models if models else MINIMAX_MODELSAs per coding guidelines "Format Python code with ruff before linting; run make format_backend first before running lint checks".
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| try: | |
| response = requests.get(url, headers=headers, timeout=10) | |
| response.raise_for_status() | |
| data = response.json() | |
| models = [model["id"] for model in data.get("data", [])] | |
| return models if models else MINIMAX_MODELS | |
| except requests.RequestException as e: | |
| self.status = f"Error fetching models: {e}" | |
| return MINIMAX_MODELS | |
| try: | |
| response = requests.get(url, headers=headers, timeout=10) | |
| response.raise_for_status() | |
| data = response.json() | |
| models = [model["id"] for model in data.get("data", [])] | |
| except requests.RequestException as e: | |
| self.status = f"Error fetching models: {e}" | |
| return MINIMAX_MODELS | |
| else: | |
| return models if models else MINIMAX_MODELS |
🧰 Tools
🪛 GitHub Actions: Ruff Style Check
[error] 105-105: ruff check failed (TRY300): Consider moving this statement to an else block.
🪛 GitHub Check: Ruff Style Check (3.13)
[failure] 105-105: Ruff (TRY300)
src/lfx/src/lfx/components/minimax/minimax.py:105:13: TRY300 Consider moving this statement to an else block
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@src/lfx/src/lfx/components/minimax/minimax.py` around lines 100 - 108, In
get_models(), Ruff flags TRY300 because the try block contains a return; move
the success-path return out of the try by computing the response, parsing data
and building models inside the try (keeping response.raise_for_status()), then
add an else: block after the except to return models if present or
MINIMAX_MODELS; keep the except handling setting self.status and returning
MINIMAX_MODELS unchanged. Reference: function get_models, MINIMAX_MODELS,
requests.get, requests.RequestException, response.raise_for_status(), data =
response.json().
Summary
MiniMaxModelComponentwith OpenAI-compatible API (https://api.minimax.io/v1)MiniMax-M2.7(default) andMiniMax-M2.7-highspeedmodelsMINIMAX_API_KEYenvironment variable support(0.0, 1.0]as required by MiniMax API (defaults to1.0)API Reference
Test plan
src/backend/tests/unit/components/languagemodels/test_minimax.py)MiniMax-M2.7model responds correctly viaapi.minimax.io/v1DeepSeekandxAIcomponentsSummary by CodeRabbit
Release Notes
New Features
Improvements
Dependencies
Tests