dv-pipecat-flows 0.0.22.dev1509__tar.gz → 0.0.22.dev1511__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 (91) hide show
  1. {dv_pipecat_flows-0.0.22.dev1509/src/dv_pipecat_flows.egg-info → dv_pipecat_flows-0.0.22.dev1511}/PKG-INFO +1 -1
  2. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511/src/dv_pipecat_flows.egg-info}/PKG-INFO +1 -1
  3. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/dv_pipecat_flows.egg-info/scm_file_list.json +1 -0
  4. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/dv_pipecat_flows.egg-info/scm_version.json +2 -2
  5. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/manager.py +13 -2
  6. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/router_mode.py +21 -2
  7. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/.agents/skills/loki-logs/SKILL.md +0 -0
  8. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/.agents/skills/loki-logs/query-reference.md +0 -0
  9. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/.claude/skills/loki-logs/SKILL.md +0 -0
  10. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/.claude/skills/loki-logs/query-reference.md +0 -0
  11. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/.gitattributes +0 -0
  12. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/.gitignore +0 -0
  13. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/.pre-commit-config.yaml +0 -0
  14. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/.python-version +0 -0
  15. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/.readthedocs.yaml +0 -0
  16. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/AGENTS.md +0 -0
  17. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/CHANGELOG.md +0 -0
  18. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/CLAUDE.md +0 -0
  19. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/CONTRIBUTING.md +0 -0
  20. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/LICENSE +0 -0
  21. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/MANIFEST.in +0 -0
  22. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/README.md +0 -0
  23. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/dev-requirements.txt +0 -0
  24. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/docker-compose.dev.yml +0 -0
  25. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/.eslintrc.json +0 -0
  26. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/.prettierrc +0 -0
  27. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/css/tailwind.css +0 -0
  28. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/examples/food_ordering.json +0 -0
  29. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/examples/movie_explorer.json +0 -0
  30. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/examples/patient_intake.json +0 -0
  31. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/examples/restaurant_reservation.json +0 -0
  32. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/examples/travel_planner.json +0 -0
  33. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/favicon.png +0 -0
  34. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/favicon.svg +0 -0
  35. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/index.html +0 -0
  36. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/editor/canvas.js +0 -0
  37. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/editor/editorState.js +0 -0
  38. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/editor/sidePanel.js +0 -0
  39. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/editor/toolbar.js +0 -0
  40. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/main.js +0 -0
  41. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/nodes/baseNode.js +0 -0
  42. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/nodes/endNode.js +0 -0
  43. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/nodes/flowNode.js +0 -0
  44. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/nodes/functionNode.js +0 -0
  45. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/nodes/index.js +0 -0
  46. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/nodes/mergeNode.js +0 -0
  47. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/nodes/startNode.js +0 -0
  48. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/types.js +0 -0
  49. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/utils/export.js +0 -0
  50. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/utils/helpers.js +0 -0
  51. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/utils/import.js +0 -0
  52. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/js/utils/validation.js +0 -0
  53. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/jsdoc.json +0 -0
  54. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/package-lock.json +0 -0
  55. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/package.json +0 -0
  56. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/postcss.config.cjs +0 -0
  57. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/public/favicon.png +0 -0
  58. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/public/favicon.svg +0 -0
  59. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/tailwind.config.cjs +0 -0
  60. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/vercel.json +0 -0
  61. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/editor/vite.config.js +0 -0
  62. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/engine_primitives_plan.md +0 -0
  63. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/env.example +0 -0
  64. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/images/food-ordering-flow.png +0 -0
  65. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/pipecat-flows.png +0 -0
  66. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/pipecat_upgrade.md +0 -0
  67. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/pyproject.toml +0 -0
  68. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/remote-asterisk-code/README.md +0 -0
  69. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/remote-asterisk-code/extensions.conf +0 -0
  70. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/remote-asterisk-code/rtp.conf +0 -0
  71. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/requirements.txt +0 -0
  72. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/scripts/check-pypi-package.py +0 -0
  73. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/scripts/fix-ruff.sh +0 -0
  74. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/scripts/pre-commit.sh +0 -0
  75. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/setup.cfg +0 -0
  76. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/dv_pipecat_flows.egg-info/SOURCES.txt +0 -0
  77. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/dv_pipecat_flows.egg-info/dependency_links.txt +0 -0
  78. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/dv_pipecat_flows.egg-info/requires.txt +0 -0
  79. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/dv_pipecat_flows.egg-info/top_level.txt +0 -0
  80. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/__init__.py +0 -0
  81. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/actions.py +0 -0
  82. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/adapters.py +0 -0
  83. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/condition_evaluator.py +0 -0
  84. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/exceptions.py +0 -0
  85. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/flow_validator.py +0 -0
  86. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/processors/__init__.py +0 -0
  87. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/processors/router_mode_guard.py +0 -0
  88. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/processors/speak_interruption_guard.py +0 -0
  89. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/processors/user_turn_observer.py +0 -0
  90. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/src/pipecat_flows/types.py +0 -0
  91. {dv_pipecat_flows-0.0.22.dev1509 → dv_pipecat_flows-0.0.22.dev1511}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dv-pipecat-flows
3
- Version: 0.0.22.dev1509
3
+ Version: 0.0.22.dev1511
4
4
  Summary: Conversation Flow management for Pipecat AI applications
5
5
  License: BSD 2-Clause License
6
6
  Project-URL: Source, https://github.com/pipecat-ai/pipecat-flows
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dv-pipecat-flows
3
- Version: 0.0.22.dev1509
3
+ Version: 0.0.22.dev1511
4
4
  Summary: Conversation Flow management for Pipecat AI applications
