dv-pipecat-flows 0.0.23.dev12__tar.gz → 0.0.26.dev145__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 (135) hide show
  1. dv_pipecat_flows-0.0.26.dev145/.agents/skills/pipecat-logs/SKILL.md +237 -0
  2. dv_pipecat_flows-0.0.26.dev145/.agents/skills/pipecat-logs/query-reference.md +165 -0
  3. dv_pipecat_flows-0.0.26.dev145/.claude/skills/pipecat-logs/SKILL.md +237 -0
  4. dv_pipecat_flows-0.0.26.dev145/.claude/skills/pipecat-logs/query-reference.md +165 -0
  5. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/.gitignore +0 -2
  6. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/AGENTS.md +31 -3
  7. {dv_pipecat_flows-0.0.23.dev12/src/dv_pipecat_flows.egg-info → dv_pipecat_flows-0.0.26.dev145}/PKG-INFO +1 -1
  8. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/pyproject.toml +4 -0
  9. dv_pipecat_flows-0.0.26.dev145/scripts/build_uae_pipecat_secret_blob.py +315 -0
  10. dv_pipecat_flows-0.0.26.dev145/scripts/check-ar-package.py +103 -0
  11. dv_pipecat_flows-0.0.26.dev145/scripts/test_build_uae_pipecat_secret_blob.py +86 -0
  12. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145/src/dv_pipecat_flows.egg-info}/PKG-INFO +1 -1
  13. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/dv_pipecat_flows.egg-info/SOURCES.txt +7 -7
  14. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/dv_pipecat_flows.egg-info/scm_file_list.json +219 -6
  15. dv_pipecat_flows-0.0.26.dev145/src/dv_pipecat_flows.egg-info/scm_version.json +8 -0
  16. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/exceptions.py +19 -0
  17. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/manager.py +868 -56
  18. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/processors/user_turn_observer.py +148 -1
  19. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/types.py +13 -0
  20. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/uv.lock +2 -0
  21. dv_pipecat_flows-0.0.23.dev12/.agents/skills/loki-logs/SKILL.md +0 -121
  22. dv_pipecat_flows-0.0.23.dev12/.agents/skills/loki-logs/query-reference.md +0 -113
  23. dv_pipecat_flows-0.0.23.dev12/.claude/skills/loki-logs/SKILL.md +0 -121
  24. dv_pipecat_flows-0.0.23.dev12/.claude/skills/loki-logs/query-reference.md +0 -113
  25. dv_pipecat_flows-0.0.23.dev12/scripts/azure_latency_probe.py +0 -220
  26. dv_pipecat_flows-0.0.23.dev12/scripts/check-pypi-package.py +0 -27
  27. dv_pipecat_flows-0.0.23.dev12/scripts/langfuse_export.py +0 -321
  28. dv_pipecat_flows-0.0.23.dev12/src/dv_pipecat_flows.egg-info/scm_version.json +0 -8
  29. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/.gitattributes +0 -0
  30. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/.pre-commit-config.yaml +0 -0
  31. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/.python-version +0 -0
  32. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/.readthedocs.yaml +0 -0
  33. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/CHANGELOG.md +0 -0
  34. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/CLAUDE.md +0 -0
  35. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/CONTRIBUTING.md +0 -0
  36. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/LICENSE +0 -0
  37. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/MANIFEST.in +0 -0
  38. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/README.md +0 -0
  39. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/.env.example +0 -0
  40. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/.gitignore +0 -0
  41. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/README.md +0 -0
  42. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/docs/ARCHITECTURE.md +0 -0
  43. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/docs/CODE_MAP.md +0 -0
  44. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/docs/CONFIG.md +0 -0
  45. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/docs/CONTRACTS.md +0 -0
  46. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/docs/COPILOT_TODO.md +0 -0
  47. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/docs/DISTRIBUTION.md +0 -0
  48. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/docs/HLD.md +0 -0
  49. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/docs/METHODS.md +0 -0
  50. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/docs/VOICE_E2E.md +0 -0
  51. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/ANALYSIS_stagehand_vs_hybrid.md +0 -0
  52. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/RESULTS.md +0 -0
  53. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/_env.py +0 -0
  54. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/bench.py +0 -0
  55. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/bench_browseruse.py +0 -0
  56. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/bench_stagehand.py +0 -0
  57. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/inspect_browseruse.py +0 -0
  58. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/inspect_browseruse_showcase.py +0 -0
  59. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/inspect_stagehand_prompt.py +0 -0
  60. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/pages/checkout.html +0 -0
  61. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/pages/dashboard.html +0 -0
  62. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/pages/signup.html +0 -0
  63. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/results_browseruse.json +0 -0
  64. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/results_perception.json +0 -0
  65. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/results_stagehand.json +0 -0
  66. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/tasks.py +0 -0
  67. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/try_hybrid.py +0 -0
  68. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/try_hybrid_multistep.py +0 -0
  69. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/eval/try_hybrid_oneshot.py +0 -0
  70. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/pyproject.toml +0 -0
  71. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/scripts/dev-stack.sh +0 -0
  72. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/browser_copilot/uv.lock +0 -0
  73. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/dev-requirements.txt +0 -0
  74. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/docker-compose.dev.yml +0 -0
  75. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/.eslintrc.json +0 -0
  76. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/.prettierrc +0 -0
  77. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/css/tailwind.css +0 -0
  78. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/examples/food_ordering.json +0 -0
  79. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/examples/movie_explorer.json +0 -0
  80. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/examples/patient_intake.json +0 -0
  81. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/examples/restaurant_reservation.json +0 -0
  82. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/examples/travel_planner.json +0 -0
  83. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/favicon.png +0 -0
  84. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/favicon.svg +0 -0
  85. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/index.html +0 -0
  86. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/editor/canvas.js +0 -0
  87. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/editor/editorState.js +0 -0
  88. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/editor/sidePanel.js +0 -0
  89. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/editor/toolbar.js +0 -0
  90. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/main.js +0 -0
  91. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/nodes/baseNode.js +0 -0
  92. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/nodes/endNode.js +0 -0
  93. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/nodes/flowNode.js +0 -0
  94. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/nodes/functionNode.js +0 -0
  95. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/nodes/index.js +0 -0
  96. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/nodes/mergeNode.js +0 -0
  97. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/nodes/startNode.js +0 -0
  98. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/types.js +0 -0
  99. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/utils/export.js +0 -0
  100. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/utils/helpers.js +0 -0
  101. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/utils/import.js +0 -0
  102. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/js/utils/validation.js +0 -0
  103. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/jsdoc.json +0 -0
  104. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/package-lock.json +0 -0
  105. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/package.json +0 -0
  106. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/postcss.config.cjs +0 -0
  107. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/public/favicon.png +0 -0
  108. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/public/favicon.svg +0 -0
  109. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/tailwind.config.cjs +0 -0
  110. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/vercel.json +0 -0
  111. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/editor/vite.config.js +0 -0
  112. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/engine_primitives_plan.md +0 -0
  113. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/env.example +0 -0
  114. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/images/food-ordering-flow.png +0 -0
  115. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/pipecat-flows.png +0 -0
  116. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/pipecat_upgrade.md +0 -0
  117. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/remote-asterisk-code/README.md +0 -0
  118. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/remote-asterisk-code/extensions.conf +0 -0
  119. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/remote-asterisk-code/rtp.conf +0 -0
  120. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/requirements.txt +0 -0
  121. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/scripts/fix-ruff.sh +0 -0
  122. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/scripts/pre-commit.sh +0 -0
  123. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/setup.cfg +0 -0
  124. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/dv_pipecat_flows.egg-info/dependency_links.txt +0 -0
  125. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/dv_pipecat_flows.egg-info/requires.txt +0 -0
  126. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/dv_pipecat_flows.egg-info/top_level.txt +0 -0
  127. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/__init__.py +0 -0
  128. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/actions.py +0 -0
  129. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/adapters.py +0 -0
  130. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/condition_evaluator.py +0 -0
  131. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/flow_validator.py +0 -0
  132. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/processors/__init__.py +0 -0
  133. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/processors/router_mode_guard.py +0 -0
  134. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/processors/speak_interruption_guard.py +0 -0
  135. {dv_pipecat_flows-0.0.23.dev12 → dv_pipecat_flows-0.0.26.dev145}/src/pipecat_flows/router_mode.py +0 -0
