dv-pipecat-flows 0.0.0.dev2786__tar.gz → 0.0.0.dev2810__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 (128) hide show
  1. {dv_pipecat_flows-0.0.0.dev2786/src/dv_pipecat_flows.egg-info → dv_pipecat_flows-0.0.0.dev2810}/PKG-INFO +1 -1
  2. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810/src/dv_pipecat_flows.egg-info}/PKG-INFO +1 -1
  3. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/dv_pipecat_flows.egg-info/scm_file_list.json +4 -0
  4. dv_pipecat_flows-0.0.0.dev2810/src/dv_pipecat_flows.egg-info/scm_version.json +8 -0
  5. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/manager.py +61 -21
  6. dv_pipecat_flows-0.0.0.dev2786/src/dv_pipecat_flows.egg-info/scm_version.json +0 -8
  7. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/.agents/skills/loki-logs/SKILL.md +0 -0
  8. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/.agents/skills/loki-logs/query-reference.md +0 -0
  9. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/.claude/skills/loki-logs/SKILL.md +0 -0
  10. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/.claude/skills/loki-logs/query-reference.md +0 -0
  11. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/.gitattributes +0 -0
  12. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/.gitignore +0 -0
  13. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/.pre-commit-config.yaml +0 -0
  14. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/.python-version +0 -0
  15. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/.readthedocs.yaml +0 -0
  16. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/AGENTS.md +0 -0
  17. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/CHANGELOG.md +0 -0
  18. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/CLAUDE.md +0 -0
  19. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/CONTRIBUTING.md +0 -0
  20. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/LICENSE +0 -0
  21. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/MANIFEST.in +0 -0
  22. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/README.md +0 -0
  23. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/.env.example +0 -0
  24. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/.gitignore +0 -0
  25. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/README.md +0 -0
  26. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/docs/ARCHITECTURE.md +0 -0
  27. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/docs/CODE_MAP.md +0 -0
  28. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/docs/CONFIG.md +0 -0
  29. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/docs/CONTRACTS.md +0 -0
  30. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/docs/COPILOT_TODO.md +0 -0
  31. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/docs/DISTRIBUTION.md +0 -0
  32. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/docs/HLD.md +0 -0
  33. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/docs/METHODS.md +0 -0
  34. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/docs/VOICE_E2E.md +0 -0
  35. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/ANALYSIS_stagehand_vs_hybrid.md +0 -0
  36. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/RESULTS.md +0 -0
  37. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/_env.py +0 -0
  38. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/bench.py +0 -0
  39. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/bench_browseruse.py +0 -0
  40. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/bench_stagehand.py +0 -0
  41. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/inspect_browseruse.py +0 -0
  42. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/inspect_browseruse_showcase.py +0 -0
  43. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/inspect_stagehand_prompt.py +0 -0
  44. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/pages/checkout.html +0 -0
  45. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/pages/dashboard.html +0 -0
  46. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/pages/signup.html +0 -0
  47. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/results_browseruse.json +0 -0
  48. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/results_perception.json +0 -0
  49. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/results_stagehand.json +0 -0
  50. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/tasks.py +0 -0
  51. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/try_hybrid.py +0 -0
  52. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/try_hybrid_multistep.py +0 -0
  53. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/eval/try_hybrid_oneshot.py +0 -0
  54. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/pyproject.toml +0 -0
  55. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/scripts/dev-stack.sh +0 -0
  56. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/browser_copilot/uv.lock +0 -0
  57. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/dev-requirements.txt +0 -0
  58. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/docker-compose.dev.yml +0 -0
  59. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/.eslintrc.json +0 -0
  60. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/.prettierrc +0 -0
  61. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/css/tailwind.css +0 -0
  62. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/examples/food_ordering.json +0 -0
  63. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/examples/movie_explorer.json +0 -0
  64. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/examples/patient_intake.json +0 -0
  65. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/examples/restaurant_reservation.json +0 -0
  66. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/examples/travel_planner.json +0 -0
  67. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/favicon.png +0 -0
  68. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/favicon.svg +0 -0
  69. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/index.html +0 -0
  70. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/editor/canvas.js +0 -0
  71. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/editor/editorState.js +0 -0
  72. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/editor/sidePanel.js +0 -0
  73. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/editor/toolbar.js +0 -0
  74. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/main.js +0 -0
  75. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/nodes/baseNode.js +0 -0
  76. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/nodes/endNode.js +0 -0
  77. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/nodes/flowNode.js +0 -0
  78. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/nodes/functionNode.js +0 -0
  79. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/nodes/index.js +0 -0
  80. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/nodes/mergeNode.js +0 -0
  81. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/nodes/startNode.js +0 -0
  82. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/types.js +0 -0
  83. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/utils/export.js +0 -0
  84. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/utils/helpers.js +0 -0
  85. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/utils/import.js +0 -0
  86. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/js/utils/validation.js +0 -0
  87. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/jsdoc.json +0 -0
  88. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/package-lock.json +0 -0
  89. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/package.json +0 -0
  90. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/postcss.config.cjs +0 -0
  91. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/public/favicon.png +0 -0
  92. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/public/favicon.svg +0 -0
  93. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/tailwind.config.cjs +0 -0
  94. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/vercel.json +0 -0
  95. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/editor/vite.config.js +0 -0
  96. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/engine_primitives_plan.md +0 -0
  97. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/env.example +0 -0
  98. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/images/food-ordering-flow.png +0 -0
  99. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/pipecat-flows.png +0 -0
  100. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/pipecat_upgrade.md +0 -0
  101. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/pyproject.toml +0 -0
  102. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/remote-asterisk-code/README.md +0 -0
  103. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/remote-asterisk-code/extensions.conf +0 -0
  104. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/remote-asterisk-code/rtp.conf +0 -0
  105. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/requirements.txt +0 -0
  106. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/scripts/azure_latency_probe.py +0 -0
  107. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/scripts/check-pypi-package.py +0 -0
  108. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/scripts/fix-ruff.sh +0 -0
  109. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/scripts/langfuse_export.py +0 -0
  110. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/scripts/pre-commit.sh +0 -0
  111. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/setup.cfg +0 -0
  112. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/dv_pipecat_flows.egg-info/SOURCES.txt +0 -0
  113. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/dv_pipecat_flows.egg-info/dependency_links.txt +0 -0
  114. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/dv_pipecat_flows.egg-info/requires.txt +0 -0
  115. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/dv_pipecat_flows.egg-info/top_level.txt +0 -0
  116. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/__init__.py +0 -0
  117. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/actions.py +0 -0
  118. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/adapters.py +0 -0
  119. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/condition_evaluator.py +0 -0
  120. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/exceptions.py +0 -0
  121. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/flow_validator.py +0 -0
  122. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/processors/__init__.py +0 -0
  123. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/processors/router_mode_guard.py +0 -0
  124. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/processors/speak_interruption_guard.py +0 -0
  125. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/processors/user_turn_observer.py +0 -0
  126. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/router_mode.py +0 -0
  127. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/src/pipecat_flows/types.py +0 -0
  128. {dv_pipecat_flows-0.0.0.dev2786 → dv_pipecat_flows-0.0.0.dev2810}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dv-pipecat-flows
