mirror of
https://github.com/langflow-ai/langflow.git
synced 2026-07-24 08:23:43 +08:00
fix: add stream toggle back to agent (#13155)
* add stream toggle back to agent * chore: auto-bake note keys and regenerate backend locales/en.json [skip ci] * ci: stop transient Windows npm/cache flakes from failing frontend tests The nightly frontend job fails almost every day on a single Windows Playwright shard, never on actual test logic. With fail-fast:false over ~70 Windows shards each making several cache/artifact-service calls, a transient GitHub Actions cache/artifact hiccup on any one shard flips needs.setup-and-test.result to failure and reds the whole nightly (observed steps: Setup Node.js Environment, Cache Playwright Browsers, Upload Playwright Coverage Artifact). - Decouple npm caching from actions/setup-node (its internal cache step can't be made non-fatal) and replace it with a standalone actions/cache@v5 step marked continue-on-error. - Mark Cache Playwright Browsers and the artifact-upload steps continue-on-error so an infra blip can no longer fail a test shard. Only a real test/browser failure can fail a shard now. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com> * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * [autofix.ci] apply automated fixes --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
851a48401b
commit
d017e156cd
40
.github/workflows/typescript_test.yml
vendored
40
.github/workflows/typescript_test.yml
vendored
@ -227,8 +227,22 @@ jobs:
|
||||
id: setup-node
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: "npm"
|
||||
cache-dependency-path: ./src/frontend/package-lock.json
|
||||
|
||||
# npm caching is decoupled from setup-node so a transient cache-service
|
||||
# hiccup (frequent on Windows runners) never fails the job. See #25 / #1.
|
||||
- name: Get npm cache directory
|
||||
id: npm-cache-dir
|
||||
shell: bash
|
||||
run: echo "dir=$(npm config get cache)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v5
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: ${{ steps.npm-cache-dir.outputs.dir }}
|
||||
key: ${{ runner.os }}-npm-${{ env.NODE_VERSION }}-${{ hashFiles('src/frontend/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-${{ env.NODE_VERSION }}-
|
||||
|
||||
- name: Install Frontend Dependencies
|
||||
run: npm ci
|
||||
@ -298,8 +312,23 @@ jobs:
|
||||
id: setup-node
|
||||
with:
|
||||
node-version: ${{ env.NODE_VERSION }}
|
||||
cache: "npm"
|
||||
cache-dependency-path: ./src/frontend/package-lock.json
|
||||
|
||||
# npm caching is decoupled from setup-node so a transient cache-service
|
||||
# hiccup (frequent on Windows runners) never fails the job. See #25 / #1.
|
||||
- name: Get npm cache directory
|
||||
id: npm-cache-dir
|
||||
shell: bash
|
||||
run: echo "dir=$(npm config get cache)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Cache npm dependencies
|
||||
uses: actions/cache@v5
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: ${{ steps.npm-cache-dir.outputs.dir }}
|
||||
key: ${{ runner.os }}-npm-${{ env.NODE_VERSION }}-${{ hashFiles('src/frontend/package-lock.json') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-npm-${{ env.NODE_VERSION }}-
|
||||
|
||||
- name: Install Frontend Dependencies
|
||||
run: npm ci
|
||||
working-directory: ./src/frontend
|
||||
@ -308,6 +337,7 @@ jobs:
|
||||
- name: Cache Playwright Browsers
|
||||
id: cache-playwright
|
||||
uses: actions/cache@v5
|
||||
continue-on-error: true
|
||||
with:
|
||||
path: ${{ env.PLAYWRIGHT_BROWSERS_PATH }}
|
||||
key: playwright-${{ env.PLAYWRIGHT_VERSION }}-chromium-${{ runner.os }}
|
||||
@ -366,6 +396,7 @@ jobs:
|
||||
|
||||
- name: Upload Test Results
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: blob-report-${{ runner.os }}-${{ matrix.shardIndex }}
|
||||
@ -375,6 +406,7 @@ jobs:
|
||||
|
||||
- name: Upload Playwright Coverage Artifact
|
||||
if: always() && hashFiles('src/frontend/coverage/playwright/**') != ''
|
||||
continue-on-error: true
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: playwright-coverage-${{ matrix.shardIndex }}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -65,6 +65,8 @@
|
||||
"components.agent.inputs.output_schema.info.3b7a7b80": "Schema Validation: Define the structure and data types for structured output. No validation if no output schema.",
|
||||
"components.agent.inputs.project_id.display_name.c7feb8db": "watsonx Project ID",
|
||||
"components.agent.inputs.project_id.info.0d91e5f5": "The project ID associated with the foundation model (IBM watsonx.ai only)",
|
||||
"components.agent.inputs.stream.display_name.1eec3071": "Stream",
|
||||
"components.agent.inputs.stream.info.f835b3ff": "Stream the response from the model. Streaming works only in Chat.",
|
||||
"components.agent.inputs.system_prompt.display_name.55ce85ab": "Agent Instructions",
|
||||
"components.agent.inputs.system_prompt.info.a1fa7781": "System Prompt: Initial instructions and context provided to guide the agent's behavior. Supports dynamic placeholders: {current_date}, {model_name}, {optional_user_context}.",
|
||||
"components.agent.inputs.tools.display_name.ea93d6a2": "Tools",
|
||||
@ -173,6 +175,8 @@
|
||||
"components.altkagent.inputs.project_id.info.0d91e5f5": "The project ID associated with the foundation model (IBM watsonx.ai only)",
|
||||
"components.altkagent.inputs.response_processing_size_threshold.display_name.84c35424": "Response Processing Size Threshold",
|
||||
"components.altkagent.inputs.response_processing_size_threshold.info.d6aeb95b": "Tool output is post-processed only if response exceeds this character threshold.",
|
||||
"components.altkagent.inputs.stream.display_name.1eec3071": "Stream",
|
||||
"components.altkagent.inputs.stream.info.f835b3ff": "Stream the response from the model. Streaming works only in Chat.",
|
||||
"components.altkagent.inputs.system_prompt.display_name.55ce85ab": "Agent Instructions",
|
||||
"components.altkagent.inputs.system_prompt.info.a1fa7781": "System Prompt: Initial instructions and context provided to guide the agent's behavior. Supports dynamic placeholders: {current_date}, {model_name}, {optional_user_context}.",
|
||||
"components.altkagent.inputs.tools.display_name.ea93d6a2": "Tools",
|
||||
|
||||
@ -451,6 +451,47 @@ class TestAgentComponent(ComponentTestBaseWithoutClient):
|
||||
# Note: The provider-specific field name mapping happens inside get_llm,
|
||||
# so we just verify max_tokens is passed correctly
|
||||
|
||||
async def test_should_expose_stream_input_when_agent_component_is_loaded(self, component_class, default_kwargs):
|
||||
"""Regression: the Stream toggle disappeared from the Agent after the ModelInput unification (#12025).
|
||||
|
||||
Given the Agent component is loaded, When its inputs are inspected,
|
||||
Then a 'stream' input field must be present so users can control LLM streaming.
|
||||
"""
|
||||
component = await self.component_setup(component_class, default_kwargs)
|
||||
|
||||
input_names = [inp.name for inp in component.inputs if hasattr(inp, "name")]
|
||||
|
||||
assert "stream" in input_names, "stream input field should be present on the Agent component"
|
||||
assert hasattr(component, "stream"), "Component should have a stream attribute"
|
||||
|
||||
@patch("lfx.components.models_and_agents.agent.AgentComponent.get_memory_data")
|
||||
@patch("lfx.components.models_and_agents.agent.get_llm")
|
||||
async def test_should_pass_stream_value_to_get_llm_when_stream_input_is_enabled(
|
||||
self, mock_get_llm, mock_get_memory_data, component_class, default_kwargs
|
||||
):
|
||||
"""Regression: the Agent must forward the Stream toggle value to get_llm().
|
||||
|
||||
Given stream=True on the Agent, When get_agent_requirements runs,
|
||||
Then get_llm() must be called with stream=True so the LLM streams responses.
|
||||
"""
|
||||
from unittest.mock import AsyncMock, MagicMock
|
||||
|
||||
mock_get_memory_data.return_value = AsyncMock(return_value=[])
|
||||
mock_get_llm.return_value = MagicMock()
|
||||
|
||||
default_kwargs["stream"] = True
|
||||
component = await self.component_setup(component_class, default_kwargs)
|
||||
|
||||
# validate_model_selection requires a list — set a valid model selection
|
||||
component.model = [{"name": "gpt-4o", "provider": "OpenAI", "metadata": {}}]
|
||||
|
||||
await component.get_agent_requirements()
|
||||
|
||||
mock_get_llm.assert_called_once()
|
||||
call_kwargs = mock_get_llm.call_args.kwargs
|
||||
assert "stream" in call_kwargs, "stream should be passed to get_llm"
|
||||
assert call_kwargs["stream"] is True
|
||||
|
||||
async def test_should_append_calculator_tool_when_add_calculator_toggle_is_true(
|
||||
self, component_class, default_kwargs
|
||||
):
|
||||
|
||||
File diff suppressed because one or more lines are too long
@ -12,6 +12,7 @@ if TYPE_CHECKING:
|
||||
from lfx.base.agents.agent import LCToolsAgentComponent
|
||||
from lfx.base.agents.default_system_prompt import DEFAULT_SYSTEM_PROMPT_TEMPLATE
|
||||
from lfx.base.agents.events import ExceptionWithMessageError
|
||||
from lfx.base.constants import STREAM_INFO_TEXT
|
||||
from lfx.base.models.unified_models import (
|
||||
get_language_model_options,
|
||||
get_llm,
|
||||
@ -211,6 +212,13 @@ class AgentComponent(ToolCallingAgentComponent):
|
||||
*LCToolsAgentComponent.get_base_inputs(),
|
||||
# removed memory inputs from agent component
|
||||
# *memory_inputs,
|
||||
BoolInput(
|
||||
name="stream",
|
||||
display_name="Stream",
|
||||
info=STREAM_INFO_TEXT,
|
||||
value=False,
|
||||
advanced=True,
|
||||
),
|
||||
BoolInput(
|
||||
name="add_current_date_tool",
|
||||
display_name="Current Date",
|
||||
@ -283,6 +291,7 @@ class AgentComponent(ToolCallingAgentComponent):
|
||||
model=self.model,
|
||||
user_id=self.user_id,
|
||||
api_key=getattr(self, "api_key", None),
|
||||
stream=bool(getattr(self, "stream", False)),
|
||||
max_tokens=self._get_max_tokens_value(),
|
||||
watsonx_url=getattr(self, "base_url_ibm_watsonx", None),
|
||||
watsonx_project_id=getattr(self, "project_id", None),
|
||||
|
||||
Reference in New Issue
Block a user