5
5
  License: BSD 2-Clause License
6
6
  Project-URL: Source, https://github.com/pipecat-ai/pipecat-flows
@@ -41,6 +41,7 @@
41
41
  "k8s/dv-pipecat/templates/keda-trigger-auth.yaml",
42
42
  "k8s/dv-pipecat/templates/hpa.yaml",
43
43
  "k8s/dv-pipecat/templates/_helpers.tpl",
44
+ "tests/test_router_no_unclear.py",
44
45
  "tests/test_voicemail_detector.py",
45
46
  "tests/test_tts_split_cache.py",
46
47
  "tests/test_router_extract_schema.py",
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "tag": "0.0.21",
3
- "distance": 1509,
4
- "node": "g5fc5cdef669f8cf54cef9f14d999270d311db705",
3
+ "distance": 1511,
4
+ "node": "gc73d1ea4d386bcd47927d9d6ac461ec609da0f3f",
5
5
  "dirty": false,
6
6
  "branch": "feat/phone_call_tool",
7
7
  "node_date": "2026-06-23"
@@ -1779,9 +1779,20 @@ In all of these cases, you can provide a `name` in your new node's config for de
1779
1779
  f"{system_prompt}"
1780
1780
  )
1781
1781
 
1782
- schema = build_router_response_schema(branches, extract)
1782
+ # An agent-fed router configures no fallback (unclear/exhausted/reprompt
1783
+ # all unset) — omit __unclear__ so the classifier must commit to a real
1784
+ # branch. Routers with a fallback keep __unclear__ + the retry loop.
1785
+ include_unclear = bool(
1786
+ node_config.get("router_unclear_next")
1787
+ or node_config.get("router_exhausted_next")
1788
+ or node_config.get("router_reprompt_message")
1789
+ )
1790
+ schema = build_router_response_schema(
1791
+ branches, extract, include_unclear=include_unclear
1792
+ )
1783
1793
  valid_branch_ids = [b["id"] for b in branches if isinstance(b, dict) and b.get("id")]
1784
- valid_branch_ids.append(UNCLEAR_BRANCH_ID)
1794
+ if include_unclear:
1795
+ valid_branch_ids.append(UNCLEAR_BRANCH_ID)
1785
1796
 
1786
1797
  # Per-node unclear-attempt bookkeeping lives on the FlowManager so it
1787
1798
  # survives across _set_node calls (re-entry after a re-prompt loop).
@@ -68,6 +68,7 @@ _ISO_DATE_HINT = "Return as an ISO 8601 date (YYYY-MM-DD)."
68
68
  def build_router_response_schema(
69
69
  branches: List[RouterBranch],
70
70
  extract: Optional[Dict[str, ExtractSpec]] = None,
71
+ include_unclear: bool = True,
71
72
  ) -> Dict[str, Any]:
72
73
  """Build the JSON Schema the router LLM is constrained to.
73
74
 
@@ -84,7 +85,7 @@ def build_router_response_schema(
84
85
  "additionalProperties": false
85
86
  }
86
87
 
87
- The ``__unclear__`` sentinel is always included as a valid branch so the
88
+ The ``__unclear__`` sentinel is normally included as a valid branch so the
88
89
  LLM has a way to say "none of these" without violating the schema; the
89
90
  engine routes it to ``router_unclear_node``.
90
91
 
@@ -92,13 +93,17 @@ def build_router_response_schema(
92
93
  branches: NodeConfig ``router_branches`` list.
93
94
  extract: NodeConfig ``router_extract`` map (name -> ExtractSpec).
94
95
  Empty / None -> ``extracted`` is an empty object schema.
96
+ include_unclear: When False, ``__unclear__`` is OMITTED from the enum so
97
+ the classifier must commit to a real branch. Set for routers fed by
98
+ an ``agent_node`` (no fallback configured): the agent's free-form turn
99
+ already gathered context, so there is no unclear/reprompt/retry path.
95
100
 
96
101
  Returns:
97
102
  JSON Schema dict. Adapters re-shape this per provider in their
98
103
  ``format_router_call`` overrides.
99
104
  """
100
105
  branch_ids = [b.get("id") for b in (branches or []) if isinstance(b, dict) and b.get("id")]
101
- if UNCLEAR_BRANCH_ID not in branch_ids:
106
+ if include_unclear and UNCLEAR_BRANCH_ID not in branch_ids:
102
107
  branch_ids.append(UNCLEAR_BRANCH_ID)
103
108
 
104
109
  extracted_props: Dict[str, Any] = {}
@@ -270,6 +275,20 @@ def pick_branch_target(
270
275
  return br.get("next")
271
276
 
272
277
  if branch_id == UNCLEAR_BRANCH_ID:
278
+ # Agent-fed routers configure NO fallback (unclear/exhausted/reprompt all
279
+ # unset) and the schema omits __unclear__, so this branch is only
280
+ # reachable if a provider ignores the constraint. Commit to the first
281
+ # real branch instead of dead-ending on a None target.
282
+ has_fallback = bool(
283
+ node_config.get("router_unclear_next")
284
+ or node_config.get("router_exhausted_next")
285
+ or node_config.get("router_reprompt_message")
286
+ )
287
+ if not has_fallback:
288
+ for br in branches:
289
+ if isinstance(br, dict) and br.get("next"):
290
+ return br.get("next")
291
+ return None
273
292
  attempts = attempt_state.get(node_id, 0) + 1
274
293
  attempt_state[node_id] = attempts
275
294
  # NB: field names match what the backend lowerer emits (see