3
- Version: 0.0.0.dev2786
3
+ Version: 0.0.0.dev2810
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.0.dev2786
3
+ Version: 0.0.0.dev2810
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
@@ -359,6 +359,7 @@
359
359
  "ringg-bot/test_bot.py",
360
360
  "ringg-bot/tests/__init__.py",
361
361
  "ringg-bot/tests/conftest.py",
362
+ "ringg-bot/tests/test_abandoned_call_report.py",
362
363
  "ringg-bot/tests/test_action_call_variables.py",
363
364
  "ringg-bot/tests/test_app_metrics.py",
364
365
  "ringg-bot/tests/test_artifact_store.py",
@@ -383,6 +384,7 @@
383
384
  "ringg-bot/tests/test_end_call_schema.py",
384
385
  "ringg-bot/tests/test_env_config_asterisk_ami.py",
385
386
  "ringg-bot/tests/test_execute_plan.py",
387
+ "ringg-bot/tests/test_find_button_api_config.py",
386
388
  "ringg-bot/tests/test_flow_query_kb.py",
387
389
  "ringg-bot/tests/test_gcs_fetch.py",
388
390
  "ringg-bot/tests/test_http_client_diagnostics.py",
@@ -554,6 +556,7 @@
554
556
  "ringg-bot/utils/tts.py",
555
557
  "ringg-bot/utils/twilio_async_client.py",
556
558
  "ringg-bot/utils/warning_messages.py",
559
+ "ringg-bot/utils/widget_transcript.py",
557
560
  "ringg-bot/utils/word_timestamp_logger.py",
558
561
  "ringg-bot/voice_services/asterisk/asterisk_service.py",
559
562
  "ringg-bot/voice_services/asterisk/router.py",
@@ -648,6 +651,7 @@
648
651
  "tests/test_response_formatters.py",
649
652
  "tests/test_router_extract_schema.py",
650
653
  "tests/test_router_no_unclear.py",
654
+ "tests/test_router_wait_idle.py",
651
655
  "tests/test_tts_split_cache.py",
652
656
  "tests/test_voicemail_detector.py",
653
657
  "uv.lock"
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.0.0.dev0",
3
+ "distance": 2810,
4
+ "node": "gc326546704e7e1a6ee5805d1a16c7803d01dd4ae",
5
+ "dirty": false,
6
+ "branch": "dv-stage",
7
+ "node_date": "2026-08-12"
8
+ }
@@ -1872,6 +1872,24 @@ In all of these cases, you can provide a `name` in your new node's config for de
1872
1872
  label="jump",
1873
1873
  )
1874
1874
 
