dv-pipecat-flows 0.0.23.dev6__tar.gz → 0.0.23.dev8__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 (92) hide show
  1. {dv_pipecat_flows-0.0.23.dev6/src/dv_pipecat_flows.egg-info → dv_pipecat_flows-0.0.23.dev8}/PKG-INFO +1 -2
  2. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/README.md +0 -1
  3. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8/src/dv_pipecat_flows.egg-info}/PKG-INFO +1 -2
  4. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/dv_pipecat_flows.egg-info/scm_file_list.json +19 -0
  5. dv_pipecat_flows-0.0.23.dev8/src/dv_pipecat_flows.egg-info/scm_version.json +8 -0
  6. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/actions.py +7 -0
  7. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/manager.py +16 -0
  8. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/router_mode.py +12 -3
  9. dv_pipecat_flows-0.0.23.dev6/src/dv_pipecat_flows.egg-info/scm_version.json +0 -8
  10. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/.agents/skills/loki-logs/SKILL.md +0 -0
  11. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/.agents/skills/loki-logs/query-reference.md +0 -0
  12. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/.claude/skills/loki-logs/SKILL.md +0 -0
  13. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/.claude/skills/loki-logs/query-reference.md +0 -0
  14. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/.gitattributes +0 -0
  15. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/.gitignore +0 -0
  16. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/.pre-commit-config.yaml +0 -0
  17. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/.python-version +0 -0
  18. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/.readthedocs.yaml +0 -0
  19. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/AGENTS.md +0 -0
  20. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/CHANGELOG.md +0 -0
  21. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/CLAUDE.md +0 -0
  22. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/CONTRIBUTING.md +0 -0
  23. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/LICENSE +0 -0
  24. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/MANIFEST.in +0 -0
  25. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/dev-requirements.txt +0 -0
  26. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/docker-compose.dev.yml +0 -0
  27. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/.eslintrc.json +0 -0
  28. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/.prettierrc +0 -0
  29. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/css/tailwind.css +0 -0
  30. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/examples/food_ordering.json +0 -0
  31. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/examples/movie_explorer.json +0 -0
  32. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/examples/patient_intake.json +0 -0
  33. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/examples/restaurant_reservation.json +0 -0
  34. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/examples/travel_planner.json +0 -0
  35. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/favicon.png +0 -0
  36. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/favicon.svg +0 -0
  37. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/index.html +0 -0
  38. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/editor/canvas.js +0 -0
  39. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/editor/editorState.js +0 -0
  40. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/editor/sidePanel.js +0 -0
  41. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/editor/toolbar.js +0 -0
  42. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/main.js +0 -0
  43. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/nodes/baseNode.js +0 -0
  44. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/nodes/endNode.js +0 -0
  45. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/nodes/flowNode.js +0 -0
  46. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/nodes/functionNode.js +0 -0
  47. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/nodes/index.js +0 -0
  48. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/nodes/mergeNode.js +0 -0
  49. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/nodes/startNode.js +0 -0
  50. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/types.js +0 -0
  51. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/utils/export.js +0 -0
  52. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/utils/helpers.js +0 -0
  53. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/utils/import.js +0 -0
  54. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/js/utils/validation.js +0 -0
  55. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/jsdoc.json +0 -0
  56. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/package-lock.json +0 -0
  57. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/package.json +0 -0
  58. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/postcss.config.cjs +0 -0
  59. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/public/favicon.png +0 -0
  60. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/public/favicon.svg +0 -0
  61. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/tailwind.config.cjs +0 -0
  62. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/vercel.json +0 -0
  63. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/editor/vite.config.js +0 -0
  64. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/engine_primitives_plan.md +0 -0
  65. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/env.example +0 -0
  66. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/images/food-ordering-flow.png +0 -0
  67. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/pipecat-flows.png +0 -0
  68. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/pipecat_upgrade.md +0 -0
  69. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/pyproject.toml +0 -0
  70. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/remote-asterisk-code/README.md +0 -0
  71. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/remote-asterisk-code/extensions.conf +0 -0
  72. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/remote-asterisk-code/rtp.conf +0 -0
  73. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/requirements.txt +0 -0
  74. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/scripts/check-pypi-package.py +0 -0
  75. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/scripts/fix-ruff.sh +0 -0
  76. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/scripts/pre-commit.sh +0 -0
  77. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/setup.cfg +0 -0
  78. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/dv_pipecat_flows.egg-info/SOURCES.txt +0 -0
  79. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/dv_pipecat_flows.egg-info/dependency_links.txt +0 -0
  80. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/dv_pipecat_flows.egg-info/requires.txt +0 -0
  81. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/dv_pipecat_flows.egg-info/top_level.txt +0 -0
  82. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/__init__.py +0 -0
  83. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/adapters.py +0 -0
  84. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/condition_evaluator.py +0 -0
  85. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/exceptions.py +0 -0
  86. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/flow_validator.py +0 -0
  87. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/processors/__init__.py +0 -0
  88. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/processors/router_mode_guard.py +0 -0
  89. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/processors/speak_interruption_guard.py +0 -0
  90. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/processors/user_turn_observer.py +0 -0
  91. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/src/pipecat_flows/types.py +0 -0
  92. {dv_pipecat_flows-0.0.23.dev6 → dv_pipecat_flows-0.0.23.dev8}/uv.lock +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dv-pipecat-flows
