dv-pipecat-flows 0.0.22.dev2300__tar.gz → 0.0.22.dev2500__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 (89) hide show
  1. {dv_pipecat_flows-0.0.22.dev2300/src/dv_pipecat_flows.egg-info → dv_pipecat_flows-0.0.22.dev2500}/PKG-INFO +1 -1
  2. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500/src/dv_pipecat_flows.egg-info}/PKG-INFO +1 -1
  3. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/manager.py +85 -0
  4. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/types.py +10 -0
  5. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/uv.lock +1185 -109
  6. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/.agents/skills/loki-logs/SKILL.md +0 -0
  7. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/.agents/skills/loki-logs/query-reference.md +0 -0
  8. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/.claude/skills/loki-logs/SKILL.md +0 -0
  9. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/.claude/skills/loki-logs/query-reference.md +0 -0
  10. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/.gitattributes +0 -0
  11. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/.gitignore +0 -0
  12. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/.pre-commit-config.yaml +0 -0
  13. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/.python-version +0 -0
  14. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/.readthedocs.yaml +0 -0
  15. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/AGENTS.md +0 -0
  16. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/CHANGELOG.md +0 -0
  17. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/CLAUDE.md +0 -0
  18. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/CONTRIBUTING.md +0 -0
  19. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/LICENSE +0 -0
  20. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/MANIFEST.in +0 -0
  21. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/README.md +0 -0
  22. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/dev-requirements.txt +0 -0
  23. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/docker-compose.dev.yml +0 -0
  24. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/.eslintrc.json +0 -0
  25. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/.prettierrc +0 -0
  26. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/css/tailwind.css +0 -0
  27. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/examples/food_ordering.json +0 -0
  28. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/examples/movie_explorer.json +0 -0
  29. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/examples/patient_intake.json +0 -0
  30. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/examples/restaurant_reservation.json +0 -0
  31. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/examples/travel_planner.json +0 -0
  32. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/favicon.png +0 -0
  33. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/favicon.svg +0 -0
  34. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/index.html +0 -0
  35. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/editor/canvas.js +0 -0
  36. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/editor/editorState.js +0 -0
  37. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/editor/sidePanel.js +0 -0
  38. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/editor/toolbar.js +0 -0
  39. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/main.js +0 -0
  40. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/nodes/baseNode.js +0 -0
  41. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/nodes/endNode.js +0 -0
  42. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/nodes/flowNode.js +0 -0
  43. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/nodes/functionNode.js +0 -0
  44. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/nodes/index.js +0 -0
  45. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/nodes/mergeNode.js +0 -0
  46. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/nodes/startNode.js +0 -0
  47. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/types.js +0 -0
  48. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/utils/export.js +0 -0
  49. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/utils/helpers.js +0 -0
  50. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/utils/import.js +0 -0
  51. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/js/utils/validation.js +0 -0
  52. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/jsdoc.json +0 -0
  53. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/package-lock.json +0 -0
  54. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/package.json +0 -0
  55. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/postcss.config.cjs +0 -0
  56. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/public/favicon.png +0 -0
  57. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/public/favicon.svg +0 -0
  58. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/tailwind.config.cjs +0 -0
  59. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/vercel.json +0 -0
  60. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/editor/vite.config.js +0 -0
  61. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/engine_primitives_plan.md +0 -0
  62. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/env.example +0 -0
  63. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/images/food-ordering-flow.png +0 -0
  64. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/pipecat-flows.png +0 -0
  65. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/pipecat_upgrade.md +0 -0
  66. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/pyproject.toml +0 -0
  67. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/remote-asterisk-code/README.md +0 -0
  68. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/remote-asterisk-code/extensions.conf +0 -0
  69. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/remote-asterisk-code/rtp.conf +0 -0
  70. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/requirements.txt +0 -0
  71. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/scripts/check-pypi-package.py +0 -0
  72. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/scripts/fix-ruff.sh +0 -0
  73. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/scripts/pre-commit.sh +0 -0
  74. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/setup.cfg +0 -0
  75. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/dv_pipecat_flows.egg-info/SOURCES.txt +0 -0
  76. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/dv_pipecat_flows.egg-info/dependency_links.txt +0 -0
  77. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/dv_pipecat_flows.egg-info/requires.txt +0 -0
  78. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/dv_pipecat_flows.egg-info/top_level.txt +0 -0
  79. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/__init__.py +0 -0
  80. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/actions.py +0 -0
  81. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/adapters.py +0 -0
  82. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/condition_evaluator.py +0 -0
  83. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/exceptions.py +0 -0
  84. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/flow_validator.py +0 -0
  85. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/processors/__init__.py +0 -0
  86. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/processors/router_mode_guard.py +0 -0
  87. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/processors/speak_interruption_guard.py +0 -0
  88. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/processors/user_turn_observer.py +0 -0
  89. {dv_pipecat_flows-0.0.22.dev2300 → dv_pipecat_flows-0.0.22.dev2500}/src/pipecat_flows/router_mode.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dv-pipecat-flows