1875
+ def _last_context_role(self) -> Optional[str]:
1876
+ """Role of the last message in the live LLM context, or None when no
1877
+ context aggregator / empty context. Used by the router wait gate to
1878
+ tell a real committed user turn apart from system-generated context
1879
+ pushes (e.g. the idle warning's LLM-path append)."""
1880
+ if not self._context_aggregator:
1881
+ return None
1882
+ ctx = self._context_aggregator.user()._context
1883
+ messages = (
1884
+ ctx.get_messages() if hasattr(ctx, "get_messages") else getattr(ctx, "messages", [])
1885
+ )
1886
+ if not messages:
1887
+ return None
1888
+ last = messages[-1]
1889
+ if isinstance(last, dict):
1890
+ return last.get("role")
1891
+ return getattr(last, "role", None)
1892
+
1875
1893
  async def _run_router_node(
1876
1894
  self, node_id: str, node_config: Dict[str, Any]
1877
1895
  ) -> Optional[str]:
@@ -1905,10 +1923,19 @@ In all of these cases, you can provide a `name` in your new node's config for de
1905
1923
  # `_run_router_node` captures a fresh entry_ts — the next iteration
1906
1924
  # correctly waits for a NEW user reply instead of reclassifying the
1907
1925
  # stale one that triggered the previous UNCLEAR.
1926
+ #
1927
+ # Silence handling is delegated to the user-idle processor: we re-arm
1928
+ # it for the duration of the wait (it was stopped at `_set_node`
1929
+ # entry) and block until the user actually replies. If they never do,
1930
+ # the idle processor's warning → end stages fire and end the call —
1931
+ # the router never classifies stale silence. The idle warning's
1932
+ # fixed-phrase TTSSpeakFrame passes RouterModeGuard; its LLM-path
1933
+ # fallback (realtime/chat-only/unsupported languages) is dropped by
1934
+ # the guard, so that warning is silent but the end stage still ends
1935
+ # the call.
1908
1936
  observer = self._user_turn_observer
1909
1937
 
1910
- timeout_s = float(node_config.get("router_wait_for_user_timeout", 15.0))
1911
- if observer is not None and timeout_s > 0:
1938
+ if observer is not None:
1912
1939
  entry_ts = time.monotonic()
1913
1940
  if observer.last_user_stopped_ts >= entry_ts:
1914
1941
  logger.debug(
@@ -1929,28 +1956,41 @@ In all of these cases, you can provide a `name` in your new node's config for de
1929
1956
  )
1930
1957
  else:
1931
1958
  logger.debug(
1932
- f"Router '{node_id}': waiting up to {timeout_s}s for "
1933
- f"UserStoppedSpeakingFrame"
1959
+ f"Router '{node_id}': waiting for "
1960
+ f"UserStoppedSpeakingFrame (idle processor armed)"
1934
1961
  )
1962
+ await self._task.queue_frame(StartUserIdleProcessorFrame())
1935
1963
  try:
1936
- await asyncio.wait_for(
1937
- observer.event.wait(), timeout=timeout_s
1938
- )
1939
- logger.debug(
1940
- f"Router '{node_id}': user reply received after "
1941
- f"{time.monotonic() - entry_ts:.2f}s"
1942
- )
1943
- except asyncio.TimeoutError:
1944
- # User stayed silent. Don't raise — let the router
1945
- # LLM classify whatever context is available; it
1946
- # will most likely return UNCLEAR, which the
1947
- # existing pick_branch_target machinery routes to
1948
- # reprompt or exhausted_node.
1949
- logger.info(
1950
- f"Router '{node_id}': no user reply within "
1951
- f"{timeout_s}s; proceeding (will likely route "
1952
- f"to unclear/exhausted)"
1964
+ while True:
1965
+ await observer.event.wait()
1966
+ # The observer fires on EVERY OpenAILLMContextFrame,
1967
+ # and with idle armed there IS a competing source:
1968
+ # the idle warning's LLM path (chat-only sessions,
1969
+ # realtime LLMs) appends its prompt with
1970
+ # run_llm=True, which makes the user aggregator push
1971
+ # a context frame with NO new user turn. Accept the
1972
+ # wake only when the last context message is the
1973
+ # user's; otherwise keep waiting for the real reply
1974
+ # (or for idle end-stage to end the call).
1975
+ role = self._last_context_role()
1976
+ if role is None or role == "user":
1977
+ break
1978
+ logger.debug(
1979
+ f"Router '{node_id}': ignoring context push "
1980
+ f"with last role '{role}' (idle warning, not a "
1981
+ f"user reply); still waiting"
1982
+ )
1983
+ observer.event.clear()
1984
+ finally:
1985
+ # Restore the "idle stopped while the node is
1986
+ # processing" invariant for the classifier call.
1987
+ await self._task.queue_frame(
1988
+ StopUserIdleProcessorFrame()
1953
1989
  )
1990
+ logger.debug(
1991
+ f"Router '{node_id}': user reply received after "
1992
+ f"{time.monotonic() - entry_ts:.2f}s"
1993
+ )
1954
1994
 
1955
1995
  branches = node_config.get("router_branches") or []
1956
1996
  extract = node_config.get("router_extract") or {}
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.0.0.dev0",
3
- "distance": 2786,
4
- "node": "g4f35e028c126047efd7781c8674fba2a380c5e99",
5
- "dirty": false,
6
- "branch": "dv-stage",
7
- "node_date": "2026-08-10"
8
- }