Skip to content

fix(api): correct plugin dependency id format in snippet DSL extraction#38342

Closed
SquabbyZ wants to merge 2 commits into
langgenius:mainfrom
SquabbyZ:fix/snippet-dsl-dependency-id-format
Closed

fix(api): correct plugin dependency id format in snippet DSL extraction#38342
SquabbyZ wants to merge 2 commits into
langgenius:mainfrom
SquabbyZ:fix/snippet-dsl-dependency-id-format

Conversation

@SquabbyZ

@SquabbyZ SquabbyZ commented Jul 2, 2026

Copy link
Copy Markdown
Contributor

Fixes #38406

Summary

In api/services/snippet_dsl_service.py:577 and :585, the tool and agent branches of _extract_dependencies_from_workflow_graph() both build the dependency id with:

dependencies.append(f"{provider_name}/{provider_name}")

That produces ids like google/google (the two halves of the f-string are the same variable) which never match a real plugin id. The docstring two lines above explicitly says the expected format is ['langgenius/google'] and the canonical plugin id format is {organization}/{plugin_name}, where organization == provider_type for non-langgenius tools and plugin_name == provider_name.

Introduced during the early Snippet DSL implementation; never fixed because the buggy ids were silently dropped downstream (check_dependencies would just report no leaked deps for the typo output, instead of detecting the actual missing plugin).

Changes

api/services/snippet_dsl_service.py: switch both f-strings from f"{provider_name}/{provider_name}" to f"{provider_type}/{provider_name}", which matches the docstring and analyze_tool_dependency()'s output in services/plugin/dependencies_analysis.py (which uses ToolProviderID(tool_id).plugin_id == '{organization}/{plugin_name}').

A regression test is added in api/tests/unit_tests/services/test_snippet_dsl_service.py:

  • A graph with a TOOL node using provider='google' and an AGENT node using provider='openai' (both provider_type='langgenius') now extracts ['langgenius/google', 'langgenius/openai'].
  • A TOOL node with only provider_type set (no provider) is correctly skipped instead of being appended as a malformed id.

Diff stat

api/services/snippet_dsl_service.py                       | 4 ++--
api/tests/unit_tests/services/test_snippet_dsl_service.py | 49 ++++++++++++++++++
2 files changed, 51 insertions(+), 2 deletions(-)

Test plan

  • pytest api/tests/unit_tests/services/test_snippet_dsl_service.py::test_extract_dependencies_from_workflow_graph_uses_provider_type_and_name -v passes.
  • All existing test_snippet_dsl_service.py tests continue to pass.
  • Manual: export a workflow snippet that includes a Google search tool ??confirm the leaked-dependency check correctly reports langgenius/google as a dependency.
  • ruff check api/services/snippet_dsl_service.py clean.

Risk / behavior preservation

  • Only the string format of appended dependency ids is corrected. No other branch of the function is touched.
  • The function still returns list[str] and is still called by the same two callers (_extract_dependencies_from_workflow at lines 393 and 534).
  • The buggy output ('google/google') was always a no-op downstream ??it never matched any installed plugin, so the call sites already had no observation of the typo. The corrected output now matches real plugin ids, so any check_dependencies run that was silently passing may now surface legitimate missing-plugin warnings. This is the intended new behavior.
  • No schema, migration, controller, or frontend changes.

Related

  • Discovered by peaks-loop session 2026-07-02-session-95565c during a code-sweep on 2026-07-02.
  • Companion function: DependenciesAnalysisService.analyze_tool_dependency in services/plugin/dependencies_analysis.py ??the canonical formatter that this PR brings the snippet path in line with.

Automation

Generated via peaks-loop (full-auto mode). Red-line scope was limited to snippet_dsl_service.py and the matching test file. Commit message includes the peaks-loop provenance line for traceability.

?? Generated with Claude Code via peaks-loop

SquabbyZ added 2 commits July 3, 2026 00:47
Six updated_at Mapped columns in api/models/trigger.py (lines 128, 183,
213, 373, 433, 482) declare:

  server_default=func.current_timestamp(),
  server_onupdate=func.current_timestamp(),   <-- typo

server_onupdate= expects a FetchedValue (DB-side trigger marker), NOT a
Python callable. SQLAlchemy silently accepts func.current_timestamp()
here, so the column never gets auto-refreshed on ORM UPDATE — updated_at
stays frozen at the original row value after every ORM update.