3
- Version: 0.0.22.dev2300
3
+ Version: 0.0.22.dev2500
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.dev2300
3
+ Version: 0.0.22.dev2500
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
@@ -623,6 +623,7 @@ class FlowManager:
623
623
  transition_to: Optional[str],
624
624
  transition_callback: Optional[Callable] = None,
625
625
  state_update_keys: Optional[List[str]] = None,
626
+ router_node_meta: Optional[Dict[str, Any]] = None,
626
627
  ) -> Callable:
627
628
  """Create a transition function for the given name and handler.
628
629
 
@@ -668,6 +669,7 @@ class FlowManager:
668
669
  # ``_set_node`` after the transition. Mirrors the
669
670
  # ``state.update(extracted)`` that ``_run_router_node`` does
670
671
  # on the non-flattened path.
672
+ extract_update: Dict[str, Any] = {}
671
673
  if state_update_keys and params.arguments:
672
674
  extract_update = {
673
675
  key: params.arguments[key]
@@ -681,6 +683,53 @@ class FlowManager:
681
683
  f"{list(extract_update.keys())} function={name}"
682
684
  )
683
685
 
686
+ # Flattened-router observability: when this function bypasses
687
+ # an llm_router (router_node_meta set by backend wiring), the
688
+ # router was never ``_set_node``'d, so its on_node_entered +
689
+ # on_variables_extracted events never fired naturally. Emit
690
+ # them synthetically here so the FE canvas highlights the
691
+ # bypassed router and displays the extracted variables (e.g.
692
+ # ``state["language"]``) — same visual continuity as the
693
+ # non-flattened classifier path. Gated by the same
694
+ # ``state["observable"]`` flag as the natural fires, so prod
695
+ # calls (no SSE subscriber) skip the publish overhead.
696
+ if router_node_meta and self.state.get("observable"):
697
+ _router_id = router_node_meta.get("id") or router_node_meta.get("name")
698
+ _router_label = router_node_meta.get("name") or _router_id
699
+ _router_kind = router_node_meta.get("kind") or "router_node"
700
+ if self.on_node_entered and _router_id:
701
+ _prev_node_id = self._current_node
702
+ _prev_cfg = (
703
+ self._nodes.get(_prev_node_id) if _prev_node_id else None
704
+ )
705
+ _from_label = (_prev_cfg or {}).get("name") if _prev_cfg else None
706
+ self._fire_and_forget_observe(
707
+ self.on_node_entered(
708
+ {
709
+ "from_node_id": _prev_node_id,
710
+ "from_label": _from_label,
711
+ "node_id": _router_id,
712
+ "label": _router_label,
713
+ "kind": _router_kind,
714
+ "synthetic": "flattened_router",
715
+ "ts": time.time(),
716
+ }
717
+ ),
718
+ label=f"flattened_router_entered:{_router_id}",
719
+ )
720
+ if self.on_variables_extracted and extract_update and _router_id:
721
+ self._fire_and_forget_observe(
722
+ self.on_variables_extracted(
723
+ {
724
+ "node_id": _router_id,
725
+ "variables": dict(extract_update),
726
+ "source": "flattened_router",
727
+ "ts": time.time(),
728
+ }
729
+ ),
730
+ label=f"flattened_router_variables_extracted:{_router_id}",
731
+ )
732
+
684
733
  function_call_id = await start_tracking(
685
734
  transcript_handler=self._transcript_handler,
686
735
  tool_name=name,
@@ -931,6 +980,7 @@ class FlowManager:
931
980
  transition_to: Optional[str] = None,
932
981
  transition_callback: Optional[Callable] = None,
933
982
  state_update_keys: Optional[List[str]] = None,
983
+ router_node_meta: Optional[Dict[str, Any]] = None,
934
984
  ) -> None:
935
985
  """Register a function with the LLM if not already registered.
