fix: avoid updating Message if ChatOutput is connected to ChatInput#10586
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThis PR updates the ChatOutput component across all starter projects and the corresponding Python module to assign a unique UUID to message.id when processing an existing Message input. The changes include adding Changes
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes
Possibly related PRs
Suggested labels
Suggested reviewers
Pre-merge checks and finishing touches❌ Failed checks (1 error, 3 warnings)
✅ Passed checks (3 passed)
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: 7
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (5)
src/lfx/src/lfx/components/input_output/chat_output.py (1)
121-127: I need to gather more information about the Message class definition and verify which one is used in chat_output.py.Now I need to find the specific Message class definition used in chat_output.py and check the imports:
Based on my verification, the Message object extends the functionality of Data, and as a Pydantic model subclass, the model_copy() method allows models to be duplicated (with optional updates), which is particularly useful when working with frozen models.
The code at lines 121-127 directly mutates the
input_valueobject by creating a reference assignment (message = self.input_value) and then modifying its properties. Additionally, model_copy() returns a copy (by default, shallow copy) of the model, which should suffice for primitive field updates liketextandid.
Avoid mutating the input Message instance by creating a defensive copy.
The current code assigns
message = self.input_valueand then mutatesmessage.textandmessage.id, which modifies the original object. Ifinput_valueis reused elsewhere in the flow, this could cause unexpected behavior. Usemodel_copy()to create an independent instance:if isinstance(self.input_value, Message): message = self.input_value.model_copy() message.text = text message.id = uuid.uuid4() else: message = Message(text=text)The
idfield acceptsUUIDobjects natively, so no string conversion is needed.src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json (1)
468-474: Field name mismatch in field_order
field_orderlists "store_message" but the input is named "should_store_message". This can cause UI ordering issues or confusion.- "store_message", + "should_store_message",src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json (1)
589-700: Avoid mutating input Message and convert UUID to string for consistencyThe current code directly mutates
self.input_valueand assigns a UUID object instead of a string, creating two issues:
- Mutation side effect: Modifying
self.input_valuedirectly affects upstream references (history, caches). Deep-copy the Message before editing.- UUID type inconsistency: Assigning
uuid.uuid4()(UUID object) instead ofstr(uuid.uuid4())is inconsistent with the rest of the codebase (e.g.,memory/stubs.py:67uses string IDs).Apply this fix inside
ChatOutput.message_response:if isinstance(self.input_value, Message): - message = self.input_value - # Update message properties + # Avoid side effects on upstream references + message = self.input_value.model_copy(deep=True) message.text = text - message.id = uuid.uuid4() + message.id = str(uuid.uuid4()) else: message = Message(text=text)src/backend/base/langflow/initial_setup/starter_projects/Hybrid Search RAG.json (2)
803-906: Good fix; make ID JSON-safe and avoid mutating the input Message in place.Regenerating a new ID solves the overwrite bug. Two tweaks:
- Cast to str to avoid leaking a UUID object into JSON/db payloads.
- Don’t mutate the upstream Message; copy/update to prevent side effects.
Apply:
- if isinstance(self.input_value, Message): - message = self.input_value - # Update message properties - message.text = text - message.id = uuid.uuid4() + if isinstance(self.input_value, Message): + # Avoid mutating upstream instance; also ensure JSON-safe ID + message = self.input_value.copy(update={"text": text, "id": str(uuid.uuid4())}) else: message = Message(text=text)
912-940: isinstance with PEP 604 unions will raise at runtime.These checks use
Message | Data | ...insideisinstance, which is invalid and throwsTypeError. Use tuples:- if isinstance(self.input_value, list) and not all( - isinstance(item, Message | Data | DataFrame | str) for item in self.input_value - ): + ALLOWED_ITEM_TYPES = (Message, Data, DataFrame, str) + if isinstance(self.input_value, list) and not all(isinstance(item, ALLOWED_ITEM_TYPES) for item in self.input_value): ... - if not isinstance( - self.input_value, - Message | Data | DataFrame | str | list | Generator | type(None), - ): + ALLOWED_TYPES = (Message, Data, DataFrame, str, list, Generator, type(None)) + if not isinstance(self.input_value, ALLOWED_TYPES): ...
♻️ Duplicate comments (4)
src/backend/base/langflow/initial_setup/starter_projects/Social Media Agent.json (1)
1049-1049: Same fix as Portfolio template — apply string UUID and avoid in-place mutation.Mirror the prior suggestion:
- Use
message.id = str(uuid.uuid4()).- Clone the input Message before updating to prevent upstream side effects.
- message = self.input_value - message.text = text - message.id = uuid.uuid4() + message = ( + self.input_value.model_copy(deep=True) + if hasattr(self.input_value, "model_copy") + else Message(**getattr(self.input_value, "dict", lambda: {})()) + ) + message.text = text + message.id = str(uuid.uuid4())src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json (3)
433-506: Mirror the ID handling and immutability fix here as well.Same code path as in Hybrid Search RAG: cast UUID to str and copy the Message instead of mutating it in place.
See suggested diff in Hybrid Search RAG comment. Apply the same change here for consistency across starters.
506-540: isinstance with unions: same runtime TypeError risk.Replace
isinstance(item, Message | Data | ...)with tuples as shown in the previous file.
540-575: Generator-to-text handling: align with decision in the other file.Ensure
Message.textdoes not receive a Generator; coerce or stream properly.
🧹 Nitpick comments (15)
src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json (2)
383-383: Use tuple of types in isinstance checks for broader runtime compatibility.Within this code block,
isinstance(item, Message | Data | DataFrame | str)may raise TypeError on some Python versions. Use a tuple.Apply:
- if isinstance(self.input_value, list) and not all( - isinstance(item, Message | Data | DataFrame | str) for item in self.input_value - ): + if isinstance(self.input_value, list) and not all( + isinstance(item, (Message, Data, DataFrame, str)) for item in self.input_value + ): invalid_types = [ type(item).__name__ for item in self.input_value - if not isinstance(item, Message | Data | DataFrame | str) + if not isinstance(item, (Message, Data, DataFrame, str)) ]
383-383: Preserve traceability by storing previous ID when regenerating.Regenerating
idmutates the same Message instance; upstream references lose the original. Optionally capture it (e.g.,message.parent_id) for audit/debug.Example:
if isinstance(self.input_value, Message): message = self.input_value # Update message properties message.text = text - message.id = uuid.uuid4() + prev_id = getattr(message, "id", None) + message.id = str(uuid.uuid4()) + if prev_id and hasattr(message, "additional_kwargs"): + message.additional_kwargs = {**getattr(message, "additional_kwargs", {}), "parent_id": prev_id}src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json (2)
585-585: Prefer tuple in isinstance checks for compatibility.Mirror the same change to avoid potential TypeError.
Apply:
- if isinstance(self.input_value, list) and not all( - isinstance(item, Message | Data | DataFrame | str) for item in self.input_value - ): + if isinstance(self.input_value, list) and not all( + isinstance(item, (Message, Data, DataFrame, str)) for item in self.input_value + ): invalid_types = [ type(item).__name__ for item in self.input_value - if not isinstance(item, Message | Data | DataFrame | str) + if not isinstance(item, (Message, Data, DataFrame, str)) ]
585-585: Optional: keep original ID for lineage.Same optional enhancement as in the other file to help debugging.
- message.id = uuid.uuid4() + prev_id = getattr(message, "id", None) + message.id = str(uuid.uuid4()) + if prev_id and hasattr(message, "additional_kwargs"): + message.additional_kwargs = {**getattr(message, "additional_kwargs", {}), "parent_id": prev_id}src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json (1)
4193-4193: Consider creating a new Message instead of mutating the inbound object.Message doesn't define an
idfield—the assignment stores it in the underlying data dictionary. While Pydantic auto-serializes UUID to string in JSON mode, mutating the inbound Message can surprise upstream holders of that object. Either create a copy with a new ID or construct a fresh Message to avoid side effects.- message = self.input_value - # Update message properties - message.text = text - message.id = uuid.uuid4() + # Create a new message instead of mutating the input + message = Message( + text=text, + sender=self.input_value.sender, + sender_name=self.input_value.sender_name, + session_id=self.input_value.session_id, + # ... copy other fields ... + )src/backend/base/langflow/initial_setup/starter_projects/SEO Keyword Generator.json (1)
639-639: Same fix applies here: cast UUID to str and copy instead of mutating.Mirror the improvements from the other flow to keep behavior consistent across starters.
Apply the same diff in ChatOutput.message_response:
- if isinstance(self.input_value, Message): - message = self.input_value - # Update message properties - message.text = text - message.id = uuid.uuid4() + if isinstance(self.input_value, Message): + if hasattr(self.input_value, "model_copy"): + message = self.input_value.model_copy(update={"text": text, "id": str(uuid.uuid4())}) + else: + message = Message(**{k: v for k, v in self.input_value.__dict__.items() if k not in {"id", "text"}}, + text=text, id=str(uuid.uuid4()))Optional repo-wide verification (same as above) to confirm Message.id expectations.
src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json (1)
1730-1775: Simplify UUID handling by storing message IDs as stringsThe recommendation to cast
uuid.uuid4()to string is valid. While the current code functions correctly (the custom serializer converts UUIDs to strings for JSON output), storing IDs consistently as strings improves efficiency by avoiding unnecessary type conversions and ensures uniformity with the API response model, which declaresid: str | UUID | None.- message.id = uuid.uuid4() + message.id = str(uuid.uuid4())src/backend/base/langflow/initial_setup/starter_projects/Research Translation Loop.json (3)
480-481: Regenerate ID — cast to string for safetyThe fix is right; to avoid type/serialization surprises if
Message.idis a str field or JSON payload expects a string, cast the UUID:- message.id = uuid.uuid4() + message.id = str(uuid.uuid4())Also consider guarding generator inputs from
convert_to_string()before assignment (see note below).
480-481: Optional: avoid mutating upstream Message instanceTo prevent side effects on upstream nodes, create a new Message instead of mutating
self.input_valuein place. Keep if you rely on mutation semantics.
480-481: Handle Generator from convert_to_string
convert_to_stringmay return aGenerator. Assigning it tomessage.textcan break consumers. Consider branching:
- if str: set
message.text- if Generator: stream via your existing mechanism and set a placeholder text or skip setting
textuntil finalized.src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json (2)
554-555: Regenerate ID — cast to string for safetyGood fix. Recommend casting to string to match common
id: strschemas and ensure JSON-safe payloads:- message.id = uuid.uuid4() + message.id = str(uuid.uuid4())Also consider Generator handling as in the other file.
554-555: Optional: avoid mutating upstream Message instancePrefer cloning to avoid side effects on the input Message. Keep as-is if mutation is intentional.
src/backend/base/langflow/initial_setup/starter_projects/Knowledge Retrieval.json (1)
310-311: Regenerate ID — cast to string for safetyFix looks good. To avoid potential type mismatches or UUID JSON encoding surprises, cast to string:
- message.id = uuid.uuid4() + message.id = str(uuid.uuid4())Also consider handling Generator from
convert_to_string()before assigning tomessage.text.src/backend/base/langflow/initial_setup/starter_projects/Hybrid Search RAG.json (1)
940-975: Generator output may be assigned to Message.text. Verify or coerce.
convert_to_stringcan return aGenerator, butmessage.text = textassumes a string. IfMessage.textis not designed for streaming generators, coerce:- text = self.convert_to_string() + text = self.convert_to_string() + if isinstance(text, Generator): + # or handle streaming explicitly upstream + text = "".join(part for part in text)src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json (1)
575-575: Avoid mutating upstream Message instance (optional).To prevent side effects on callers holding the same object, consider creating a new
Messageand copying fields you need, instead of mutatingself.input_value.Example sketch:
- message = self.input_value - message.text = text - message.id = str(uuid.uuid4()) + src = self.input_value + message = Message(text=text) + message.id = str(uuid.uuid4()) + # copy fields you rely on, e.g.: + message.data = getattr(src, "data", None) + message.files = getattr(src, "files", None)
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (33)
src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Financial Report Parser.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Hybrid Search RAG.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment Analysis.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Invoice Summarizer.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Knowledge Retrieval.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Market Research.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.json(6 hunks)src/backend/base/langflow/initial_setup/starter_projects/Memory Chatbot.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Research Translation Loop.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/SEO Keyword Generator.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/SaaS Pricing.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Search agent.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Social Media Agent.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json(4 hunks)src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Twitter Thread Generator.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json(2 hunks)src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json(2 hunks)src/lfx/src/lfx/components/input_output/chat_output.py(2 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-06-26T19:43:18.260Z
Learnt from: ogabrielluiz
Repo: langflow-ai/langflow PR: 0
File: :0-0
Timestamp: 2025-06-26T19:43:18.260Z
Learning: In langflow custom components, the `module_name` parameter is now propagated through template building functions to add module metadata and code hashes to frontend nodes for better component tracking and debugging.
Applied to files:
src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.jsonsrc/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json
🔇 Additional comments (43)
src/lfx/src/lfx/components/input_output/chat_output.py (1)
5-5: Import looks good.The
uuidimport is correctly placed and necessary for generating unique message IDs.src/backend/base/langflow/initial_setup/starter_projects/Basic Prompting.json (1)
587-587: Metadata updates look correct.The
code_hashand embedded code updates properly reflect the changes made to the ChatOutput component in the Python source file.Also applies to: 661-661
src/backend/base/langflow/initial_setup/starter_projects/Price Deal Finder.json (1)
419-419: Metadata updates are consistent.The starter project configuration correctly reflects the ChatOutput component changes, with matching
code_hashand embedded code updates.Also applies to: 495-495
src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json (1)
329-329: LGTM on metadata update.code_hash bump is consistent with the embedded code change.
src/backend/base/langflow/initial_setup/starter_projects/Social Media Agent.json (1)
974-974: LGTM on metadata update.code_hash reflects the ChatOutput change.
src/backend/base/langflow/initial_setup/starter_projects/News Aggregator.json (2)
883-883: code_hash correctly updated to reflect ChatOutput component changes.The metadata hash has been updated, which is expected given the changes to the embedded ChatOutput component code.
958-958: UUID import and message ID regeneration fix properly implemented in ChatOutput.message_response.The fix correctly addresses the PR objective:
- Added
import uuidat the module level- When reusing an existing Message instance (
isinstance(self.input_value, Message)), the code now assignsmessage.id = uuid.uuid4()to ensure uniqueness- This prevents ID collisions between User and AI messages flowing through the component chain
The logic is sound: the message properties are updated (text, sender, session_id, etc.), and critically, a fresh UUID is generated to guarantee distinct message IDs in network payloads and UI rendering.
src/backend/base/langflow/initial_setup/starter_projects/Research Agent.json (3)
1720-1798: Fix correctly generates unique IDs when reusing Message instances.The implementation properly addresses the issue where User and AI messages could share IDs. When an existing Message is reused (line 1753:
message.id = uuid.uuid4()), a fresh UUID is generated before further processing, preventing ID collisions in the chat UI and network payloads.The logic flow is sound:
- Check if
input_valueis already a Message instance (line 1750)- If true, mutate the existing object with updated text and new ID (lines 1752-1753)
- If false, create a new Message (line 1755)
- Complete remaining properties setup downstream (lines 1758-1761)
1720-1730: UUID import is correctly positioned.The
import uuidstatement is added at line 1724 alongside other imports. The placement follows Python conventions and makes the standard library dependency explicit for this component.
1644-1644: Code hash metadata updated appropriately.The
code_hashvalue has been changed to "76077de62755" to reflect the logic modifications in the ChatOutput component's message_response method. This ensures the component's signature is correctly tracked for caching and versioning purposes.src/backend/base/langflow/initial_setup/starter_projects/Meeting Summary.json (1)
642-642: Consistent and correct update across all ChatOutput instances.All three ChatOutput component instances (ChatOutput-9KeOi, ChatOutput-iChI5, ChatOutput-R039P) have been properly updated with:
import uuidstatement at the top of the code- Logic to generate a fresh UUID when reusing an existing Message instance:
message.id = uuid.uuid4()- Consistent code_hash value "76077de62755" reflecting the changes
- Identical code implementations across all instances
The fix correctly addresses the PR objective of preventing message ID collisions by ensuring each message processed through ChatOutput receives a unique ID, even when the same Message object instance is reused along the component chain.
Also applies to: 718-718, 921-921, 997-997, 1200-1200, 1276-1276
src/backend/base/langflow/initial_setup/starter_projects/Sequential Tasks Agents.json (1)
4117-4117: code_hash bump acknowledged.Hash update aligns with the ChatOutput change (uuid import + new id assignment). No further action from this file.
Please confirm the same ChatOutput code (with UUID regeneration) and corresponding
code_hashupdates are applied consistently across other starter projects in this PR.src/backend/base/langflow/initial_setup/starter_projects/Search agent.json (2)
569-570: Code hash updated appropriately for ChatOutput implementation changes.The
code_hashhas been updated to reflect the addeduuidimport and the UUID regeneration logic inmessage_response(). This ensures consistency across the component versioning system.
629-683: Based on my verification of the codebase and the specific starter project structure:The review comment's concern does not apply to this starter project.
The Search agent.json flow has a linear architecture: ChatInput → intermediate nodes → ChatOutput (single terminal node). The Message object flows through once and reaches a single ChatOutput component. Since ChatOutput is the terminal/final component in the flow, the mutations to
message.textandmessage.idoccur at the end of processing with no downstream propagation. There is no scenario where the same Message object is passed to multiple nodes that would cause the unintended state changes described in the review.The underlying mutation pattern (directly modifying
self.input_valuewithout cloning) does exist in the code, but it is not problematic for this specific starter project's structure.src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json (2)
413-414: Code hash matches across starter projects (consistent implementation).Both starter projects (
Search agent.jsonandDocument Q&A.json) reference the samecode_hash("76077de62755"), confirming that ChatOutput implementations are synchronized and the UUID regeneration fix is uniformly applied.
488-489: Same UUID implementation as previous file—no duplicate concerns.This file's ChatOutput code is identical to the Search agent.json variant. The same verification regarding UUID type compatibility (UUID object vs. string) and message mutation side effects applies here. Both starter projects are correctly updated in lockstep.
src/backend/base/langflow/initial_setup/starter_projects/Instagram Copywriter.json (1)
1045-1045: Meta update acknowledged.code_hash change looks consistent with code edits; no action needed.
src/backend/base/langflow/initial_setup/starter_projects/SEO Keyword Generator.json (1)
565-565: Meta update acknowledged.code_hash reflects the code change; no further action.
src/backend/base/langflow/initial_setup/starter_projects/Pokédex Agent.json (2)
395-395: code_hash update OKHash reflects code changes; no concerns.
471-710: Assign string UUIDs to message.id to avoid type/serialization issuesIf Message.id is expected to be a string, assigning a UUID object can break JSON encoding and ID comparisons in UI/payloads. Use str(uuid.uuid4()).
Apply this diff inside ChatOutput.message_response:
- message.id = uuid.uuid4() + message.id = str(uuid.uuid4())src/backend/base/langflow/initial_setup/starter_projects/Basic Prompt Chaining.json (2)
635-635: code_hash update OKMatches underlying code change; all good.
709-710: Based on my investigation, I cannot fully verify the review comment because the Message schema is defined in message.py, but I couldn't access the exact type annotation for theidfield in the Message class.However, I can confirm the following:
JSON Serialization: In JSON mode, UUID instances are serialized as strings, and orjson serializes uuid.UUID instances to RFC 4122 format. The code uses both
jsonable_encoder()andorjson.dumps(), so technical serialization will work regardless.Type Consistency Patterns: The codebase shows explicit UUID-to-string conversion patterns in similar contexts, suggesting preference for type explicitness.
The concern about using
str(uuid.uuid4())is reasonable for ensuring consistent types, but whether it's critical depends on the actual type annotation ofMessage.id(whether it'sstr,UUID, orstr | UUID). Without access to that specific field definition, I cannot definitively confirm if this change is a type correctness issue or a best-practice recommendation.src/backend/base/langflow/initial_setup/starter_projects/Memory Chatbot.json (2)
426-426: Metadata-only changecode_hash update acknowledged. Nothing to review functionally.
500-731: Cast UUID to string to ensure consistent serialization and schema compatibilityThe code assigns
message.id = uuid.uuid4()which creates a UUID object. While Pydantic'sarbitrary_types_allowed=Truepermits this, the codebase pattern andMessageResponseschema (which prefersstr | UUID | None) indicate IDs should be serialized as strings for API compatibility and database operations.Apply the suggested cast:
- message.id = uuid.uuid4() + message.id = str(uuid.uuid4())Optionally, use
model_copy()to avoid mutating the upstream input object:- message = self.input_value - message.text = text - message.id = str(uuid.uuid4()) + base = self.input_value + message = base.model_copy(update={"text": text, "id": str(uuid.uuid4())})src/backend/base/langflow/initial_setup/starter_projects/Youtube Analysis.json (1)
1654-1654: Metadata-only changecode_hash update acknowledged. No functional impact.
src/backend/base/langflow/initial_setup/starter_projects/Research Translation Loop.json (1)
405-405: Metadata hash updateHash bump reflects code change; no concerns.
src/backend/base/langflow/initial_setup/starter_projects/Blog Writer.json (1)
480-480: Metadata hash updateHash bump is expected; no further action.
src/backend/base/langflow/initial_setup/starter_projects/Knowledge Retrieval.json (1)
235-235: Metadata hash updateAcknowledged.
src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json (1)
716-716: Consistent UUID regeneration applied to both ChatOutput nodes.Both ChatOutput instances now correctly import
uuidand assign a freshmessage.id = uuid.uuid4()when reusing an existing Message instance. The code_hash values ("76077de62755") are consistent across both nodes, confirming the changes are synchronized.The logic correctly handles message reuse: when
self.input_valueis already a Message object, it updates the text and regenerates the ID before setting other properties. This prevents ID collisions between User and AI messages.Also applies to: 791-791, 998-998, 1073-1073
src/backend/base/langflow/initial_setup/starter_projects/Custom Component Generator.json (2)
2240-2240: Code hash update notedHash reflects the ChatOutput change. No action needed.
2316-2629: Regenerate ID on reused Message — good fix; two hardening tweaksVerified: MessageResponse.id accepts str|UUID|None (src/lfx/src/lfx/schema/message.py) and the repo uses Pydantic v2 APIs (model_dump/model_copy present). Apply both hardening changes:
- Normalize id type: convert new id to str when the original id is a string (frontend expects string).
- Avoid mutating upstream Message: deep-copy (use model_copy(deep=True) when available, fallback to Message(**self.input_value.model_dump())).
Suggested patch (still relevant):
@@ async def message_response(self) -> Message: - if isinstance(self.input_value, Message): - message = self.input_value - # Update message properties - message.text = text - message.id = uuid.uuid4() + if isinstance(self.input_value, Message): + # Deep-copy to avoid mutating upstream instances + if hasattr(self.input_value, "model_copy"): # pydantic v2 + message = self.input_value.model_copy(deep=True) + else: + try: + message = Message(**self.input_value.model_dump()) + except Exception: + message = Message(text=str(self.input_value)) + # Update message properties and normalize id type + new_id = uuid.uuid4() + message.text = text + message.id = str(new_id) if isinstance(getattr(self.input_value, "id", ""), str) else new_idOptional (if streaming/generator inputs are possible):
- text = self.convert_to_string() + text = self.convert_to_string() + if isinstance(text, Generator): + text = "".join(list(text))src/backend/base/langflow/initial_setup/starter_projects/Simple Agent.json (1)
642-642: Code hash update notedHash change aligns with ChatOutput update.
src/backend/base/langflow/initial_setup/starter_projects/Financial Report Parser.json (3)
228-229: UUID generation fix correctly addresses message ID collision issue. The implementation properly generates a fresh UUID when reusing an existing Message instance, ensuring distinct User and AI messages with unique IDs. Themessage.id = uuid.uuid4()assignment in themessage_response()method (within theif isinstance(self.input_value, Message):block) directly resolves the root cause described in the PR objectives.
153-153: Code hash updated to reflect internal changes. The metadata code_hash has been updated from a previous value to"76077de62755", appropriately tracking the modifications to import statements and themessage_response()logic.
228-229: Generator handling is properly implemented and consistent.The code correctly imports
Generatorfromcollections.abc, validates it as an acceptable input type in_validate_input(), and handles it specifically inconvert_to_string()by returning it unchanged. The return type annotationstr | Generator[Any, None, None]confirms this is intentional. No inconsistencies between validation and method behavior were found.src/backend/base/langflow/initial_setup/starter_projects/Nvidia Remix.json (1)
514-514: Code hash update acknowledgedMetadata code_hash reflects the ChatOutput change. No concerns.
src/backend/base/langflow/initial_setup/starter_projects/Market Research.json (3)
479-479: Code hash correctly updated to reflect ChatOutput implementation changes.The hash has been updated from
4848ad3e35d5to76077de62755, properly documenting the changes to the ChatOutput component. This ensures the version tracking is consistent with the new UUID generation logic.
537-553: ChatOutput correctly implements fresh UUID generation for reused Message instances.The embedded Python code properly addresses the root cause of message ID collisions:
import uuidis correctly added at the top- The
message_responsemethod detects whenself.input_valueis already aMessageinstance- A fresh
message.id = uuid.uuid4()is assigned, preventing ID reuse- Other message properties (sender, sender_name, session_id, context_id, flow_id) are properly updated
This fix ensures User and AI messages receive unique IDs and will render as separate chat bubbles in the UI without overwriting each other.
447-707: Consistency verified across all starter project files.The verification confirms that all 32 starter project JSON files have been updated consistently. Each ChatOutput component includes the uuid import and the
message.id = uuid.uuid4()assignment without exception, ensuring uniform implementation and preventing regressions.src/backend/base/langflow/initial_setup/starter_projects/Twitter Thread Generator.json (2)
763-763: Message ID regeneration correctly implemented.The ChatOutput component now properly generates unique UUIDs for message IDs when reusing existing Message instances. The
uuidimport is correctly added, and the logic inmessage_response()properly assignsmessage.id = uuid.uuid4()before further processing. This addresses the root cause of message ID collisions that could cause one message to overwrite another in the UI.
688-688: Code hash updated appropriately.The metadata code_hash for the ChatOutput node has been updated to reflect the changes in the component implementation, maintaining consistency with the modified code.
src/backend/base/langflow/initial_setup/starter_projects/Travel Planning Agents.json (2)
501-501: Code hash bump looks good.Metadata reflects the behavioral change in ChatOutput.
575-575: Regenerate ID is correct; ensure ID type consistency.If
Message.idis a string elsewhere (common for storage/clients), set a string UUID to avoid type/serialization mismatches.Suggested tweak:
- message.id = uuid.uuid4() + message.id = str(uuid.uuid4())To verify the field type across the repo:
| "title_case": false, | ||
| "type": "code", | ||
| "value": "from collections.abc import Generator\nfrom typing import Any\n\nimport orjson\nfrom fastapi.encoders import jsonable_encoder\n\nfrom lfx.base.io.chat import ChatComponent\nfrom lfx.helpers.data import safe_convert\nfrom lfx.inputs.inputs import BoolInput, DropdownInput, HandleInput, MessageTextInput\nfrom lfx.schema.data import Data\nfrom lfx.schema.dataframe import DataFrame\nfrom lfx.schema.message import Message\nfrom lfx.schema.properties import Source\nfrom lfx.template.field.base import Output\nfrom lfx.utils.constants import (\n MESSAGE_SENDER_AI,\n MESSAGE_SENDER_NAME_AI,\n MESSAGE_SENDER_USER,\n)\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n documentation: str = \"https://docs.langflow.org/components-io#chat-output\"\n icon = \"MessagesSquare\"\n name = \"ChatOutput\"\n minimized = True\n\n inputs = [\n HandleInput(\n name=\"input_value\",\n display_name=\"Inputs\",\n info=\"Message to be passed as output.\",\n input_types=[\"Data\", \"DataFrame\", \"Message\"],\n required=True,\n ),\n BoolInput(\n name=\"should_store_message\",\n display_name=\"Store Messages\",\n info=\"Store the message in the history.\",\n value=True,\n advanced=True,\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],\n value=MESSAGE_SENDER_AI,\n advanced=True,\n info=\"Type of sender.\",\n ),\n MessageTextInput(\n name=\"sender_name\",\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=MESSAGE_SENDER_NAME_AI,\n advanced=True,\n ),\n MessageTextInput(\n name=\"session_id\",\n display_name=\"Session ID\",\n info=\"The session ID of the chat. If empty, the current session ID parameter will be used.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"context_id\",\n display_name=\"Context ID\",\n info=\"The context ID of the chat. Adds an extra layer to the local memory.\",\n value=\"\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n BoolInput(\n name=\"clean_data\",\n display_name=\"Basic Clean Data\",\n value=True,\n advanced=True,\n info=\"Whether to clean data before converting to string.\",\n ),\n ]\n outputs = [\n Output(\n display_name=\"Output Message\",\n name=\"message\",\n method=\"message_response\",\n ),\n ]\n\n def _build_source(self, id_: str | None, display_name: str | None, source: str | None) -> Source:\n source_dict = {}\n if id_:\n source_dict[\"id\"] = id_\n if display_name:\n source_dict[\"display_name\"] = display_name\n if source:\n # Handle case where source is a ChatOpenAI object\n if hasattr(source, \"model_name\"):\n source_dict[\"source\"] = source.model_name\n elif hasattr(source, \"model\"):\n source_dict[\"source\"] = str(source.model)\n else:\n source_dict[\"source\"] = str(source)\n return Source(**source_dict)\n\n async def message_response(self) -> Message:\n # First convert the input to string if needed\n text = self.convert_to_string()\n\n # Get source properties\n source, _, display_name, source_id = self.get_properties_from_source_component()\n\n # Create or use existing Message object\n if isinstance(self.input_value, Message):\n message = self.input_value\n # Update message properties\n message.text = text\n else:\n message = Message(text=text)\n\n # Set message properties\n message.sender = self.sender\n message.sender_name = self.sender_name\n message.session_id = self.session_id\n message.context_id = self.context_id\n message.flow_id = self.graph.flow_id if hasattr(self, \"graph\") else None\n message.properties.source = self._build_source(source_id, display_name, source)\n\n # Store message if needed\n if self.session_id and self.should_store_message:\n stored_message = await self.send_message(message)\n self.message.value = stored_message\n message = stored_message\n\n self.status = message\n return message\n\n def _serialize_data(self, data: Data) -> str:\n \"\"\"Serialize Data object to JSON string.\"\"\"\n # Convert data.data to JSON-serializable format\n serializable_data = jsonable_encoder(data.data)\n # Serialize with orjson, enabling pretty printing with indentation\n json_bytes = orjson.dumps(serializable_data, option=orjson.OPT_INDENT_2)\n # Convert bytes to string and wrap in Markdown code blocks\n return \"```json\\n\" + json_bytes.decode(\"utf-8\") + \"\\n```\"\n\n def _validate_input(self) -> None:\n \"\"\"Validate the input data and raise ValueError if invalid.\"\"\"\n if self.input_value is None:\n msg = \"Input data cannot be None\"\n raise ValueError(msg)\n if isinstance(self.input_value, list) and not all(\n isinstance(item, Message | Data | DataFrame | str) for item in self.input_value\n ):\n invalid_types = [\n type(item).__name__\n for item in self.input_value\n if not isinstance(item, Message | Data | DataFrame | str)\n ]\n msg = f\"Expected Data or DataFrame or Message or str, got {invalid_types}\"\n raise TypeError(msg)\n if not isinstance(\n self.input_value,\n Message | Data | DataFrame | str | list | Generator | type(None),\n ):\n type_name = type(self.input_value).__name__\n msg = f\"Expected Data or DataFrame or Message or str, Generator or None, got {type_name}\"\n raise TypeError(msg)\n\n def convert_to_string(self) -> str | Generator[Any, None, None]:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n self._validate_input()\n if isinstance(self.input_value, list):\n clean_data: bool = getattr(self, \"clean_data\", False)\n return \"\\n\".join([safe_convert(item, clean_data=clean_data) for item in self.input_value])\n if isinstance(self.input_value, Generator):\n return self.input_value\n return safe_convert(self.input_value)\n" | ||
| "value": "from collections.abc import Generator\nfrom typing import Any\n\nimport orjson\nimport uuid\nfrom fastapi.encoders import jsonable_encoder\n\nfrom lfx.base.io.chat import ChatComponent\nfrom lfx.helpers.data import safe_convert\nfrom lfx.inputs.inputs import BoolInput, DropdownInput, HandleInput, MessageTextInput\nfrom lfx.schema.data import Data\nfrom lfx.schema.dataframe import DataFrame\nfrom lfx.schema.message import Message\nfrom lfx.schema.properties import Source\nfrom lfx.template.field.base import Output\nfrom lfx.utils.constants import (\n MESSAGE_SENDER_AI,\n MESSAGE_SENDER_NAME_AI,\n MESSAGE_SENDER_USER,\n)\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n documentation: str = \"https://docs.langflow.org/components-io#chat-output\"\n icon = \"MessagesSquare\"\n name = \"ChatOutput\"\n minimized = True\n\n inputs = [\n HandleInput(\n name=\"input_value\",\n display_name=\"Inputs\",\n info=\"Message to be passed as output.\",\n input_types=[\"Data\", \"DataFrame\", \"Message\"],\n required=True,\n ),\n BoolInput(\n name=\"should_store_message\",\n display_name=\"Store Messages\",\n info=\"Store the message in the history.\",\n value=True,\n advanced=True,\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],\n value=MESSAGE_SENDER_AI,\n advanced=True,\n info=\"Type of sender.\",\n ),\n MessageTextInput(\n name=\"sender_name\",\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=MESSAGE_SENDER_NAME_AI,\n advanced=True,\n ),\n MessageTextInput(\n name=\"session_id\",\n display_name=\"Session ID\",\n info=\"The session ID of the chat. If empty, the current session ID parameter will be used.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"context_id\",\n display_name=\"Context ID\",\n info=\"The context ID of the chat. Adds an extra layer to the local memory.\",\n value=\"\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n BoolInput(\n name=\"clean_data\",\n display_name=\"Basic Clean Data\",\n value=True,\n advanced=True,\n info=\"Whether to clean data before converting to string.\",\n ),\n ]\n outputs = [\n Output(\n display_name=\"Output Message\",\n name=\"message\",\n method=\"message_response\",\n ),\n ]\n\n def _build_source(self, id_: str | None, display_name: str | None, source: str | None) -> Source:\n source_dict = {}\n if id_:\n source_dict[\"id\"] = id_\n if display_name:\n source_dict[\"display_name\"] = display_name\n if source:\n # Handle case where source is a ChatOpenAI object\n if hasattr(source, \"model_name\"):\n source_dict[\"source\"] = source.model_name\n elif hasattr(source, \"model\"):\n source_dict[\"source\"] = str(source.model)\n else:\n source_dict[\"source\"] = str(source)\n return Source(**source_dict)\n\n async def message_response(self) -> Message:\n # First convert the input to string if needed\n text = self.convert_to_string()\n\n # Get source properties\n source, _, display_name, source_id = self.get_properties_from_source_component()\n\n # Create or use existing Message object\n if isinstance(self.input_value, Message):\n message = self.input_value\n # Update message properties\n message.text = text\n message.id = uuid.uuid4()\n else:\n message = Message(text=text)\n\n # Set message properties\n message.sender = self.sender\n message.sender_name = self.sender_name\n message.session_id = self.session_id\n message.context_id = self.context_id\n message.flow_id = self.graph.flow_id if hasattr(self, \"graph\") else None\n message.properties.source = self._build_source(source_id, display_name, source)\n\n # Store message if needed\n if self.session_id and self.should_store_message:\n stored_message = await self.send_message(message)\n self.message.value = stored_message\n message = stored_message\n\n self.status = message\n return message\n\n def _serialize_data(self, data: Data) -> str:\n \"\"\"Serialize Data object to JSON string.\"\"\"\n # Convert data.data to JSON-serializable format\n serializable_data = jsonable_encoder(data.data)\n # Serialize with orjson, enabling pretty printing with indentation\n json_bytes = orjson.dumps(serializable_data, option=orjson.OPT_INDENT_2)\n # Convert bytes to string and wrap in Markdown code blocks\n return \"```json\\n\" + json_bytes.decode(\"utf-8\") + \"\\n```\"\n\n def _validate_input(self) -> None:\n \"\"\"Validate the input data and raise ValueError if invalid.\"\"\"\n if self.input_value is None:\n msg = \"Input data cannot be None\"\n raise ValueError(msg)\n if isinstance(self.input_value, list) and not all(\n isinstance(item, Message | Data | DataFrame | str) for item in self.input_value\n ):\n invalid_types = [\n type(item).__name__\n for item in self.input_value\n if not isinstance(item, Message | Data | DataFrame | str)\n ]\n msg = f\"Expected Data or DataFrame or Message or str, got {invalid_types}\"\n raise TypeError(msg)\n if not isinstance(\n self.input_value,\n Message | Data | DataFrame | str | list | Generator | type(None),\n ):\n type_name = type(self.input_value).__name__\n msg = f\"Expected Data or DataFrame or Message or str, Generator or None, got {type_name}\"\n raise TypeError(msg)\n\n def convert_to_string(self) -> str | Generator[Any, None, None]:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n self._validate_input()\n if isinstance(self.input_value, list):\n clean_data: bool = getattr(self, \"clean_data\", False)\n return \"\\n\".join([safe_convert(item, clean_data=clean_data) for item in self.input_value])\n if isinstance(self.input_value, Generator):\n return self.input_value\n return safe_convert(self.input_value)\n" |
There was a problem hiding this comment.
🧩 Analysis chain
Ensure regenerated ID is a string for consistency across storage, UI, and payloads.
Same pattern here: assign str(uuid.uuid4()) instead of a UUID object.
Apply:
- message.id = uuid.uuid4()
+ message.id = str(uuid.uuid4())To verify consistency across all starter projects:
🏁 Script executed:
#!/bin/bash
# Count sites still using raw UUIDs
rg -nP 'message\.id\s*=\s*uuid\.uuid4\(\)' src/backend/base/langflow/initial_setup/starter_projects | sortLength of output: 259253
Fix UUID ID assignment across all starter project templates
The issue extends beyond Image Sentiment Analysis.json. The search confirms message.id = uuid.uuid4() appears in 32 starter project files. Apply this fix consistently:
- message.id = uuid.uuid4()
+ message.id = str(uuid.uuid4())Affected files:
- Basic Prompt Chaining.json:709
- Basic Prompting.json:661
- Blog Writer.json:554
- Custom Component Generator.json:2316
- Document Q&A.json:488
- Financial Report Parser.json:229
- Hybrid Search RAG.json:803
- Image Sentiment Analysis.json:585
- Instagram Copywriter.json:1119
- Invoice Summarizer.json:383
- Knowledge Retrieval.json:310
- Market Research.json:553
- Meeting Summary.json:718, 997, 1276
- Memory Chatbot.json:500
- News Aggregator.json:958
- Nvidia Remix.json:589
- Pokédex Agent.json:471
- Portfolio Website Code Generator.json:405
- Price Deal Finder.json:495
- Research Agent.json:1720
- Research Translation Loop.json:480
- SEO Keyword Generator.json:639
- SaaS Pricing.json:448
- Search agent.json:645
- Sequential Tasks Agents.json:4193
- Simple Agent.json:718
- Social Media Agent.json:1049
- Text Sentiment Analysis.json:791, 1073
- Travel Planning Agents.json:575
- Twitter Thread Generator.json:763
- Vector Store RAG.json:1140
- Youtube Analysis.json:1730
📝 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 collections.abc import Generator\nfrom typing import Any\n\nimport orjson\nimport uuid\nfrom fastapi.encoders import jsonable_encoder\n\nfrom lfx.base.io.chat import ChatComponent\nfrom lfx.helpers.data import safe_convert\nfrom lfx.inputs.inputs import BoolInput, DropdownInput, HandleInput, MessageTextInput\nfrom lfx.schema.data import Data\nfrom lfx.schema.dataframe import DataFrame\nfrom lfx.schema.message import Message\nfrom lfx.schema.properties import Source\nfrom lfx.template.field.base import Output\nfrom lfx.utils.constants import (\n MESSAGE_SENDER_AI,\n MESSAGE_SENDER_NAME_AI,\n MESSAGE_SENDER_USER,\n)\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n documentation: str = \"https://docs.langflow.org/components-io#chat-output\"\n icon = \"MessagesSquare\"\n name = \"ChatOutput\"\n minimized = True\n\n inputs = [\n HandleInput(\n name=\"input_value\",\n display_name=\"Inputs\",\n info=\"Message to be passed as output.\",\n input_types=[\"Data\", \"DataFrame\", \"Message\"],\n required=True,\n ),\n BoolInput(\n name=\"should_store_message\",\n display_name=\"Store Messages\",\n info=\"Store the message in the history.\",\n value=True,\n advanced=True,\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],\n value=MESSAGE_SENDER_AI,\n advanced=True,\n info=\"Type of sender.\",\n ),\n MessageTextInput(\n name=\"sender_name\",\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=MESSAGE_SENDER_NAME_AI,\n advanced=True,\n ),\n MessageTextInput(\n name=\"session_id\",\n display_name=\"Session ID\",\n info=\"The session ID of the chat. If empty, the current session ID parameter will be used.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"context_id\",\n display_name=\"Context ID\",\n info=\"The context ID of the chat. Adds an extra layer to the local memory.\",\n value=\"\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n BoolInput(\n name=\"clean_data\",\n display_name=\"Basic Clean Data\",\n value=True,\n advanced=True,\n info=\"Whether to clean data before converting to string.\",\n ),\n ]\n outputs = [\n Output(\n display_name=\"Output Message\",\n name=\"message\",\n method=\"message_response\",\n ),\n ]\n\n def _build_source(self, id_: str | None, display_name: str | None, source: str | None) -> Source:\n source_dict = {}\n if id_:\n source_dict[\"id\"] = id_\n if display_name:\n source_dict[\"display_name\"] = display_name\n if source:\n # Handle case where source is a ChatOpenAI object\n if hasattr(source, \"model_name\"):\n source_dict[\"source\"] = source.model_name\n elif hasattr(source, \"model\"):\n source_dict[\"source\"] = str(source.model)\n else:\n source_dict[\"source\"] = str(source)\n return Source(**source_dict)\n\n async def message_response(self) -> Message:\n # First convert the input to string if needed\n text = self.convert_to_string()\n\n # Get source properties\n source, _, display_name, source_id = self.get_properties_from_source_component()\n\n # Create or use existing Message object\n if isinstance(self.input_value, Message):\n message = self.input_value\n # Update message properties\n message.text = text\n message.id = uuid.uuid4()\n else:\n message = Message(text=text)\n\n # Set message properties\n message.sender = self.sender\n message.sender_name = self.sender_name\n message.session_id = self.session_id\n message.context_id = self.context_id\n message.flow_id = self.graph.flow_id if hasattr(self, \"graph\") else None\n message.properties.source = self._build_source(source_id, display_name, source)\n\n # Store message if needed\n if self.session_id and self.should_store_message:\n stored_message = await self.send_message(message)\n self.message.value = stored_message\n message = stored_message\n\n self.status = message\n return message\n\n def _serialize_data(self, data: Data) -> str:\n \"\"\"Serialize Data object to JSON string.\"\"\"\n # Convert data.data to JSON-serializable format\n serializable_data = jsonable_encoder(data.data)\n # Serialize with orjson, enabling pretty printing with indentation\n json_bytes = orjson.dumps(serializable_data, option=orjson.OPT_INDENT_2)\n # Convert bytes to string and wrap in Markdown code blocks\n return \"```json\\n\" + json_bytes.decode(\"utf-8\") + \"\\n```\"\n\n def _validate_input(self) -> None:\n \"\"\"Validate the input data and raise ValueError if invalid.\"\"\"\n if self.input_value is None:\n msg = \"Input data cannot be None\"\n raise ValueError(msg)\n if isinstance(self.input_value, list) and not all(\n isinstance(item, Message | Data | DataFrame | str) for item in self.input_value\n ):\n invalid_types = [\n type(item).__name__\n for item in self.input_value\n if not isinstance(item, Message | Data | DataFrame | str)\n ]\n msg = f\"Expected Data or DataFrame or Message or str, got {invalid_types}\"\n raise TypeError(msg)\n if not isinstance(\n self.input_value,\n Message | Data | DataFrame | str | list | Generator | type(None),\n ):\n type_name = type(self.input_value).__name__\n msg = f\"Expected Data or DataFrame or Message or str, Generator or None, got {type_name}\"\n raise TypeError(msg)\n\n def convert_to_string(self) -> str | Generator[Any, None, None]:\n \"\"\"Convert input data to string with proper error handling.\"\"\"\n self._validate_input()\n if isinstance(self.input_value, list):\n clean_data: bool = getattr(self, \"clean_data\", False)\n return \"\\n\".join([safe_convert(item, clean_data=clean_data) for item in self.input_value])\n if isinstance(self.input_value, Generator):\n return self.input_value\n return safe_convert(self.input_value)\n" | |
| "value": "from collections.abc import Generator\nfrom typing import Any\n\nimport orjson\nimport uuid\nfrom fastapi.encoders import jsonable_encoder\n\nfrom lfx.base.io.chat import ChatComponent\nfrom lfx.helpers.data import safe_convert\nfrom lfx.inputs.inputs import BoolInput, DropdownInput, HandleInput, MessageTextInput\nfrom lfx.schema.data import Data\nfrom lfx.schema.dataframe import DataFrame\nfrom lfx.schema.message import Message\nfrom lfx.schema.properties import Source\nfrom lfx.template.field.base import Output\nfrom lfx.utils.constants import (\n MESSAGE_SENDER_AI,\n MESSAGE_SENDER_NAME_AI,\n MESSAGE_SENDER_USER,\n)\n\n\nclass ChatOutput(ChatComponent):\n display_name = \"Chat Output\"\n description = \"Display a chat message in the Playground.\"\n documentation: str = \"https://docs.langflow.org/components-io#chat-output\"\n icon = \"MessagesSquare\"\n name = \"ChatOutput\"\n minimized = True\n\n inputs = [\n HandleInput(\n name=\"input_value\",\n display_name=\"Inputs\",\n info=\"Message to be passed as output.\",\n input_types=[\"Data\", \"DataFrame\", \"Message\"],\n required=True,\n ),\n BoolInput(\n name=\"should_store_message\",\n display_name=\"Store Messages\",\n info=\"Store the message in the history.\",\n value=True,\n advanced=True,\n ),\n DropdownInput(\n name=\"sender\",\n display_name=\"Sender Type\",\n options=[MESSAGE_SENDER_AI, MESSAGE_SENDER_USER],\n value=MESSAGE_SENDER_AI,\n advanced=True,\n info=\"Type of sender.\",\n ),\n MessageTextInput(\n name=\"sender_name\",\n display_name=\"Sender Name\",\n info=\"Name of the sender.\",\n value=MESSAGE_SENDER_NAME_AI,\n advanced=True,\n ),\n MessageTextInput(\n name=\"session_id\",\n display_name=\"Session ID\",\n info=\"The session ID of the chat. If empty, the current session ID parameter will be used.\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"context_id\",\n display_name=\"Context ID\",\n info=\"The context ID of the chat. Adds an extra layer to the local memory.\",\n value=\"\",\n advanced=True,\n ),\n MessageTextInput(\n name=\"data_template\",\n display_name=\"Data Template\",\n value=\"{text}\",\n advanced=True,\n info=\"Template to convert Data to Text. If left empty, it will be dynamically set to the Data's text key.\",\n ),\n BoolInput(\n name=\"clean_data\",\n display_name=\"Basic Clean Data\",\n value=True,\n advanced=True,\n info=\"Whether to clean data before converting to string.\",\n ),\n ]\n outputs = [\n Output(\n display_name=\"Output Message\",\n name=\"message\",\n method=\"message_response\",\n ),\n ]\n\n def _build_source(self, id_: str | None, display_name: str | None, source: str | None) -> Source:\n source_dict = {}\n if id_:\n source_dict[\"id\"] = id_\n if display_name:\n source_dict[\"display_name\"] = display_name\n if source:\n # Handle case where source is a ChatOpenAI object\n if hasattr(source, \"model_name\"):\n source_dict[\"source\"] = source.model_name\n elif hasattr(source, \"model\"):\n source_dict[\"source\"] = str(source.model)\n else:\n source_dict[\"source\"] = str(source)\n return Source(**source_dict)\n\n async def message_response(self) -> Message:\n # First convert the input to string if needed\n text = self.convert_to_string()\n\n # Get source properties\n source, _, display_name, source_id = self.get_properties_from_source_component()\n\n # Create or use existing Message object\n if isinstance(self.input_value, Message):\n message = self.input_value\n # Update message properties\n message.text = text\n message.id = str(uuid.uuid4())\n else:\n message = Message(text=text)\n\n # Set message properties\n message.sender = self.sender\n message.sender_name = self.sender_name\n message.session_id = self.session_id\n message.context_id = self.context_id\n message.flow_id = self.graph.flow_id if hasattr(self, \"graph\") else None\n message.properties.source = self._build_source(source_id, display_name, source)\n\n # Store message if needed\n if self.session_id and self.should_store_message:\n stored_message = await self.send_message(message)\n self.message.value = stored_message\n message = stored_message\n\n self.status = message\n return message\n\n def _serialize_data(self, data: Data) -> str:\n \"\"\"Serialize Data object to JSON string.\"\"\"\n # Convert data.data to JSON-serializable format\n serializable_data = jsonable_encoder(data.data)\n # Serialize with orjson, enabling pretty printing with indentation\n json_bytes = orjson.dumps(serializable_data, option=orjson.OPT_INDENT_2)\n # Convert bytes to string and wrap in Markdown code blocks\n return \" |
🤖 Prompt for AI Agents
In src/backend/base/langflow/initial_setup/starter_projects/Image Sentiment
Analysis.json around line 585, the code sets message.id = uuid.uuid4() which
assigns a UUID object where a string ID is expected; change it to assign a
string (e.g., message.id = str(uuid.uuid4())). Apply the same replacement
(uuid.uuid4() -> str(uuid.uuid4())) for the identical occurrences across all
listed starter project JSON files to ensure consistent string IDs.
1cfa90a to
cc8229f
Compare
Codecov Report❌ Patch coverage is
❌ Your project status has failed because the head coverage (40.22%) is below the target coverage (60.00%). You can increase the head coverage or adjust the target coverage. Additional details and impacted files@@ Coverage Diff @@
## main #10586 +/- ##
==========================================
+ Coverage 32.38% 32.40% +0.01%
==========================================
Files 1366 1366
Lines 62943 62953 +10
Branches 9304 9305 +1
==========================================
+ Hits 20387 20397 +10
+ Misses 41532 41528 -4
- Partials 1024 1028 +4
Flags with carried forward coverage won't be shown. Click here to find out more.
🚀 New features to boost your workflow:
|
a7f0797 to
1412fb7
Compare
0cb4013 to
4384ee2
Compare
ca951ef to
807d20d
Compare
|
Hey @keval718 Could you give me some examples of this happening? If an Agent sends a message, then the ChatOutput creates a new message, it would duplicate the message in the playground. |
569a642 to
b1fdf05
Compare
f4d547c to
1e148ba
Compare
…10586) * fix: resolved merge conflict * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix: create a new message to avoid mutating shared instances * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix: resolved merge conflict * [autofix.ci] apply automated fixes * fix: resolved merge conflict * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix: added a check for using exisiting message object * fix: remove unwanted import * fix: resolve merge conflict * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix: add None checks to prevent errors * fix: resolve merge conflict * [autofix.ci] apply automated fixes * fix: backend unit test * fix: resolve merge conflict * [autofix.ci] apply automated fixes * fix: ruff styling errors * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
* docs: update component links to individual pages (#10706) * Revert "Revert "docs: update component documentation links to individual pages"" This reverts commit 0bc27d6. * [autofix.ci] apply automated fixes * llm-selector-renamed * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Apply suggestions from code review * [autofix.ci] apply automated fixes * Apply suggestions from code review * [autofix.ci] apply automated fixes * rebuild-component-index * update-component-index * [autofix.ci] apply automated fixes * build-index * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: avoid updating Message if ChatOutput is connected to ChatInput (#10586) * fix: resolved merge conflict * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix: create a new message to avoid mutating shared instances * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix: resolved merge conflict * [autofix.ci] apply automated fixes * fix: resolved merge conflict * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix: added a check for using exisiting message object * fix: remove unwanted import * fix: resolve merge conflict * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix: add None checks to prevent errors * fix: resolve merge conflict * [autofix.ci] apply automated fixes * fix: backend unit test * fix: resolve merge conflict * [autofix.ci] apply automated fixes * fix: ruff styling errors * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Feat: Runflow optimization and improved dropdown behavior (#10720) * feat: optimize dropdown filtering and output resolution misc: remove commented out code feat: add refresh button and sort flows by updated_at date from most to least recent ruff (flow.py imports) improve fn contracts in runflow and improve flow id retrieval logic based on graph exec context add dynamic outputs and optimize db lookups add flow cache and db query for getting a single flow by id or name cache run outputs and add refresh context to build config misc misc use ids for flow retrieval misc fix missing flow_id bug add unit and integration tests add input field flag to persist hidden fields at runtime move unit tests and change input and output display names chore: update component index fix: fix tool mode when flow has multiple inputs by dynamically creating resolvers chore: update component index ruff (run_flow and tests) add resolvers to outputs map for non tool mode runtime fix tests (current flow excluded in db fetch) mypy (helpers/flow.py) chore: update component index remove unused code and clean up comments fix: persist user messages in chat-based flows via session injection chore: update component index empty string fallback for sessionid in chat.py chore: update component index chore: update component index cache invalidation with timestamps misc add cache invalidation chore: update component index chore: update comp idx ruff (run_flow.py) change session_id input type to MessageTextInput chore: update component index chore: update component index chore: update component index chore: update component index sync starter projects with main chore: update component index chore: update component index chore: update component index remove dead code + impl coderabbit suggestions chore: update component index chore: update component index clear options metadata before updating chore: update component index sync starter projects with main sync starter projects with main default param val (list flows) * chore: update component index * add integration tests * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) --------- Co-authored-by: Cristhian Zanforlin <criszl@192.168.15.88> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: Add dynamic tool mode descriptions for agent integration (#10744) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: Add profile picture management and API endpoints (#10763) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * deps: upgrade altk (#10804) upgrade altk: * fix: use running event loop to fix asyncio error when calling mcp tools (#10806) * use existing event loop instead of recreating when calling mcp tools * component index * [autofix.ci] apply automated fixes * starter projects * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: Improve file processing robustness and error feedback (#10781) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: resolve merge conflict (#10831) * fix: fixed warning on console for nested button (#10724) (#10832) * removed unnecessary buttons on the flows page * added the asChild prop and hid button so they are not accessible by tabbing * added tab index to ensure that buttons as not selectable using the tab * made sure that accessibility is possible one bulk selection is enabled * made sure that accessibility is possible one bulk selection is enabled * Fix: added testcases and refactor * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes --------- Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: fixed warning on console (#10745) (#10830) * remove console warnings * [autofix.ci] apply automated fixes --------- Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: mask value to hide null field being returned (#10778) (#10829) * fix: mask value to hide null field being returned * [autofix.ci] apply automated fixes * fix: added testcase and updated functionality --------- Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com> Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local> * Fix: Allow refresh list button to stay stagnant while zoom (Safari) (… (#10827) Fix: Allow refresh list button to stay stagnant while zoom (Safari) (#10777) * remove sticky as it was causing the refresh list to float on safari * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes --------- Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * feat: Add superuser support for running any user flow (#10808) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Revert "feat: Add superuser support for running any user flow (#10808)" This reverts commit 423419e. * fix: Ollama models list in Agent component (#10814) * fix: Ollama model list fails to load in Agent and Ollama components * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Fix: Ensure Default Tab is Credential (#10779) (#10826) * fix: made sure the tab is visible * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Fix: added typing * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix: added testcases * fix: added handleOnValue change function and created a helper file --------- Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local> Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com> * chore: update cuga version (#10737) (#10738) Co-authored-by: Sami Marreed <sami.marreed@ibm.com> * chore: Remove DataFrameToToolsetComponent and related tests (#10845) Remove DataFrameToToolsetComponent and related tests Deleted the DataFrameToToolsetComponent implementation, its import/registration in the processing module, and all associated unit tests. This cleans up unused code and test files related to converting DataFrame rows into toolset actions. * fix: Handle GCP JSON parsing credentials (#10859) fix: Proper parsing of GCP credentials JSON (#10828) * fix: Proper parsing of GCP credentials JSON * Update save_file.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Update test_save_file_component.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Fix GCP issues * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Update test_save_file_component.py * Update save_file.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Update save_file.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Update save_file.py * Fix ruff errors * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: anthropic constants (#10862) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: Add feature flag check to simplified_run_flow_session (#10863) * fix: Improve the debugging messages on startup (#10864) * fix: Suppress SIGSEGV errors on startup (#10849) * fix: Suppress SIGSEGV errors * Update test_cli.py * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Update News Aggregator.json Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: Don't fail if doc column is missing (#10746) (#10872) * fix: Don't fail if doc column is missing * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Surface warning message to the UI * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Update test_docling_utils.py * [autofix.ci] apply automated fixes * Update test_docling_utils.py --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * add x-api-key auth option * fix(auth): Disallow refresh token access to API endpoints * fix: Properly support the Batch Run component for watsonX models (#10877) * fix: Support Batch Run with watsonX (#10848) * fix: Support Batch Run with watsonX * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Update batch_run.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: Image upload for Gemini/Anthropic (#10880) * fix: Image upload for Gemini/Anthropic (#10867) * Fix image upload for Gemini/Anthropic and ChatOutput session_id preservation * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix ruff erros * [autofix.ci] apply automated fixes * resolve conflicts * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * build component index * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) --------- Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Himavarsha <40851462+HimavarshaVS@users.noreply.github.com> * fix: Improve the default startup logging for readability (#10894) fix: Clean up the default startup logging (#10842) * fix: Clean up the default startup logging * [autofix.ci] apply automated fixes * Update manager.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Update test_security_cors.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Himavarsha <40851462+HimavarshaVS@users.noreply.github.com> * Fix: lfx serve aysncio event loop error (#10888) fix lfx serve asyncio event loop bug * fix: Update LangflowCounts component to format star and Discord counts (#10896) * fixed counts * fix: Update LangflowCounts component to format star and Discord counts --------- Co-authored-by: Deon Sanchez <69873175+deon-sanchez@users.noreply.github.com> * Fix: update lfx serve tests to mock the .serve() to prevent hanging (#10905) port lfx serve test fix from main * Fix: lfx run agent _noopresult not iterable error (#10893) * fix _noopresult not iterable and session.add never awaited error and warning, respectively * just make the add stub sync * Fix: lfx run agent _noopresult not iterable error (#10911) * fix _noopresult not iterable and session.add never awaited error and warning, respectively * just make the add stub sync * the real final solution v3 * real solution v4 * revert * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: Add graceful subprocess cleanup during shutdown (#10906) * add mcp cleanup function * refactor(mcp_cleanup.py): simplify error handling using contextlib.suppress to improve code readability test(mcp_cleanup.py): update tests to use context manager for patching to enhance clarity and maintainability --------- Co-authored-by: Adam Aghili <Adam.Aghili@ibm.com> * fix(workflows): include src/lfx/uv.lock in git add command to ensure all necessary files are tracked fix(Makefile): add --no-sources flag to uv build command for langflow_base to optimize build process * chore(nightly_build.yml): remove unnecessary directory change for lfx in nightly build workflow to streamline the process * chore(release_nightly): update build command to include --no-sources flag for Langflow Base CLI to ensure proper build configuration fix(Makefile): remove --no-sources from build_langflow_base to align with updated build command in release workflow * chore(chat.py): remove unused future annotations import to clean up code * fix(chat.py): add future annotations import for better type hinting support fix(deps.py): move certain imports outside TYPE_CHECKING for FastAPI compatibility and update type hinting for get_cache_service function * chore: print version * chore: use release_tag as version * fix: --prerelease=allow * fix: correctly raise file not found errors in File GET endpoints (#10922) fix: correctly raise file not found errors in File GET endpoints (#10908) * Clean up the file GET endpoints * Add test * [autofix.ci] apply automated fixes * ruff/mypy * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Fix issues with async * use uvlock from main * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Eric Hare <ericrhare@gmail.com> Co-authored-by: Himavarsha <40851462+HimavarshaVS@users.noreply.github.com> * fix: image pathing to operate with s3 storage (#10919) (#10929) * Fix image pathing to operate with s3 storage * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * add test * [autofix.ci] apply automated fixes * ruff * Add abstract method annotation * [autofix.ci] apply automated fixes * fix: use parse_file_path in get_files for S3 storage compatibility --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: himavarshagoutham <himavarshajan17@gmail.com> * Feat: migrate MCP transport from SSE to streamable http (#10934) * port #10727 * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * refactor(deps.py): reorganize imports for clarity and compliance with FastAPI requirements fix(deps.py): update return type of get_cache_service function to use Union for better type hinting * fix: update sidebar icon styles to maintain backward compatibility (#10948) * fix: Add empty input check in ALTKAgent for Anthropic (#10926) * fix: Add empty input check in ALTKAgent for Anthropic Shamelessly copies agent.py's empty input check to prevent Anthropic API errors. * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) --------- Co-authored-by: Jason Tsay <jason.tsay@ibm.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: add condition to not make folder download fail when flow has Note component (#10953) * fix: Enhance error handling for langchain-core version compatibility (#10768) * fix: Restrict message and session access to flow owners (#10973) * feat(monitor.py): add user flow filtering to message sessions and messages endpoints to enhance data access control refactor(monitor.py): remove dependencies from route decorators and pass current_user as a parameter for better clarity and maintainability * test: update message-related test fixtures to associate messages with user-specific flows This change ensures that messages created in tests are linked to a flow specific to the active user, allowing for better filtering and organization of messages in the database. It enhances the test environment by simulating real-world usage scenarios more accurately. * chore(monitor.py): reorder import statements to follow consistent structure and improve readability * Fix: lfx run with agent component throws '_NoopResult' object is not iterable' (#10914) * fix _noopresult not iterable and session.add never awaited error and warning, respectively * just make the add stub sync * the real final solution v3 * real solution v4 * revert * fix noopresult not iterable error and add was not awaited warning * do await check in aupdate_messages * [autofix.ci] apply automated fixes --------- Co-authored-by: Himavarsha <40851462+HimavarshaVS@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: Support tool mode for components that have no inputs (#10982) fix: Support tool mode in components without inputs (#10959) * fix: Support tool mode in components without inputs * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: (Cherry Pick) default Ollama base url (#10981) * fix: Properly set a default Ollama base url (#10940) * fix: Properly set a default Ollama base url * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) --------- Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: Add authentication to various endpoints (#10977) (#10985) * fix: Add authentication to various endpoints (#10977) * fix: Add authentication to various endpoints * [autofix.ci] apply automated fixes * Couple more endpoints * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Update log_router.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Update mcp.py * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * Fix ruff errors * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Update test_endpoints.py * Fix tests * Update Nvidia Remix.json * Update test_registration.py * [autofix.ci] apply automated fixes * Update test_files.py Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Address review comments Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Review updates Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Fix: ensure streamable-http session manager is entered and exited from the same task (#10991) * cherry pick #10966 * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Fix: cuga integration (#10976) (#10990) * Fix: cuga integration (#10976) * feat: upgrade cuga version * chore: add component index * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix: cuga component * chore: update index * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * fix: upgrade cuga * fix: new component index * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * chore: add component index * [autofix.ci] apply automated fixes * chore: update package * chore: update index * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix: cuga relatetive temp * fix: update cuga * chore: add component index * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * fix: remove space * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * [autofix.ci] apply automated fixes --------- Co-authored-by: Sami Marreed <sami.marreed@ibm.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * test(webhook): add comprehensive tests for webhook endpoint functionality and error handling (#10995) * fix: Improve image path extraction and validation (#10999) * fix: make key generated on mcp json be shown, make placeholder show up if key not generated (#10997) * changed api key to show placeholder when api key is empty * changed useMcpServer to use generated api key if store api key is empty, add dependency to callback * [autofix.ci] apply automated fixes * Added tests * [autofix.ci] apply automated fixes * Update src/frontend/src/pages/MainPage/pages/homePage/hooks/useMcpServer.ts Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com> --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com> * Fix: disable mcp sse endpoints astra (#11004) * disable mcp sse transport endpoints in astra cloud * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Himavarsha <40851462+HimavarshaVS@users.noreply.github.com> * fix: mcp-proxy process leak (#11008) * fix: mcp-proxy process leak (#10988) * fix leak * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Move MCP client imports out of loop iteration in get_servers (#10993) * Initial plan * Move MCPStdioClient and MCPStreamableHttpClient imports to get_servers function Co-authored-by: phact <1313220+phact@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: phact <1313220+phact@users.noreply.github.com> * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Edwin Jose <edwin.jose@datastax.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: phact <1313220+phact@users.noreply.github.com> Co-authored-by: Adam Aghili <Adam.Aghili@ibm.com> * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) --------- Co-authored-by: Sebastián Estévez <estevezsebastian@gmail.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Edwin Jose <edwin.jose@datastax.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: phact <1313220+phact@users.noreply.github.com> * feat: add build-nightly-ep to docker-nightly-build (#10942) * feat: add build-nightly-ep to docker-nightly-build add build-nightly-ep to docker-nightly-build * chore: update where langflow-nightly-ep is used update where langflow-nightly-ep is used to match update where langflow-nightly-all * chore: add nightly-main-ep to release_nightly add nightly-main-ep to call_docker_build_main_ep in release_nightly * chore: run what is already here * chore: revert .secrets.baseline and let it regen * fix(message.py): simplify file presence check using kwargs.get() for better readability and maintainability * fix: Disable Local storage option in Write File component for cloud environments (#11003) (#11022) * fix: Disable Local storage option in Write File component for cloud environments (#11003) * modify savefile component * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * component index * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Update src/lfx/src/lfx/components/files_and_knowledge/save_file.py Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com> * fix ruff errors * fix conflicts * resolve conflicts * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix indentation error * [autofix.ci] apply automated fixes * update options dynamically * build component index * [autofix.ci] apply automated fixes * fix ruff errors * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com> * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com> * fix: cuga update (#11019) (#11026) * fix: update cuga version * chore: build index Co-authored-by: Sami Marreed <sami.marreed@ibm.com> * fix: langwatch traces all api endpoints (#11014) * create tracerprovider so langwatch doesnt pick up fastapi calls * move opentel sdk imports to the top * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Fix: improve exception handling and status code for disabled endpoints (#11012) * port #11011 * recover line from 1.7.0 * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix(deps): Pin langchain-mcp-adapters to resolve langchain-core compatibility (#11037) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: Make sure the research translation loop template is properly operating (#11042) * fix: Make sure loop inputs are properly handled in research (#11029) * fix: Make sure loop inputs are properly handled in research Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * [autofix.ci] apply automated fixes * Update reactflowUtils.ts Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Update reactflowUtils.ts Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Revert "Update reactflowUtils.ts" This reverts commit 9c8b1d1. * Revert "Update reactflowUtils.ts" This reverts commit 6be7ab9. * Fix template Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * [autofix.ci] apply automated fixes * Update Research Translation Loop.json Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Update reactflowUtils.ts Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --------- Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * Update Research Translation Loop.json Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: disable knowledge components in astra (#11047) * cherry-pick #11046 * update component index * update component index again * fix: Advanced mode in read file component (#11041) (#11056) * fix: Advanced mode in read file component (#11041) * add a proper file path * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Update file.py Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * build component index * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * build component index * [autofix.ci] apply automated fixes * Fix incorrect use of .tempdir Co-Authored-By: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Eric Hare <ericrhare@gmail.com> * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Eric Hare <ericrhare@gmail.com> * fix: validate flow file_save path is in a valid location (#11060) fix: validate flow file_save path is in a valid location (#11039) * Validate flow file save path is in a valid location * clean up logic * fix tests * comments * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * fix backslash vuln * [autofix.ci] apply automated fixes * add storage service param to function in agentic utils * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Ruff errors * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * Resolve path in setup * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes (attempt 3/3) * comp index update * [autofix.ci] apply automated fixes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Eric Hare <ericrhare@gmail.com> * refactor: Move fetch credentials to the customizations (#11049) (#11063) move fetch credentials to the customizations * fix: Fix async context handling in serve command and add integration tests (#10776) * refactor(tests): rename test IDs from helpersCreate List and logicPass to processingCreate List and flow_controlsPass for consistency and clarity in decision flow tests * refactor: Langflow cloud updates (#10910) * refactor: Use customization to get api base urls (#10871) * fixed counts * use customization to get api base urls --------- Co-authored-by: Deon Sanchez <69873175+deon-sanchez@users.noreply.github.com> * refactor: add code sample customizations (#10884) * add code sample customizations * import cleanup * embedded widget generator --------- Co-authored-by: Deon Sanchez <69873175+deon-sanchez@users.noreply.github.com> * fix: release workflow (#11087) * chore(release.yml): update release_lfx input description and make it optional to improve clarity feat(release.yml): add ensure-lfx-published job to automate LFX version check and publishing process to PyPI * chore: clean up release workflow comment out unneeded cross platform test and move steps around to match the already existing pattern --------- Co-authored-by: cristhianzl <cristhian.lousa@gmail.com> * Revert "fix: release workflow " (#11088) Revert "fix: release workflow (#11087)" This reverts commit b26d032. * fix: release workflow (#11089) * chore(release.yml): update release_lfx input description and make it optional to improve clarity feat(release.yml): add ensure-lfx-published job to automate LFX version check and publishing process to PyPI * chore: clean up release workflow comment out unneeded cross platform test and move steps around to match the already existing pattern * chore: remove test-lfx-cross-platform remove test-lfx-cross-platform * chore: address some of co-pilots comments address some of co-pilots comments --------- Co-authored-by: cristhianzl <cristhian.lousa@gmail.com> * fix: use langflow package path for database location (#11107) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * chore: bump versions for langflow 1.7.1, langflow-base 0.7.1, and lfx 0.2.1 (#11108) * chore: update version to 0.2.1 in pyproject.toml * bump version to 1.7.1 in package.json * chore: bump version to 0.7.1 and update lfx dependency to 0.2.1 in pyproject.toml * chore: bump versions for langflow, langflow-base, and lfx in pyproject.toml and uv.lock * regenarate lock based on release branch * new package-lock fixed * fix: regenerate package-lock.json with missing nested dependencies Adds canvas@2.11.2 (for rehype-mathjax) and yaml@2.8.2 (for tailwindcss) that were missing from the lock file causing npm ci to fail. --------- Co-authored-by: cristhianzl <cristhian.lousa@gmail.com> * test(regression): update test to use box selection for Combine Text nodes instead of Ctrl/Meta+click for better reliability in Playwright with ReactFlow * test(fileUploadComponent.spec.ts): increase timeout duration for file rename tests to ensure stability test(general-bugs-reset-flow-run.spec.ts): add wait time to improve reliability of component build checks * Template update * [autofix.ci] apply automated fixes * Fix test failures --------- Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: keval shah <kevalvirat@gmail.com> Co-authored-by: Hamza Rashid <74062092+HzaRashid@users.noreply.github.com> Co-authored-by: Cristhian Zanforlin <criszl@192.168.15.88> Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com> Co-authored-by: Jordan Frazier <122494242+jordanrfrazier@users.noreply.github.com> Co-authored-by: olayinkaadelakun <olayinka.adelakun@ibm.com> Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local> Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com> Co-authored-by: Carlos Coelho <80289056+carlosrcoelho@users.noreply.github.com> Co-authored-by: Himavarsha <40851462+HimavarshaVS@users.noreply.github.com> Co-authored-by: Sami Marreed <sami.marreed@ibm.com> Co-authored-by: Edwin Jose <edwin.jose@datastax.com> Co-authored-by: Eric Hare <ericrhare@gmail.com> Co-authored-by: Mike Pawlowski <mpawlow@ca.ibm.com> Co-authored-by: Viktor Avelino <64113566+viktoravelino@users.noreply.github.com> Co-authored-by: Deon Sanchez <69873175+deon-sanchez@users.noreply.github.com> Co-authored-by: himavarshagoutham <himavarshajan17@gmail.com> Co-authored-by: Jason Tsay <jason.tsay@ibm.com> Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com> Co-authored-by: Gabriel Luiz Freitas Almeida <gabriel@langflow.org> Co-authored-by: Sebastián Estévez <estevezsebastian@gmail.com> Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com> Co-authored-by: phact <1313220+phact@users.noreply.github.com> Co-authored-by: Mike Fortman <michael.fortman@datastax.com>
This PR fixes an issue where User and AI messages were generated with the same message ID, causing one message to overwrite the other in the chat UI and in network payloads. The issue occurred because the ChatOutput component reused an existing Message instance without generating a new ID.
Root Cause
When input_value is already a Message object, the component mutates it by updating the text but previously did not regenerate the message.id. As a result, both the User message and the AI message could share the same ID if the object was reused along the component chain.
This ID collision caused:
What This Fix Does
When reusing an existing Message instance, we now generate a fresh UUID:
if isinstance(self.input_value, Message):
message = self.input_value
message.text = text
message.id = uuid.uuid4() # Generate new unique ID
Why This Fix Matters
With unique IDs:
Testing & Verification
Summary by CodeRabbit
Release Notes