The same file already uses the correct onupdate=func.current_timestamp()
once on line 534 (WorkflowSchedulePlan.updated_at), proving the typo is
inconsistent rather than intentional. All other 70+ models in
api/models/ (account, model, tools, provider, dataset, workflow, ...)
already use onupdate= uniformly.

A seventh column (line 482, AppTrigger.updated_at) used
default=naive_utc_now() alongside server_onupdate= — switched to
onupdate=naive_utc_now() for symmetry: Python-side default + Python-side
onupdate.

Impact: the affected models are AppTriggerSubscription,
TriggerProviderSubscription, AppTrigger, WorkflowTriggerLog,
WorkflowTriggerStatus, AppTrigger (the 6 server_default= sites) and
AppTrigger.updated_at. Any ORM-side mutation of these rows in
api/services/trigger/* (app_trigger_service.py:39 update(AppTrigger),
schedule_service.py, webhook_service.py, etc.) silently leaves
updated_at stale.

No migration needed — column shape is unchanged, only the auto-refresh
behavior on ORM UPDATE is corrected.

diff --stat:
  api/models/trigger.py | 14 +++++++-------
  1 file changed, 7 insertions(+), 7 deletions(-)

Generated via peaks-loop (session 2026-07-02-session-95565c, request
2026-07-02-fix-trigger-models-onupdate-typo). Red-line scope was limited
to api/models/trigger.py.
In api/services/snippet_dsl_service.py:577 and :585, the tool and
agent branches of _extract_dependencies_from_workflow_graph() both
build the dependency id with:

    dependencies.append(f"{provider_name}/{provider_name}")

That produces ids like 'google/google' (the two halves of the f-string
are the same variable) which never match a real plugin id. The
docstring two lines above explicitly says the expected format is
['langgenius/google'] and the canonical plugin id format is
'{organization}/{plugin_name}', where organization == provider_type
for non-langgenius tools and plugin_name == provider_name.

Introduced during the early Snippet DSL implementation; never fixed
because the buggy ids were silently dropped downstream
(check_dependencies would just report no leaked deps for the typo
output, instead of detecting the actual missing plugin).

This change switches both f-strings to:

    f"{provider_type}/{provider_name}"

which matches the docstring and the analyze_tool_dependency() output
in services/plugin/dependencies_analysis.py (which uses
ToolProviderID(tool_id).plugin_id == '{organization}/{plugin_name}').

A regression test is added: a graph with a TOOL node using provider
'google' and an AGENT node using provider 'openai' (both with
provider_type 'langgenius') now extracts ['langgenius/google',
'langgenius/openai']; a TOOL node with only provider_type set (no
provider) is correctly skipped instead of being appended as a
malformed id.

diff --stat:
  api/services/snippet_dsl_service.py                                  | 4 ++--
  api/tests/unit_tests/services/test_snippet_dsl_service.py            | 49 ++++++
  2 files changed, 51 insertions(+), 2 deletions(-)

Generated via peaks-loop (session 2026-07-02-session-95565c, request
2026-07-02-fix-snippet-dsl-dependency-id). Red-line scope was limited
to snippet_dsl_service.py and the matching test file.
@dosubot dosubot Bot added the size:S This PR changes 10-29 lines, ignoring generated files. label Jul 2, 2026

Copy link
Copy Markdown
Member

Thanks for the contribution. Before we review this PR, please open an issue first to describe the problem, expected behavior, and proposed approach, then link that issue here. This helps us confirm the scope and align on the fix before moving forward.

@crazywoola crazywoola self-assigned this Jul 3, 2026
@SquabbyZ

SquabbyZ commented Jul 4, 2026

Copy link
Copy Markdown
Contributor Author

@crazywoola Thanks for the guidance. Opened issue #38406 describing the malformed plugin id bug (f"{provider_name}/{provider_name}" instead of f"{provider_type}/{provider_name}"), the proposed fix, and the regression test. PR description now links the issue via Fixes #38406. Ready for re-review.

@SquabbyZ SquabbyZ closed this Jul 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:S This PR changes 10-29 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

extract_dependencies_from_workflow_graph produces malformed plugin ids for non-langgenius tools

2 participants