936
986
 
@@ -959,6 +1009,7 @@ class FlowManager:
959
1009
  transition_to,
960
1010
  transition_callback,
961
1011
  state_update_keys=state_update_keys,
1012
+ router_node_meta=router_node_meta,
962
1013
  )
963
1014
 
964
1015
  # Register function with LLM (or LLMSwitcher).
@@ -2535,6 +2586,39 @@ In all of these cases, you can provide a `name` in your new node's config for de
2535
2586
  await self._short_circuit_to(pure_code_target)
2536
2587
  return
2537
2588
 
2589
+ # ``pure_code_target is None`` for a node that SHOULD be
2590
+ # pure-code-dispatched is an author-config failure: condition
2591
+ # router with no matching rule + no ``router_default_next``
2592
+ # (or default points at a deleted node and the backend's
2593
+ # ``_resolve_node_ref`` returned None), or an action node
2594
+ # with success/failure both pointing at deleted targets.
2595
+ # Falling through to LLM dispatch below makes no sense — these
2596
+ # nodes have ``task_messages: []`` (no LLM context), so the
2597
+ # bot just sits silent until ``user_idle_processor`` fires
2598
+ # the generic "Sorry, could you please repeat that?" prompt.
2599
+ # End the call gracefully with a logged error so the misconfig
2600
+ # is visible instead of silently degrading.
2601
+ auto_transition = node_config.get("auto_transition")
2602
+ if auto_transition == "__condition__" or isinstance(auto_transition, dict):
2603
+ self._current_node = node_id
2604
+ logger.error(
2605
+ f"Pure-code dispatch on '{node_id}' resolved no target "
2606
+ f"(auto_transition={auto_transition!r}). Ending the call "
2607
+ f"gracefully — this is an author-config error: a condition "
2608
+ f"router with no matching rule + no valid router_default_next, "
2609
+ f"OR an action node whose success/failure targets were deleted."
2610
+ )
2611
+ try:
2612
+ await self._action_manager.execute_actions(
2613
+ [{"type": "end_conversation"}]
2614
+ )
2615
+ except Exception as end_exc:
2616
+ logger.warning(
2617
+ f"end_conversation action failed during graceful-end on "
2618
+ f"'{node_id}': {end_exc!r}"
2619
+ )
2620
+ return
2621
+
2538
2622
  # Router-mode LLM short-circuit: if this node uses constrained
2539
2623
  # JSON output (llm_mode="router"), run the small classification
2540
2624
  # call, parse the response, recurse into the chosen branch.
@@ -2611,6 +2695,7 @@ In all of these cases, you can provide a `name` in your new node's config for de
2611
2695
  transition_to=schema.transition_to,
2612
2696
  transition_callback=schema.transition_callback,
2613
2697
  state_update_keys=schema.state_update_keys,
2698
+ router_node_meta=schema.router_node_meta,
2614
2699
  )
2615
2700
 
2616
2701
  async def register_direct_function(func):
@@ -279,6 +279,16 @@ class FlowsFunctionSchema:
279
279
  # transitions and still propagate the router's ``router_extract``
280
280
  # variables (e.g. ``language``) into state. Empty/None = no-op.
281
281
  state_update_keys: Optional[List[str]] = None
282
+ # Identity of the LLM-router this function bypassed in the flatten path
283
+ # (``agent_node → llm_router``). When set, the engine emits a synthetic
284
+ # ``on_node_entered`` for the router and an ``on_variables_extracted``
285
+ # for the LLM's args at function-call time — so the FE canvas still
286
+ # highlights the bypassed router AND displays the extracted variables
287
+ # (e.g. "language") even though the router's classifier turn never ran.
288
+ # Shape: ``{"id": <node_uuid>, "name": <node_name>, "kind": "router_node"}``
289
+ # None means this function is a direct agent→non-router transition;
290
+ # no synthetic events fire.
291
+ router_node_meta: Optional[Dict[str, Any]] = None
282
292
 
283
293
  def __post_init__(self):
284
294
  """Validate the schema configuration.