3
- Version: 0.0.23.dev6
3
+ Version: 0.0.23.dev8
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
@@ -309,4 +309,3 @@ We aim to review all contributions promptly and provide constructive feedback to
309
309
  ➡️ [Reach us on X](https://x.com/pipecat_ai)
310
310
 
311
311
 
312
-
@@ -284,4 +284,3 @@ We aim to review all contributions promptly and provide constructive feedback to
284
284
  ➡️ [Reach us on X](https://x.com/pipecat_ai)
285
285
 
286
286
 
287
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dv-pipecat-flows
3
- Version: 0.0.23.dev6
3
+ Version: 0.0.23.dev8
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
@@ -309,4 +309,3 @@ We aim to review all contributions promptly and provide constructive feedback to
309
309
  ➡️ [Reach us on X](https://x.com/pipecat_ai)
310
310
 
311
311
 
312
-
@@ -22,6 +22,7 @@
22
22
  ".readthedocs.yaml",
23
23
  "env.example",
24
24
  "images/food-ordering-flow.png",
25
+ "k8s/docs/deepgram-self-hosted-restore.md",
25
26
  "k8s/livekit/Chart.yaml",
26
27
  "k8s/livekit/README.md",
27
28
  "k8s/livekit/values.yaml",
@@ -93,10 +94,13 @@
93
94
  "docs/ASTERISK_OUTBOUND_CHAN_WEBSOCKET.md",
94
95
  "docs/ASTERISK_MACHINE_SETUP.md",
95
96
  "docs/CALL_TRANSFER_SUMMARY_DESIGN.md",
97
+ "docs/blockkit-agents-cdn-integration.md",
96
98
  "docs/make.bat",
97
99
  "docs/build-docs.sh",
98
100
  "docs/AZURE_MULTI_REGION_ROUTING.md",
99
101
  "docs/examples/pb_fintech_call_transfer_config.json",
102
+ "docs/superpowers/plans/2026-07-11-timeout-connection-diagnostics.md",
103
+ "docs/superpowers/specs/2026-07-11-timeout-connection-diagnostics-design.md",
100
104
  "ringg-bot/server.py",
101
105
  "ringg-bot/pipeline_test.py",
102
106
  "ringg-bot/pytest.ini",
@@ -158,6 +162,7 @@
158
162
  "ringg-bot/ringg_processors/openai_realtime_transcript_filter.py",
159
163
  "ringg-bot/ringg_processors/realtime_tts_bridge.py",
160
164
  "ringg-bot/ringg_processors/two_stage_user_idle_processor.py",
165
+ "ringg-bot/ringg_processors/realtime_audio_suppressor.py",
161
166
  "ringg-bot/ringg_processors/function_call_filler_processor.py",
162
167
  "ringg-bot/ringg_processors/screen_auto_injector.py",
163
168
  "ringg-bot/ringg_processors/livekit_caption_observer.py",
@@ -209,13 +214,19 @@
209
214
  "ringg-bot/voice_services/twilio/router.py",
210
215
  "ringg-bot/voice_services/twilio/twilio_service.py",
211
216
  "ringg-bot/transports/factory.py",
217
+ "ringg-bot/tests/test_http_client_diagnostics.py",
212
218
  "ringg-bot/tests/test_tts_currency.py",
213
219
  "ringg-bot/tests/test_azure_region_routing.py",
214
220
  "ringg-bot/tests/test_sdk_tool_schema.py",
221
+ "ringg-bot/tests/test_recording_stereo.py",
215
222
  "ringg-bot/tests/conftest.py",
223
+ "ringg-bot/tests/test_widget_text_suppression.py",
216
224
  "ringg-bot/tests/test_inbound_registration_race.py",
225
+ "ringg-bot/tests/test_action_call_variables.py",
226
+ "ringg-bot/tests/test_send_widget_action.py",
217
227
  "ringg-bot/tests/test_language_map.py",
218
228
  "ringg-bot/tests/test_warning_fixed_message.py",
229
+ "ringg-bot/tests/test_transcript_timestamp_format.py",
219
230
  "ringg-bot/tests/test_variable_replacement.py",
220
231
  "ringg-bot/tests/test_metrics_bridge.py",
221
232
  "ringg-bot/tests/test_language_steering.py",
@@ -224,12 +235,15 @@
224
235
  "ringg-bot/tests/test_word_timestamp_logger.py",
225
236
  "ringg-bot/tests/__init__.py",
226
237
  "ringg-bot/tests/test_kb_planner.py",
238
+ "ringg-bot/tests/test_inbound_call_data_and_custom_vars.py",
227
239
  "ringg-bot/tests/test_whatsapp.py",
228
240
  "ringg-bot/tests/test_recording_flush.py",
229
241
  "ringg-bot/tests/test_metrics_collector_llm.py",
230
242
  "ringg-bot/tests/test_language_sample_store.py",
231
243
  "ringg-bot/tests/test_traffic_split.py",
232
244
  "ringg-bot/tests/test_flow_query_kb.py",
245
+ "ringg-bot/tests/test_realtime_external_tts.py",
246
+ "ringg-bot/tests/test_send_blocks_calendar.py",
233
247
  "ringg-bot/tests/test_sdk_executor_flatten.py",
234
248
  "ringg-bot/tests/test_decimal_safe_aggregator.py",
235
249
  "ringg-bot/tests/test_dropped_turn_regeneration.py",
@@ -239,7 +253,10 @@
239
253
  "ringg-bot/tests/test_summary_dispatcher.py",
240
254
  "ringg-bot/tests/test_ozonetel_transfer.py",
241
255
  "ringg-bot/tests/test_tool_executor_context.py",
256
+ "ringg-bot/tests/test_media_mode.py",
257
+ "ringg-bot/tests/test_widget_tool_tracking.py",
242
258
  "ringg-bot/tests/test_custom_vars_pipeline_parity.py",
259
+ "ringg-bot/tests/test_llm_shadow.py",
243
260
  "ringg-bot/simulation/simulation_service.py",
244
261
  "ringg-bot/simulation/__init__.py",
245
262
  "ringg-bot/simulation/router.py",
@@ -250,9 +267,11 @@
250
267
  "ringg-bot/utils/deepgram_warmup.py",
251
268
  "ringg-bot/utils/collect_prompts.py",
252
269
  "ringg-bot/utils/tools_helper.py",
270
+ "ringg-bot/utils/llm_shadow.py",
253
271
  "ringg-bot/utils/backend_url_resolver.py",
254
272
  "ringg-bot/utils/test_cache_8k.mp3",
255
273
  "ringg-bot/utils/language_resolver.py",
274
+ "ringg-bot/utils/media_mode.py",
256
275
  "ringg-bot/utils/tracking_helpers.py",
257
276
  "ringg-bot/utils/transcript.py",
258
277
  "ringg-bot/utils/logger_config.py",
@@ -0,0 +1,8 @@
1
+ {
2
+ "tag": "0.0.21",
3
+ "distance": 1680,
4
+ "node": "g38f3578bb39abc4fd2a9e8387cf026bf4e7055e2",
5
+ "dirty": false,
6
+ "branch": "feat/widget-action-router",
7
+ "node_date": "2026-07-20"
8
+ }
@@ -88,6 +88,13 @@ def substitute_extract_vars(text: str, state: dict) -> str:
88
88
  for seg in key.split("."):
89
89
  if isinstance(cur, dict) and seg in cur:
90
90
  cur = cur[seg]
91
+ elif isinstance(cur, list):
92
+ # Numeric segment indexes a list — an Action node's stored
93
+ # response is often a root array (``[{action_1.0.title}]``).
94
+ try:
95
+ cur = cur[int(seg)]
96
+ except (ValueError, IndexError, TypeError):
97
+ return None
91
98
  else:
92
99
  return None
93
100
  return cur
@@ -928,6 +928,22 @@ class FlowManager:
928
928
  next_node = None
929
929
  is_transition_only_function = True
930
930
 
931
+ # Record that THIS function moved the flow, so
932
+ # RESET_WITH_CONVERSATION keeps its tool call in the carried
933
+ # context (see extract_conversation_messages).
934
+ #
935
+ # Detected at CALL time, not registration time. ringg-bot bakes the
936
+ # target into the handler (``create_transition_handler`` returns
937
+ # ``({"status": "ok"}, target_node)``) and leaves
938
+ # ``FlowsFunctionSchema.transition_to`` unset — so a
939
+ # registration-time check reads None, never fires, and silently
940
+ # reduces the whole context filter to a no-op. A truthy
941
+ # ``next_node`` is the only reliable signal. Call-time is
942
+ # sufficient by construction: a transition's tool call can only be
943
+ # in the context if the transition actually ran.
944
+ if next_node:
945
+ self._transition_function_names.add(name)
946
+
931
947
  logger.debug(
932
948
  f"{'Transition-only function called for' if is_transition_only_function else 'Function handler completed for'} {name}"
933
949
  )
@@ -298,14 +298,23 @@ def pick_branch_target(
298
298
  # the legacy `_node` / `_max_unclear` names for historical reasons,
299
299
  # but those keys never reach this dict at runtime.
300
300
  max_attempts = int(node_config.get("router_max_attempts", 2))
301
- if attempts > max_attempts:
301
+ reprompt_message = node_config.get("router_reprompt_message")
302
+ unclear_next = node_config.get("router_unclear_next")
303
+ # The under-cap path needs somewhere to retry: an inline re-prompt or a
304
+ # dedicated unclear Speak node. With NEITHER configured (only
305
+ # exhausted_next set, as the router config UI allows) there is no retry
306
+ # to perform, so an unclear pick has nowhere to go while under the cap —
307
+ # returning unclear_next=None here dead-airs the whole call even though
308
+ # a valid exhausted target exists. Fall straight through to exhausted in
309
+ # that case instead of after an unreachable retry loop.
310
+ if attempts > max_attempts or (not reprompt_message and not unclear_next):
302
311
  attempt_state[node_id] = 0 # reset for next time we enter this node
303
312
  return node_config.get("router_exhausted_next")
304
313
  # Under cap: prefer the new inline re-prompt if configured, else fall
305
314
  # back to the legacy separate-Speak unclear target.
306
- if node_config.get("router_reprompt_message"):
315
+ if reprompt_message:
307
316
  return REPROMPT_IN_PLACE
308
- return node_config.get("router_unclear_next")
317
+ return unclear_next
309
318
 
310
319
  return None # caller treats unknown id as a parse failure
311
320
 
@@ -1,8 +0,0 @@
1
- {
2
- "tag": "0.0.21",
3
- "distance": 1590,
4
- "node": "g68bb0481ac9d17412e39fb73da7a0e07253e200d",
5
- "dirty": true,
6
- "branch": "feat/livekit_transport",
7
- "node_date": "2026-07-06"
8
- }