mirror of
https://github.com/OpenSquawk/OpenSquawk
synced 2026-05-13 01:46:08 +08:00
Replace the LLM-per-request flow in /pm with a stateful Python backend
(OpenSquawk-LiveATC-api). The backend owns session state, does regex-first
routing with readback evaluation, and returns the next state + ATC speech.
The frontend keeps its local cursor (communicationsEngine) for TTS and
monitoring UI, but no longer calls /api/llm/decide.
Changes:
app/composables/useRadioBackend.ts (new)
Typed Nuxt composable wrapping the Python REST API:
createSession, transmit, deleteSession, fetchFlows.
Base URL read from NUXT_PUBLIC_RADIO_BACKEND_URL (default 127.0.0.1:8000).
nuxt.config.ts
Expose radioBackendUrl as a public runtime config key so the composable
and communicationsEngine can both reach the Python backend.
shared/utils/communicationsEngine.ts
- fetchRuntimeTree now accepts an optional baseUrl so it fetches from the
Python backend instead of the Nuxt server when a URL is provided.
- renderTpl handles both {var} (old MongoDB schema) and {{var}} (new YAML
schema) — double-brace matched first to avoid partial matches.
- stateSayTpl / stateUtteranceTpl helpers unify say_tpl|say_template and
utterance_tpl|expected_pilot_template across both schema versions.
- auto_transitions from the new YAML schema are included when collecting
eligible transitions in collectAtcStatesUntilPilotTurn.
shared/types/decision.ts
RuntimeDecisionState extended with say_template and expected_pilot_template
fields (new YAML schema field names alongside the existing legacy names).
app/pages/pm.vue
- startMonitoring: loads tree from Python backend, then creates a backend
session (backendSessionId). Cursor synced to session.current_state.
- handlePilotTransmission: calls radioBackend.transmit instead of
/api/llm/decide. Applies auto_advanced_states via moveToSilent, then
the final state. Speaks controller_say_template via TTS.
- Both fetchRuntimeTree calls now pass radioBackendUrl so they hit the
Python backend, not the Nuxt flow-from-MongoDB path.
AGENTS.md (new)
Project guide updated to document the new two-backend architecture,
the Python backend session lifecycle, and the dual template schema.
docs/plans/2026-05-06-pm-python-runtime-contract.md (new)
Implementation plan and API contract written before the work started.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2.9 KiB
2.9 KiB
OpenSquawk - Project Guide
Architecture
- Nuxt 4 (Vue 3 SFC) frontend in
/app - H3 server handlers in
/server - Shared types/utils in
/shared - MongoDB models in
/server/models - Python backend (
OpenSquawk-LiveATC-api) — owns PM session state and routing decisions; runs onhttp://127.0.0.1:8000
Key Files
/shared/utils/communicationsEngine.ts— Core state machine composable (used by/pmlive ATC). Drives local cursor and TTS; Python backend owns the authoritative state./app/composables/useRadioBackend.ts— Typed wrapper around the Python backend REST API (createSession,transmit,deleteSession,fetchFlows)/server/utils/openai.ts— Legacy LLM decision router (routeDecision()). No longer called by/pm; may still be used by other routes./server/services/decisionFlowService.ts— Builds runtime decision trees from MongoDB (used by Nuxt/api/decision-flows/runtime;/pmnow fetches directly from the Python backend)/app/pages/pm.vue— Live ATC page (speech-to-text, PTT, text input)/app/pages/classroom.vue— Classroom learning mode (separate system, does NOT use communicationsEngine)
Live ATC Flow (/pm) — current
startMonitoring()→fetchRuntimeTree('icao_atc_decision_tree', radioBackendUrl)loads the YAML flow from Python backend into the local engine (for cursor tracking / TTS)startMonitoring()→radioBackend.createSession('icao_atc_decision_tree')creates an authoritative server-side session; storesbackendSessionId- User inputs (PTT or text) →
handlePilotTransmission() radioBackend.transmit(backendSessionId, transcript)→ Python backend runs regex routing, readback evaluation, and side effects; returnsnext_state_id,controller_say_template,auto_advanced_states,flagsmoveToSilent(stateId)called for each auto-advanced state then the final state — advances local cursor without triggering further auto-transitionsscheduleControllerSpeech(controller_say_template)speaks the ATC reply via TTS- PTT path: STT still goes to Nuxt (
POST /api/atc/ptt); transcription result then calls step 4
Decision Tree States
States have role: 'pilot' | 'atc' | 'system'. The engine supports two template field naming conventions:
- Old schema:
say_tpl,utterance_tpl(MongoDB/legacy) - New schema:
say_template,expected_pilot_template(Python backend YAML)
Both are handled transparently by stateSayTpl() and stateUtteranceTpl() helpers in communicationsEngine.ts.
Template variables use {{variable}} (new) or {variable} (old) — both are rendered by renderTpl().
Transitions: next, ok_next, bad_next, timer_next, auto_transitions.
Environment Variables
NUXT_PUBLIC_RADIO_BACKEND_URL— URL of the Python backend (defaulthttp://127.0.0.1:8000)
Commands
bun run dev— dev server (Nuxt)- Python backend: see
OpenSquawk-LiveATC-api/README.md