dify-player 0.3.3__tar.gz → 0.3.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. {dify_player-0.3.3 → dify_player-0.3.5}/PKG-INFO +1 -1
  2. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/__init__.py +1 -1
  3. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/nodes/llm_groq_chat.py +64 -7
  4. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player.egg-info/PKG-INFO +1 -1
  5. {dify_player-0.3.3 → dify_player-0.3.5}/pyproject.toml +1 -1
  6. {dify_player-0.3.3 → dify_player-0.3.5}/MANIFEST.in +0 -0
  7. {dify_player-0.3.3 → dify_player-0.3.5}/README.md +0 -0
  8. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/__main__.py +0 -0
  9. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/cli.py +0 -0
  10. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/__init__.py +0 -0
  11. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/graph_parser.py +0 -0
  12. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/http_body_converter.py +0 -0
  13. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/node_converters/__init__.py +0 -0
  14. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/node_converters/assigner.py +0 -0
  15. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/node_converters/code.py +0 -0
  16. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/node_converters/end.py +0 -0
  17. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/node_converters/http_request.py +0 -0
  18. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/node_converters/if_else.py +0 -0
  19. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/node_converters/llm.py +0 -0
  20. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/node_converters/loop.py +0 -0
  21. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/node_converters/start.py +0 -0
  22. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/node_converters/template_transform.py +0 -0
  23. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/node_converters/variable_aggregator.py +0 -0
  24. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/plan_serializer.py +0 -0
  25. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/reference_converter.py +0 -0
  26. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/workflow_loader.py +0 -0
  27. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_importer/workflow_normalizer.py +0 -0
  28. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/dify_workflow_importer.py +0 -0
  29. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/event_logger.py +0 -0
  30. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/exceptions.py +0 -0
  31. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/input_resolver.py +0 -0
  32. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/llm_cache.py +0 -0
  33. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/models.py +0 -0
  34. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/nodes/__init__.py +0 -0
  35. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/nodes/assigner.py +0 -0
  36. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/nodes/code.py +0 -0
  37. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/nodes/end.py +0 -0
  38. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/nodes/http.py +0 -0
  39. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/nodes/if_else.py +0 -0
  40. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/nodes/llm_azure_chat.py +0 -0
  41. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/nodes/llm_xai_chat.py +0 -0
  42. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/nodes/start.py +0 -0
  43. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/nodes/template.py +0 -0
  44. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/nodes/variable_aggregator.py +0 -0
  45. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/plan_loader.py +0 -0
  46. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/runtime.py +0 -0
  47. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/value_renderer.py +0 -0
  48. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/workflow_engine.py +0 -0
  49. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player/workflow_executor.py +0 -0
  50. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player.egg-info/SOURCES.txt +0 -0
  51. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player.egg-info/dependency_links.txt +0 -0
  52. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player.egg-info/requires.txt +0 -0
  53. {dify_player-0.3.3 → dify_player-0.3.5}/dify_player.egg-info/top_level.txt +0 -0
  54. {dify_player-0.3.3 → dify_player-0.3.5}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dify-player
3
- Version: 0.3.3
3
+ Version: 0.3.5
4
4
  Summary: Minimal workflow runner for hand-authored Dify-like plans.
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: Jinja2<4,>=3.1
@@ -5,4 +5,4 @@ from dify_player.workflow_engine import WorkflowEngine
5
5
 
6
6
  __all__ = ["__version__", "LLMCacheStore", "NullLLMCacheStore", "WorkflowEngine"]
7
7
 
8
- __version__ = "0.3.3"
8
+ __version__ = "0.3.5"
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import json
3
4
  import os
4
5
  from typing import Any
5
6
 
@@ -158,13 +159,38 @@ async def _run_structured_output_with_repair(
158
159
  latest_metadata = {"usage": _zero_usage(), "finish_reason": None}
159
160
 
160
161
  for attempt_index in range(_STRUCTURED_OUTPUT_REPAIR_RETRIES + 1):
161
- raw_text, metadata = await _request_raw_text(
162
- node=node,
163
- base_url=base_url,
164
- api_key=api_key,
165
- messages=current_messages,
166
- http_client=http_client,
167
- )
162
+ try:
163
+ raw_text, metadata = await _request_raw_text(
164
+ node=node,
165
+ base_url=base_url,
166
+ api_key=api_key,
167
+ messages=current_messages,
168
+ http_client=http_client,
169
+ )
170
+ except GroqLLMBadStatusError as exc:
171
+ failed_generation = _extract_groq_failed_generation(exc)
172
+ if failed_generation is None:
173
+ raise
174
+
175
+ validation_error, raw_text = failed_generation
176
+ attempts.append(
177
+ {
178
+ "attempt": str(attempt_index + 1),
179
+ "error": validation_error,
180
+ "raw_text": raw_text,
181
+ "provider_status_code": str(exc.status_code),
182
+ }
183
+ )
184
+ if attempt_index >= _STRUCTURED_OUTPUT_REPAIR_RETRIES:
185
+ raise GroqLLMStructuredOutputError(
186
+ f"{validation_error} after {attempt_index + 1} attempts",
187
+ attempts=attempts,
188
+ ) from exc
189
+ current_messages = current_messages + [
190
+ _build_repair_message(validation_error=validation_error, previous_output=raw_text)
191
+ ]
192
+ continue
193
+
168
194
  aggregated_usage = _merge_usage(aggregated_usage, metadata["usage"])
169
195
  latest_metadata = metadata
170
196
  try:
@@ -195,6 +221,37 @@ async def _run_structured_output_with_repair(
195
221
  raise AssertionError("structured output repair loop must return or raise")
196
222
 
197
223
 
224
+ # Groq may return json_validate_failed as HTTP 400 even when the failure is the
225
+ # model's generated JSON, not a permanent request/schema error. Retry through the
226
+ # existing repair prompt even when Groq omits failed_generation, because the next
227
+ # attempt can still recover from provider-side structured-output validation.
228
+ def _extract_groq_failed_generation(exc: GroqLLMBadStatusError) -> tuple[str, str] | None:
229
+ if exc.status_code != 400 or exc.response_body is None:
230
+ return None
231
+
232
+ try:
233
+ payload = json.loads(exc.response_body)
234
+ except json.JSONDecodeError:
235
+ return None
236
+ if not isinstance(payload, dict):
237
+ return None
238
+
239
+ error = payload.get("error")
240
+ if not isinstance(error, dict):
241
+ return None
242
+ if error.get("code") != "json_validate_failed":
243
+ return None
244
+
245
+ failed_generation = error.get("failed_generation")
246
+ if not isinstance(failed_generation, str):
247
+ return None
248
+
249
+ message = error.get("message")
250
+ if not isinstance(message, str) or not message:
251
+ message = "Groq json_validate_failed"
252
+ return message, failed_generation
253
+
254
+
198
255
  def _build_llm_output(
199
256
  *,
200
257
  text: str,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dify-player
3
- Version: 0.3.3
3
+ Version: 0.3.5
4
4
  Summary: Minimal workflow runner for hand-authored Dify-like plans.
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: Jinja2<4,>=3.1
@@ -7,7 +7,7 @@ build-backend = "setuptools.build_meta"
7
7
 
8
8
  [project]
9
9
  name = "dify-player"
10
- version = "0.3.3"
10
+ version = "0.3.5"
11
11
  description = "Minimal workflow runner for hand-authored Dify-like plans."
12
12
  requires-python = ">=3.11"
13
13
  dependencies = [
File without changes
File without changes
File without changes