mirror of
https://github.com/OpenSquawk/OpenSquawk
synced 2026-08-10 19:36:04 +08:00
Wire /pm to Python backend for stateful ATC training sessions
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>
This commit is contained in:
44
AGENTS.md
Normal file
44
AGENTS.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# 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 on `http://127.0.0.1:8000`
|
||||
|
||||
## Key Files
|
||||
- `/shared/utils/communicationsEngine.ts` — Core state machine composable (used by `/pm` live 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`; `/pm` now 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
|
||||
|
||||
1. `startMonitoring()` → `fetchRuntimeTree('icao_atc_decision_tree', radioBackendUrl)` loads the YAML flow from Python backend into the local engine (for cursor tracking / TTS)
|
||||
2. `startMonitoring()` → `radioBackend.createSession('icao_atc_decision_tree')` creates an authoritative server-side session; stores `backendSessionId`
|
||||
3. User inputs (PTT or text) → `handlePilotTransmission()`
|
||||
4. `radioBackend.transmit(backendSessionId, transcript)` → Python backend runs regex routing, readback evaluation, and side effects; returns `next_state_id`, `controller_say_template`, `auto_advanced_states`, `flags`
|
||||
5. `moveToSilent(stateId)` called for each auto-advanced state then the final state — advances local cursor without triggering further auto-transitions
|
||||
6. `scheduleControllerSpeech(controller_say_template)` speaks the ATC reply via TTS
|
||||
7. 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 (default `http://127.0.0.1:8000`)
|
||||
|
||||
## Commands
|
||||
- `bun run dev` — dev server (Nuxt)
|
||||
- Python backend: see `OpenSquawk-LiveATC-api/README.md`
|
||||
Reference in New Issue
Block a user