dify/api/models
dparkmit24 2c162109c5 test(agent): pin the colliding case and state why the rule is shaped this way
The occurrence selector tells a per-call list from a single call's list
value by length alone. One test pinned the side where that is
unambiguous -- a 3-element list against 2 calls, replayed whole. The side
that decides whether the rule is safe is the other one: a tool called n
times whose single stored value is a list of length n. That case was
decided by the rule and described by no test, so it read as an oversight
rather than a decision.

Pin it at both readers. The replay reader in base_agent_runner and the
display reader on MessageAgentThought each get a two-call record whose
one stored value is a two-element list, asserting that call 1 reads
element 0 and call 2 reads element 1 -- what the rule does today. The
name says what the case concedes rather than what it asserts.

The docstrings say why the asymmetry is tolerable. observation values
are always str: ToolEngine.agent_invoke is typed
-> tuple[str, list[str], ToolInvokeMeta] and both runners store element
0, so a list under a tool name is not a shape any writer produces and
the length check is defensive there. tool_input values are json.loads of
the model's arguments with no shape check, so a legacy list-valued input
is possible in principle, and that is the side the collision can reach.

The selector is defined twice, identically, because models/ importing
from core/agent/ is the worse layering trade and the reverse is odd.
Neither copy is in the wrong place, so each now names the other and says
the duplication is deliberate -- enough for a future editor to find both.

No behaviour change: the condition, the ordering and the fallback are
untouched.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-05 18:57:51 -07:00
..
utils chore(api): Upgrade graphon to v0.5.1 (#37168) 2026-06-11 07:37:27 +00:00
__init__.py refactor: introduce agent working environment architecture (#39480) 2026-07-28 13:16:05 +00:00
_workflow_exc.py feat: Persist Variables for Enhanced Debugging Workflow (#20699) 2025-06-24 09:05:29 +08:00
account.py chore(api): consolidate chained .where() calls into single calls (#39819) 2026-07-30 16:59:50 +00:00
agent_config_entities.py test(e2e): validate generated console contracts (#39400) 2026-07-22 07:48:37 +00:00
agent.py feat(agent): make home snapshots optional and use backend defaults (#39702) 2026-07-29 02:01:12 +00:00
api_based_extension.py fix: use default_factory for callable defaults in ORM dataclasses (#28730) 2025-11-27 09:39:49 +09:00
base.py ci: add flag for linter (#37018) 2026-06-08 04:53:12 +00:00
comment.py chore: port WorkflowComment (#36039) 2026-05-11 09:17:12 +00:00
credential_permission.py feat: per-credential visibility control for plugin credentials (#35468) 2026-06-01 05:56:18 +00:00
dataset.py chore: bump pyrefly version (#39876) 2026-08-03 05:59:01 +00:00
engine.py feat(api): Add image multimodal support for LLMNode (#17372) 2025-04-30 17:28:02 +08:00
enums.py fix(api): tolerate legacy service_api end-user type on load (#38271) 2026-07-02 05:34:36 +00:00
execution_extra_content.py refactor: migrate execution extra content repository tests from mocks to testcontainers (#33852) 2026-03-23 17:32:11 +09:00
human_input.py chore(api): upgrade graphon to v0.6.0, migrate HITL logic back to Dify (#38247) 2026-07-03 03:45:21 +00:00
model.py test(agent): pin the colliding case and state why the rule is shaped this way 2026-08-05 18:57:51 -07:00
oauth.py feat: per-credential visibility control for plugin credentials (#35468) 2026-06-01 05:56:18 +00:00
onboarding.py feat(web): add step-by-step tour shell (#38785) 2026-07-20 09:23:25 +00:00
provider_ids.py ci: add flag for linter (#37018) 2026-06-08 04:53:12 +00:00
provider.py ci: add flag for linter (#37018) 2026-06-08 04:53:12 +00:00
snippet.py feat: snippet (#37046) 2026-06-05 09:38:42 +00:00
source.py refactor: replace bare dict with dict[str, Any] in models, providers, extensions, libs, and test utilities (#35186) 2026-04-14 17:51:25 +00:00
task.py fix: use default_factory for callable defaults in ORM dataclasses (#28730) 2025-11-27 09:39:49 +09:00
tools.py feat(api): add MCP user-identity forwarding (#36839) 2026-06-08 04:32:11 +00:00
trigger.py fix(models): correct onupdate typo on trigger.py updated_at columns (#38341) 2026-07-04 17:14:01 +00:00
types.py chore: port isinstance to match case (#37271) 2026-06-18 00:18:03 +00:00
web.py refactor(api): Query API to select function_1 (#33565) 2026-03-17 23:29:16 +09:00
workflow.py feat(workflow): support LLM environment variables (#39125) 2026-08-04 06:17:13 +00:00