@@ -0,0 +1,237 @@
1
+ ---
2
+ name: pipecat-logs
3
+ description: Fetch and analyze pipecat application logs from VictoriaLogs by call ID or call SID. Use when debugging call issues, investigating errors, or analyzing bot behavior for a specific call. Accepts any call identifier — the Ringg call id, a provider-native id, a telephony provider UUID, or an Asterisk sid (the last two are resolved first) — and optional environment (staging/production).
4
+ argument-hint: <call_id|call_sid> [staging|production]
5
+ allowed-tools: Bash(curl *), Bash(jq *), Bash(kubectl *), Bash(pkill *)
6
+ ---
7
+
8
+ # Pipecat Logs Fetcher
9
+
10
+ Fetch logs from **VictoriaLogs** for a specific pipecat call and analyze them.
11
+
12
+ > Pipecat logging moved from Loki to VictoriaLogs in 2026-08. The old Loki
13
+ > instance (`35.154.72.110:3100`) is still up and still answers `200`, but it
14
+ > receives only a residual trickle (~18 lines/hour of pod-shutdown noise). It
15
+ > returns **an empty result set rather than an error** for every real query, so
16
+ > a stale Loki query looks like "this call has no logs" instead of like a
17
+ > broken endpoint. Do not query it.
18
+
19
+ ## Parameters
20
+
21
+ - `search` — **any call identifier** (required): the Ringg call id (`01a03784-…`), a provider-native id (`3825374100`, `e42e1ec1…`), a telephony provider UUID, or an Asterisk sid. The last two need a resolve hop — see step 3.
22
+ - `for` — **environment** (optional): `production` (default) or `staging`
23
+
24
+ ## Where pipecat logs actually live
25
+
26
+ VictoriaLogs is **regional** — three independent instances, each storing only
27
+ its own cluster's logs, each behind its own `vmauth` (max 4 concurrent reads).
28
+ There is no cross-region query.
29
+
30
+ | Instance | Cluster | Holds |
31
+ |---|---|---|
32
+ | **us-east1** | `desivocal-prod-us-e1-cluster` | **all pipecat** — `dv-pipecat` (`production`), `dv-pipecat-canary`, `dv-pipecat-stage` (`staging`) |
33
+ | Mumbai | `desivocal-prod-cluster` | backend / taskiq / temporal only — **no pipecat** |
34
+ | KSA | `desivocal-prod-cluster-ksa` | backend / taskiq only — **no pipecat** |
35
+
36
+ **Always query us-east1 for pipecat, whatever the call's region.** Both
37
+ production and staging pipecat live there, separated by the `environment`
38
+ field. The Mumbai cluster does have a `dv-pipecat` Deployment, but it is a
39
+ single idle replica (us-east1 runs ~900) — it serves no traffic, and its pods
40
+ lack the `logs.ringg.ai/collect=application` label that Mumbai's Vector agent
41
+ selects on, so nothing from it is collected anyway. An empty Mumbai result is
42
+ therefore expected and means nothing.
43
+
44
+ Non-pipecat lookups do need the other two: the backend's
45
+ `new-calling-agent-taskiq-call-completion` logs live in Mumbai (India) or KSA.
46
+ See "Cross-checking against the backend" below.
47
+
48
+ ## Instructions
49
+
50
+ ### 1. Parse arguments
51
+
52
+ ```
53
+ IDENTIFIER = search
54
+ ENV = for (default: "production")
55
+ ```
56
+
57
+ Normalize `prod` to `production`. If `IDENTIFIER` is missing, ask the user.
58
+
59
+ **Do not branch on what the identifier looks like.** A call has several ids and
60
+ they are not interchangeable — but you cannot tell which kind you were handed
61
+ by its shape, so always try the indexed field first and only resolve if it
62
+ comes back empty (step 3). What exists in practice:
63
+
64
+ | Identifier | Example | `call_id:=` works? |
65
+ |---|---|---|
66
+ | Ringg call id (UUIDv7, `01a0…`) | `01a03784-c580-7811-95ef-20ef317f8352` | **yes** |
67
+ | provider-native numeric | `3825374100` | **yes** |
68
+ | provider-native 32-hex | `e42e1ec169ea4ab5abba0f49480b84ba` | **yes** |
69
+ | telephony provider's own UUID | `db6bd116-5197-4cad-8df6-d39bbbcc4565` | **no — 0 rows** |
70
+ | Asterisk sid | `1787637558.655495` | **no — 0 rows** |
71
+
72
+ The indexed `call_id` field carries the **Ringg** id — which the logs also call
73
+ `callback_call_id`. The last two rows are the trap: a provider UUID looks
74
+ exactly like a Ringg id and silently returns nothing, and the sid returns only
75
+ a few callback lines. Both are recoverable — see step 3.
76
+
77
+ ### 2. Open a port-forward to the us-east1 VictoriaLogs
78
+
79
+ The regional read endpoints (`use1.victorialogs.internal:8427` etc.) resolve
80
+ only inside their own cluster, so query `svc/victoria-logs` through a
81
+ port-forward. Start it in the background and poll until it answers — do not
82
+ `sleep` in the foreground:
83
+
84
+ ```bash
85
+ kubectl --context gke_desivocalprod01_us-east1_desivocal-prod-us-e1-cluster \
86
+ -n victorialogs port-forward svc/victoria-logs 9430:9428 > /tmp/vl-pf.log 2>&1 &
87
+
88
+ curl -sf --retry 30 --retry-delay 1 --retry-connrefused -m 10 \
89
+ "http://127.0.0.1:9430/select/logsql/query" \
90
+ --data-urlencode 'query=_time:5m * | limit 1' -o /dev/null
91
+ ```
92
+
93
+ The readiness check must be `curl`'s own `--retry-connrefused`, not a shell
94
+ retry loop. The forward takes ~1-2s to bind, and until it does `curl` fails
95
+ with connection-refused **instantly** — `-m` never applies, because there is
96
+ nothing to wait on. A bare `for i in 1..10; do curl … && break; done` therefore
97
+ burns all ten attempts in milliseconds and reports failure on a port-forward
98
+ that is about to come up. Only `--retry-delay` actually waits.
99
+
100
+ Tear it down with `pkill -f "port-forward svc/victoria-logs"` when finished.
101
+
102
+ ### 3. Query
103
+
104
+ **Timezone note:** user-supplied times are **IST (Asia/Kolkata, UTC+5:30)**.
105
+ LogsQL `_time` accepts relative ranges (`_time:1d`) or absolute UTC
106
+ (`_time:[2026-08-25T04:00:00Z, 2026-08-25T05:00:00Z]`) — convert before querying.
107
+
108
+ ```bash
109
+ curl -s -m 60 "http://127.0.0.1:9430/select/logsql/query" \
110
+ --data-urlencode "query=_time:1d application:dv-pipecat environment:=<ENV> call_id:=\"<IDENTIFIER>\" | limit 500" \
111
+ -o /tmp/vl.json
112
+ ```
113
+
114
+ `call_id` is an indexed field, and matching it is **strictly better than a
115
+ substring search** — not just faster. Most lines carry the field without
116
+ printing the id in their text, so substring under-returns badly. Measured on
117
+ three live calls:
118
+
119
+ | id | `call_id:=` | substring |
120
+ |---|---|---|
121
+ | `01a03784-…` | 82 lines | 27 |
122
+ | `3825374100` | 84 lines | 32 |
123
+ | `e42e1ec1…` | 177 lines | 34 |
124
+
125
+ **If it returns 0 rows, the identifier is a provider id, not the Ringg id.**
126
+ Recover the real one and re-query — this is the difference between "this call
127
+ barely logged anything" and the actual call:
128
+
129
+ ```bash
130
+ REAL=$(curl -s -m 60 "http://127.0.0.1:9430/select/logsql/query" \
131
+ --data-urlencode "query=_time:1d application:dv-pipecat \"<IDENTIFIER>\" | fields call_id, _msg | limit 20" \
132
+ | { grep -oE '"call_id":"[^"u][^"]*"|callback_call_id[=: ]+[0-9a-f-]{8,}' || true; } \
133
+ | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' | sort -u | head -1)
134
+ ```
135
+
136
+ Then re-run the indexed query with `$REAL`. A bare substring filter is the last
137
+ resort, and also the only way to see early-startup lines (`[run_bot] call_id=…`
138
+ and friends), which are logged before the call context is bound and so carry no
139
+ `call_id` field at all — they show as `call_id: "unknown"` or omit it.
140
+
141
+ If the result is empty, in order: try the other `environment`; drop the
142
+ `environment` filter; widen `_time` (max range is 720h); try
143
+ `application:~"dv-pipecat"` to include `dv-pipecat-canary`.
144
+
145
+ ### 4. Parse and display
146
+
147
+ The response is **JSON Lines** — one JSON object per line, not a wrapped
148
+ envelope. `jq .` on the whole file fails; parse per line:
149
+
150
+ ```bash
151
+ jq -r '[._time, (.level // "-"), ._msg] | @tsv' /tmp/vl.json | sort
152
+ ```
153
+
154
+ Results come back unordered, so **sort by `_time` yourself**. Display
155
+ chronologically (earliest first) with timestamp, level, and message.
156
+
157
+ Useful fields: `_time`, `_msg`, `level`, `call_id`, `pod`, `application`,
158
+ `environment`, `cluster`, `container`, `logger`, `module`, `function`, `line`.
159
+
160
+ Two field names differ from the backend's records and are easy to get wrong:
161
+ pipecat logs the pod as **`pod`**, not `pod_name`, and its **`level` is
162
+ lowercase** (`debug`/`info`/`warning`/`error`) while the parallel `severity`
163
+ field is uppercase. A filter on the wrong one silently matches nothing.
164
+
165
+ ### 5. Analyze
166
+
167
+ After displaying the logs, provide a brief analysis:
168
+
169
+ 1. **Call timeline**: what happened (connected, greeted, conversation, ended)
170
+ 2. **Errors/warnings**: highlight ERROR/WARNING lines
171
+ 3. **Tool calls**: function/tool calls made during the call
172
+ 4. **TTS/STT activity**: speech-related events
173
+ 5. **Call outcome**: normal hangup, error, transfer, timeout
174
+ 6. **Anomalies**: long silences, repeated errors, unexpected transitions
175
+
176
+ Note the session shape while reading — it changes which pipeline is running and
177
+ therefore which failures are possible. `Using single_node bot` vs a FlowManager
178
+ line; `channel=livekit|daily|telephony|smallwebrtc`; and `text mode, starting
179
+ flow` / `Local recording disabled for text-only session` / `lk.chat message ->
180
+ queued to LLM`, which mark a **text-only** session (no STT, no
181
+ `TranscriptionFrame`).
182
+
183
+ ### 6. Grafana link
184
+
185
+ Give the user a link to the pipecat dashboard (datasource `vl-use1`, i.e. the
186
+ same us-east1 store queried above):
187
+
188
+ ```
189
+ http://10.120.0.49/d/vl-pipecat-logs
190
+ ```
191
+
192
+ Its variables are `environment`, `application`, `container`, `pod`, `call_id`,
193
+ `trace_id`, `message_substring`, `minimum_level`. The host is an internal
194
+ LoadBalancer IP — reachable on the VPN, not from the public internet.
195
+
196
+ ## Cross-checking against the backend
197
+
198
+ When pipecat logs are thin, the backend's call-completion payload is a good
199
+ second source: it dumps the whole completion object, including
200
+ `function_calls_detailed` with each tool's `response_data` — so a failing
201
+ tool's error string is greppable even without pipecat logs. It lives in the
202
+ **Mumbai** (India) or **KSA** VL instance, not us-east1:
203
+
204
+ ```bash
205
+ kubectl --context gke_desivocalprod01_asia-south1_desivocal-prod-cluster \
206
+ -n victorialogs port-forward svc/victoria-logs 9429:9428 > /tmp/vl-pf-mum.log 2>&1 &
207
+
208
+ curl -s -m 60 "http://127.0.0.1:9429/select/logsql/query" \
209
+ --data-urlencode 'query=_time:1d application:new-calling-agent-taskiq-call-completion "<IDENTIFIER>" | limit 50'
210
+ ```
211
+
212
+ KSA is `gke_desivocalprod01_me-central2_desivocal-prod-cluster-ksa`, same
213
+ namespace and service.
214
+
215
+ ## Troubleshooting
216
+
217
+ - **Empty result, `200` status** — the usual cause is the wrong region or a
218
+ missing `_time` window, not a missing call. Work through the fallbacks in
219
+ step 3 before concluding the call has no logs.
220
+ - **`too big time range selected`** — `_time:` is mandatory and capped at 720h.
221
+ A query with no `_time` filter is rejected with a `1677-09-21 → 2262-04-11`
222
+ range in the message; that is the missing-filter error, not a real range.
223
+ - **`jq: parse error`** — the response is JSON Lines; see step 4.
224
+ - **Port-forward drops** — `kubectl port-forward` dies on idle or on pod
225
+ rotation. Re-run step 2; the retry makes that safe to repeat.
226
+ - **Zero rows, or only a handful** — you were almost certainly handed a
227
+ provider id rather than the Ringg one. Resolve it (step 3) instead of
228
+ widening the time range.
229
+ - **Slow or refused reads** — each region's `vmauth` allows 4 concurrent reads.
230
+ Serialize queries rather than fanning out.
231
+ - **A migrated webcall with no pipecat logs at all** — webcalls with
232
+ `telephony_provider=livekit` run on LiveKit Agents, not pipecat, and log to
233
+ GCP Cloud Logging (`desivocalprod01`, container `ringg-webcall`).
234
+
235
+ ## Reference
236
+
237
+ For LogsQL syntax and more filtering options, see [query-reference.md](query-reference.md).
@@ -0,0 +1,165 @@
1
+ # LogsQL Query Reference for Pipecat Logs
2
+
3
+ VictoriaLogs uses **LogsQL**, not LogQL. The two look similar and are not
4
+ compatible: there are no `{label="value"}` stream selectors, no `|=` line
5
+ filters, and no `| json` / `| line_format` stages. Fields are filtered
6
+ directly, and the pipeline after `|` uses named pipes (`limit`, `stats`,
7
+ `sort`, `fields`, `field_names`).
8
+
9
+ Full syntax: <https://docs.victoriametrics.com/victorialogs/logsql/>
10
+
11
+ ## Base query pattern
12
+
13
+ ```logsql
14
+ _time:1d application:dv-pipecat environment:=production call_id:="<call_id>" | limit 500
15
+ ```
16
+
17
+ `_time:` is **mandatory** on every query and capped at 720h. Omitting it is
18
+ rejected with a `[1677-09-21 … 2262-04-11]` range in the error — that is the
19
+ missing-filter message, not a real range you asked for.
20
+
21
+ ## Filter forms
22
+
23
+ | Form | Meaning |
24
+ |---|---|
25
+ | `field:="exact"` | exact field match (fastest — use for `call_id`) |
26
+ | `field:"phrase"` | phrase match within the field |
27
+ | `field:~"regex"` | regexp match, e.g. `application:~"dv-pipecat"` |
28
+ | `"substring"` | substring across the whole record — the `\|=` equivalent |
29
+ | `field:*` | field exists |
30
+ | `-field:="x"` | negation |
31
+ | `a AND b`, `a OR b` | boolean (bare space is AND) |
32
+
33
+ ## Time ranges
34
+
35
+ ```logsql
36
+ _time:5m _time:1h _time:1d _time:7d
37
+ _time:[2026-08-25T04:00:00Z, 2026-08-25T05:00:00Z]
38
+ ```
39
+
40
+ Absolute times are **UTC**. User-supplied times are IST (UTC+5:30) — subtract
41
+ 5h30m first.
42
+
43
+ ## Common variations
44
+
45
+ **Errors only** — `level` is lowercase on pipecat records; the uppercase
46
+ values live on the parallel `severity` field, so match case-insensitively or
47
+ pick one field deliberately:
48
+ ```logsql
49
+ _time:1d application:dv-pipecat call_id:="<call_id>" level:~"(?i)error|critical" | limit 200
50
+ ```
51
+
52
+ **Warnings and above:**
53
+ ```logsql
54
+ _time:1d application:dv-pipecat call_id:="<call_id>" severity:~"WARNING|ERROR|CRITICAL" | limit 200
55
+ ```
56
+
57
+ **Keyword within a call** (LLM / TTS / tool calls / VAD):
58
+ ```logsql
59
+ _time:1d application:dv-pipecat call_id:="<call_id>" "LLM" | limit 200
60
+ _time:1d application:dv-pipecat call_id:="<call_id>" _msg:~"function|tool_call|generic_function" | limit 200
61
+ _time:1d application:dv-pipecat call_id:="<call_id>" _msg:~"VAD|speaking|speech|silence|idle" | limit 200
62
+ ```
63
+
64
+ **One error string across all calls** — how you find out whether a bug is
65
+ systemic and how often it fires:
66
+ ```logsql
67
+ _time:1d application:dv-pipecat "TaskManager is still not initialized" | limit 200
68
+ ```
69
+
70
+ **By pod** — the field is `pod`; `pod_name` exists on the backend's records
71
+ but **not** on pipecat's, and filtering on it silently matches nothing:
72
+ ```logsql
73
+ _time:1h application:dv-pipecat pod:~"dv-pipecat-canary" | limit 200
74
+ ```
75
+
76
+ **Include canary:**
77
+ ```logsql
78
+ _time:1d application:~"dv-pipecat" call_id:="<call_id>" | limit 500
79
+ ```
80
+
81
+ ## Aggregation and discovery pipes
82
+
83
+ ```logsql
84
+ _time:30m * | stats by (application, cluster, environment) count() # what's in this instance
85
+ _time:1h application:dv-pipecat | stats by (level) count() # error-rate breakdown
86
+ _time:1h application:dv-pipecat | limit 500 | field_names # available fields
87
+ _time:1d application:dv-pipecat "<error>" | fields _time, call_id, pod | limit 200
88
+ ```
89
+
90
+ `stats by (...)` is the cheap way to answer "which region / app / pod is this
91
+ happening in" before pulling raw lines.
92
+
93
+ ## API endpoints
94
+
95
+ | Endpoint | Purpose |
96
+ |---|---|
97
+ | `POST /select/logsql/query` | Query logs (use `--data-urlencode 'query=…'`) |
98
+ | `POST /select/logsql/hits` | Hit counts bucketed over time |
99
+ | `GET /select/logsql/field_names` | Field names for a query |
100
+ | `GET /select/logsql/field_values` | Values for one field |
101
+
102
+ Parameters: `query` (LogsQL, includes its own time filter), and optionally
103
+ `start` / `end` / `limit`. There is no `direction` — order with a `sort` pipe
104
+ or sort client-side.
105
+
106
+ ## Response structure
107
+
108
+ **JSON Lines** — one JSON object per line, no envelope. `jq .` over the whole
109
+ body fails; parse per line:
110
+
111
+ ```
112
+ {"_time":"2026-08-25T04:09:20.448Z","_msg":"Call config: …","level":"info","call_id":"01a0371b-…","pod":"dv-pipecat-…"}
113
+ {"_time":"2026-08-25T04:09:20.455Z","_msg":"BYOK status: …","level":"info","call_id":"01a0371b-…","pod":"dv-pipecat-…"}
114
+ ```
115
+
116
+ ```bash
117
+ jq -r '[._time, (.level // "-"), ._msg] | @tsv' /tmp/vl.json | sort
118
+ ```
119
+
120
+ Results are unordered — sort by `_time` yourself.
121
+
122
+ ## Fields on pipecat records
123
+
124
+ `_time`, `_msg`, `level`, `severity`, `call_id`, `pod`, `node`, `application`,
125
+ `container`, `namespace`, `cluster`, `environment`, `logger`, `module`,
126
+ `function`, `line`, `process`, `thread`, `stream`, `_extras_dropped`,
127
+ `_truncated`.
128
+
129
+ `level` is lowercase, `severity` is uppercase, and the pod is `pod` — **not**
130
+ `pod_name`. The backend's records carry a different and larger set
131
+ (`pod_name`, `trace_id`, `agent_id`, `workspace_id`, `region`, `host_ip`,
132
+ `correlation_id`, …), so don't carry a working backend filter over to a pipecat
133
+ query unchanged. `| limit N | field_names` on a live window is the way to check.
134
+
135
+ Vector sets `cluster` / `environment` / the `kubernetes` metadata itself and
136
+ strips any same-named keys from the application payload, so those cannot be
137
+ spoofed by a log line — they are reliable for filtering.
138
+
139
+ ## Infrastructure
140
+
141
+ Three regional instances, no cross-region query, each behind its own `vmauth`
142
+ (max 4 concurrent reads). All are `svc/victoria-logs:9428` in namespace
143
+ `victorialogs`; the `*.victorialogs.internal:8427` read endpoints resolve only
144
+ inside their own cluster, so port-forward from a laptop.
145
+
146
+ | Region | kubectl context | Holds |
147
+ |---|---|---|
148
+ | us-east1 | `gke_desivocalprod01_us-east1_desivocal-prod-us-e1-cluster` | **all pipecat**, prod + staging |
149
+ | Mumbai | `gke_desivocalprod01_asia-south1_desivocal-prod-cluster` | backend / taskiq / temporal |
150
+ | KSA | `gke_desivocalprod01_me-central2_desivocal-prod-cluster-ksa` | backend / taskiq |
151
+
152
+ - **Grafana**: `http://10.120.0.49` (internal LB — VPN only), pipecat dashboard
153
+ uid `vl-pipecat-logs`, datasources `vl-use1` (default) / `vl-mumbai` / `vl-ksa`.
154
+ - **Collection**: a Vector DaemonSet per cluster ships to the regional `vmauth`.
155
+ Mumbai, KSA and staging collect only Pods labelled
156
+ `logs.ringg.ai/collect=application`; us-east1 collects everything except Pods
157
+ labelled `vector.dev/exclude`. So in Mumbai/KSA, "no logs for this workload"
158
+ can mean "not labelled for collection", not "not running".
159
+
160
+ ## Environment values
161
+
162
+ | Environment | `environment` value | Pipecat application |
163
+ |---|---|---|
164
+ | Production | `production` | `dv-pipecat`, `dv-pipecat-canary` |
165
+ | Staging | `staging` | `dv-pipecat-stage` |
@@ -0,0 +1,237 @@
1
+ ---
2
+ name: pipecat-logs
3
+ description: Fetch and analyze pipecat application logs from VictoriaLogs by call ID or call SID. Use when debugging call issues, investigating errors, or analyzing bot behavior for a specific call. Accepts any call identifier — the Ringg call id, a provider-native id, a telephony provider UUID, or an Asterisk sid (the last two are resolved first) — and optional environment (staging/production).
4
+ argument-hint: <call_id|call_sid> [staging|production]
5
+ allowed-tools: Bash(curl *), Bash(jq *), Bash(kubectl *), Bash(pkill *)
6
+ ---
7
+
8
+ # Pipecat Logs Fetcher
9
+
10
+ Fetch logs from **VictoriaLogs** for a specific pipecat call and analyze them.
11
+
12
+ > Pipecat logging moved from Loki to VictoriaLogs in 2026-08. The old Loki
13
+ > instance (`35.154.72.110:3100`) is still up and still answers `200`, but it
14
+ > receives only a residual trickle (~18 lines/hour of pod-shutdown noise). It
15
+ > returns **an empty result set rather than an error** for every real query, so
16
+ > a stale Loki query looks like "this call has no logs" instead of like a
17
+ > broken endpoint. Do not query it.
18
+
19
+ ## Parameters
20
+
21
+ - `search` — **any call identifier** (required): the Ringg call id (`01a03784-…`), a provider-native id (`3825374100`, `e42e1ec1…`), a telephony provider UUID, or an Asterisk sid. The last two need a resolve hop — see step 3.
22
+ - `for` — **environment** (optional): `production` (default) or `staging`
23
+
24
+ ## Where pipecat logs actually live
25
+
26
+ VictoriaLogs is **regional** — three independent instances, each storing only
27
+ its own cluster's logs, each behind its own `vmauth` (max 4 concurrent reads).
28
+ There is no cross-region query.
29
+
30
+ | Instance | Cluster | Holds |
31
+ |---|---|---|
32
+ | **us-east1** | `desivocal-prod-us-e1-cluster` | **all pipecat** — `dv-pipecat` (`production`), `dv-pipecat-canary`, `dv-pipecat-stage` (`staging`) |
33
+ | Mumbai | `desivocal-prod-cluster` | backend / taskiq / temporal only — **no pipecat** |
34
+ | KSA | `desivocal-prod-cluster-ksa` | backend / taskiq only — **no pipecat** |
35
+
36
+ **Always query us-east1 for pipecat, whatever the call's region.** Both
37
+ production and staging pipecat live there, separated by the `environment`
38
+ field. The Mumbai cluster does have a `dv-pipecat` Deployment, but it is a
39
+ single idle replica (us-east1 runs ~900) — it serves no traffic, and its pods
40
+ lack the `logs.ringg.ai/collect=application` label that Mumbai's Vector agent
41
+ selects on, so nothing from it is collected anyway. An empty Mumbai result is
42
+ therefore expected and means nothing.
43
+
44
+ Non-pipecat lookups do need the other two: the backend's
45
+ `new-calling-agent-taskiq-call-completion` logs live in Mumbai (India) or KSA.
46
+ See "Cross-checking against the backend" below.
47
+
48
+ ## Instructions
49
+
50
+ ### 1. Parse arguments
51
+
52
+ ```
53
+ IDENTIFIER = search
54
+ ENV = for (default: "production")
55
+ ```
56
+
57
+ Normalize `prod` to `production`. If `IDENTIFIER` is missing, ask the user.
58
+
59
+ **Do not branch on what the identifier looks like.** A call has several ids and
60
+ they are not interchangeable — but you cannot tell which kind you were handed
61
+ by its shape, so always try the indexed field first and only resolve if it
62
+ comes back empty (step 3). What exists in practice:
63
+
64
+ | Identifier | Example | `call_id:=` works? |
65
+ |---|---|---|
66
+ | Ringg call id (UUIDv7, `01a0…`) | `01a03784-c580-7811-95ef-20ef317f8352` | **yes** |
67
+ | provider-native numeric | `3825374100` | **yes** |
68
+ | provider-native 32-hex | `e42e1ec169ea4ab5abba0f49480b84ba` | **yes** |
69
+ | telephony provider's own UUID | `db6bd116-5197-4cad-8df6-d39bbbcc4565` | **no — 0 rows** |
70
+ | Asterisk sid | `1787637558.655495` | **no — 0 rows** |
71
+
72
+ The indexed `call_id` field carries the **Ringg** id — which the logs also call
73
+ `callback_call_id`. The last two rows are the trap: a provider UUID looks
74
+ exactly like a Ringg id and silently returns nothing, and the sid returns only
75
+ a few callback lines. Both are recoverable — see step 3.
76
+
77
+ ### 2. Open a port-forward to the us-east1 VictoriaLogs
78
+
79
+ The regional read endpoints (`use1.victorialogs.internal:8427` etc.) resolve
80
+ only inside their own cluster, so query `svc/victoria-logs` through a
81
+ port-forward. Start it in the background and poll until it answers — do not
82
+ `sleep` in the foreground:
83
+
84
+ ```bash
85
+ kubectl --context gke_desivocalprod01_us-east1_desivocal-prod-us-e1-cluster \
86
+ -n victorialogs port-forward svc/victoria-logs 9430:9428 > /tmp/vl-pf.log 2>&1 &
87
+
88
+ curl -sf --retry 30 --retry-delay 1 --retry-connrefused -m 10 \
89
+ "http://127.0.0.1:9430/select/logsql/query" \
90
+ --data-urlencode 'query=_time:5m * | limit 1' -o /dev/null
91
+ ```
92
+
93
+ The readiness check must be `curl`'s own `--retry-connrefused`, not a shell
94
+ retry loop. The forward takes ~1-2s to bind, and until it does `curl` fails
95
+ with connection-refused **instantly** — `-m` never applies, because there is
96
+ nothing to wait on. A bare `for i in 1..10; do curl … && break; done` therefore
97
+ burns all ten attempts in milliseconds and reports failure on a port-forward
98
+ that is about to come up. Only `--retry-delay` actually waits.
99
+
100
+ Tear it down with `pkill -f "port-forward svc/victoria-logs"` when finished.
101
+
102
+ ### 3. Query
103
+
104
+ **Timezone note:** user-supplied times are **IST (Asia/Kolkata, UTC+5:30)**.
105
+ LogsQL `_time` accepts relative ranges (`_time:1d`) or absolute UTC
106
+ (`_time:[2026-08-25T04:00:00Z, 2026-08-25T05:00:00Z]`) — convert before querying.
107
+
108
+ ```bash
109
+ curl -s -m 60 "http://127.0.0.1:9430/select/logsql/query" \
110
+ --data-urlencode "query=_time:1d application:dv-pipecat environment:=<ENV> call_id:=\"<IDENTIFIER>\" | limit 500" \
111
+ -o /tmp/vl.json
112
+ ```
113
+
114
+ `call_id` is an indexed field, and matching it is **strictly better than a
115
+ substring search** — not just faster. Most lines carry the field without
116
+ printing the id in their text, so substring under-returns badly. Measured on
117
+ three live calls:
118
+
119
+ | id | `call_id:=` | substring |
120
+ |---|---|---|
121
+ | `01a03784-…` | 82 lines | 27 |
122
+ | `3825374100` | 84 lines | 32 |
123
+ | `e42e1ec1…` | 177 lines | 34 |
124
+
125
+ **If it returns 0 rows, the identifier is a provider id, not the Ringg id.**
126
+ Recover the real one and re-query — this is the difference between "this call
127
+ barely logged anything" and the actual call:
128
+
129
+ ```bash
130
+ REAL=$(curl -s -m 60 "http://127.0.0.1:9430/select/logsql/query" \
131
+ --data-urlencode "query=_time:1d application:dv-pipecat \"<IDENTIFIER>\" | fields call_id, _msg | limit 20" \
132
+ | { grep -oE '"call_id":"[^"u][^"]*"|callback_call_id[=: ]+[0-9a-f-]{8,}' || true; } \
133
+ | grep -oE '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}' | sort -u | head -1)
134
+ ```
135
+
136
+ Then re-run the indexed query with `$REAL`. A bare substring filter is the last
137
+ resort, and also the only way to see early-startup lines (`[run_bot] call_id=…`
138
+ and friends), which are logged before the call context is bound and so carry no
139
+ `call_id` field at all — they show as `call_id: "unknown"` or omit it.
140
+
141
+ If the result is empty, in order: try the other `environment`; drop the
142
+ `environment` filter; widen `_time` (max range is 720h); try
143
+ `application:~"dv-pipecat"` to include `dv-pipecat-canary`.
144
+
145
+ ### 4. Parse and display
146
+
147
+ The response is **JSON Lines** — one JSON object per line, not a wrapped
148
+ envelope. `jq .` on the whole file fails; parse per line:
149
+
150
+ ```bash
151
+ jq -r '[._time, (.level // "-"), ._msg] | @tsv' /tmp/vl.json | sort
152
+ ```
153
+
154
+ Results come back unordered, so **sort by `_time` yourself**. Display
155
+ chronologically (earliest first) with timestamp, level, and message.
156
+
157
+ Useful fields: `_time`, `_msg`, `level`, `call_id`, `pod`, `application`,
158
+ `environment`, `cluster`, `container`, `logger`, `module`, `function`, `line`.
159
+
160
+ Two field names differ from the backend's records and are easy to get wrong:
161
+ pipecat logs the pod as **`pod`**, not `pod_name`, and its **`level` is
162
+ lowercase** (`debug`/`info`/`warning`/`error`) while the parallel `severity`
163
+ field is uppercase. A filter on the wrong one silently matches nothing.
164
+
165
+ ### 5. Analyze
166
+
167
+ After displaying the logs, provide a brief analysis:
168
+
169
+ 1. **Call timeline**: what happened (connected, greeted, conversation, ended)
170
+ 2. **Errors/warnings**: highlight ERROR/WARNING lines
171
+ 3. **Tool calls**: function/tool calls made during the call
172
+ 4. **TTS/STT activity**: speech-related events
173
+ 5. **Call outcome**: normal hangup, error, transfer, timeout
174
+ 6. **Anomalies**: long silences, repeated errors, unexpected transitions
175
+
176
+ Note the session shape while reading — it changes which pipeline is running and
177
+ therefore which failures are possible. `Using single_node bot` vs a FlowManager
178
+ line; `channel=livekit|daily|telephony|smallwebrtc`; and `text mode, starting
179
+ flow` / `Local recording disabled for text-only session` / `lk.chat message ->
180
+ queued to LLM`, which mark a **text-only** session (no STT, no
181
+ `TranscriptionFrame`).
182
+
183
+ ### 6. Grafana link
184
+
185
+ Give the user a link to the pipecat dashboard (datasource `vl-use1`, i.e. the
186
+ same us-east1 store queried above):
187
+
188
+ ```
189
+ http://10.120.0.49/d/vl-pipecat-logs
190
+ ```
191
+
192
+ Its variables are `environment`, `application`, `container`, `pod`, `call_id`,
193
+ `trace_id`, `message_substring`, `minimum_level`. The host is an internal
194
+ LoadBalancer IP — reachable on the VPN, not from the public internet.
195
+
196
+ ## Cross-checking against the backend
197
+
198
+ When pipecat logs are thin, the backend's call-completion payload is a good
199
+ second source: it dumps the whole completion object, including
200
+ `function_calls_detailed` with each tool's `response_data` — so a failing
201
+ tool's error string is greppable even without pipecat logs. It lives in the
202
+ **Mumbai** (India) or **KSA** VL instance, not us-east1:
203
+
204
+ ```bash
205
+ kubectl --context gke_desivocalprod01_asia-south1_desivocal-prod-cluster \
206
+ -n victorialogs port-forward svc/victoria-logs 9429:9428 > /tmp/vl-pf-mum.log 2>&1 &
207
+
208
+ curl -s -m 60 "http://127.0.0.1:9429/select/logsql/query" \
209
+ --data-urlencode 'query=_time:1d application:new-calling-agent-taskiq-call-completion "<IDENTIFIER>" | limit 50'
210
+ ```
211
+
212
+ KSA is `gke_desivocalprod01_me-central2_desivocal-prod-cluster-ksa`, same
213
+ namespace and service.
214
+
215
+ ## Troubleshooting
216
+
217
+ - **Empty result, `200` status** — the usual cause is the wrong region or a
218
+ missing `_time` window, not a missing call. Work through the fallbacks in
219
+ step 3 before concluding the call has no logs.
220
+ - **`too big time range selected`** — `_time:` is mandatory and capped at 720h.
221
+ A query with no `_time` filter is rejected with a `1677-09-21 → 2262-04-11`
222
+ range in the message; that is the missing-filter error, not a real range.
223
+ - **`jq: parse error`** — the response is JSON Lines; see step 4.
224
+ - **Port-forward drops** — `kubectl port-forward` dies on idle or on pod
225
+ rotation. Re-run step 2; the retry makes that safe to repeat.
226
+ - **Zero rows, or only a handful** — you were almost certainly handed a
227
+ provider id rather than the Ringg one. Resolve it (step 3) instead of
228
+ widening the time range.
229
+ - **Slow or refused reads** — each region's `vmauth` allows 4 concurrent reads.
230
+ Serialize queries rather than fanning out.
231
+ - **A migrated webcall with no pipecat logs at all** — webcalls with
232
+ `telephony_provider=livekit` run on LiveKit Agents, not pipecat, and log to
233
+ GCP Cloud Logging (`desivocalprod01`, container `ringg-webcall`).
234
+
235
+ ## Reference
236
+
237
+ For LogsQL syntax and more filtering options, see [query-reference.md](query-reference.md).