sync: migrate ai-operator to Gitea (2026-08-10)

This commit is contained in:
konturai-ops
2026-08-10 15:26:52 +00:00
commit 53652b95ad
173 changed files with 16676 additions and 0 deletions
+120
View File
@@ -0,0 +1,120 @@
# Conversation State Machine
## Purpose
The conversation state machine enforces the safe order of an AI Operator call. The assistant cannot answer business questions, search a knowledge base, or execute business tools until both language and region are selected in code.
## States
```text
CALL_STARTED
-> GREETING
-> LANGUAGE_SELECTION
-> REGION_SELECTION
-> READY_TO_HELP
-> QUESTION_ANSWERING
-> READY_TO_HELP
-> CLOSING
-> ENDED
```
`HANDOFF` can be entered from any non-ended state. `CLOSING` and `ENDED` can also be entered from any non-ended state. `ENDED` is immutable.
## Transition Table
| From | Event | To | Requirement |
| --- | --- | --- | --- |
| CALL_STARTED | call.started | GREETING | call session exists |
| GREETING | greeting.played | LANGUAGE_SELECTION | bilingual greeting prepared |
| LANGUAGE_SELECTION | language.selected | REGION_SELECTION | language is `ru` or `kk` |
| REGION_SELECTION | region.selected | READY_TO_HELP | normalized region code is selected |
| READY_TO_HELP | question.received | QUESTION_ANSWERING | language and region selected |
| QUESTION_ANSWERING | answer.completed | READY_TO_HELP | answer flow completed |
| any non-ended | handoff.requested | HANDOFF | none |
| any non-ended | closing.requested | CLOSING | none |
| any non-ended | call.ended | ENDED | none |
Invalid transitions return errors and do not mutate state. Denied actions are recorded in session history.
## Tool Permission Matrix
| State | Allowed Tools |
| --- | --- |
| CALL_STARTED | none |
| GREETING | none |
| LANGUAGE_SELECTION | `set_language`, `request_human_handoff`, `end_call` |
| REGION_SELECTION | `set_region`, `set_language`, `request_human_handoff`, `end_call` |
| READY_TO_HELP | `search_knowledge_base`, `set_language`, `set_region`, `request_human_handoff`, `end_call` |
| QUESTION_ANSWERING | `search_knowledge_base`, `request_human_handoff`, `end_call`, `set_language`, `set_region` |
| HANDOFF | `end_call` |
| CLOSING | `end_call` |
| ENDED | none |
## Hard Guardrail
`search_knowledge_base` is denied unless all of these are true:
- language is `ru` or `kk`;
- region status is `selected`;
- region code is not empty;
- state is `READY_TO_HELP` or `QUESTION_ANSWERING`.
This is enforced in Go code by `internal/dialogue/policy`, independently of prompts.
## Messages
The message catalog has bilingual initial greeting plus Russian and Kazakh fragments for language, region, ready, denial, handoff, and closing states.
Initial greeting:
```text
Здравствуйте! Это AI-оператор. Выберите язык обслуживания: русский или қазақша.
Сәлеметсіз бе! Бұл AI-оператор. Қызмет көрсету тілін таңдаңыз: қазақша немесе русский.
```
## Prompt Fragments
`internal/dialogue/prompt` builds state-aware prompt fragments that include current state, language, region, next action, and forbidden actions. Prompt fragments are secondary; policy enforcement remains in Go code.
## CLI Usage
```bash
./bin/ai-operator doctor --env /etc/ai-operator/ai-operator.env --check-dialogue
./bin/ai-operator dialogue-self-test --env /etc/ai-operator/ai-operator.env
./bin/ai-operator dialogue-self-test --env /etc/ai-operator/ai-operator.env --json
```
The self-test runs without Asterisk calls, OpenAI, database, or external services.
## Integration
For the test route only, Call Manager creates a Dialogue Orchestrator session before starting the voice provider. The provider receives a state-aware system prompt. On hangup, Call Manager ends and cleans the dialogue session.
Production Kazakhtelecom routes remain disabled.
## Not Implemented Yet
- language detection from speech;
- region resolver;
- Knowledge Base/RAG;
- final agent prompt;
- real business tools;
- production route switch.
## TZ-07 Language Detector
Language selection is now handled by `internal/dialogue/language`. The state machine still stores strict `ru` or `kk`, while detector input can be natural text such as `русский`, `қазақша`, `russian`, or `kazakh`.
## TZ-08 Region Resolver Update
TZ-08 adds an offline Kazakhstan Region Resolver with 20 enabled regions, stable `region_code` values, Almaty city/region clarification, false-positive protection, and explicit region-change policy. Production routing remains disabled; OpenAI, PostgreSQL, and Knowledge Base/RAG are still not used at this stage.
## TZ-09 Knowledge Base Update
TZ-09 adds PostgreSQL + pgvector, KGA JSONL ingestion, fake embeddings, hybrid KB search, cross-language fallback for KK queries, citations, and `search_knowledge_base` integration behind the existing language/region guardrail. OpenAI is not called automatically and production routing remains disabled.
## TZ-10 Agent Integration
The state machine remains the hard gate for business answers. Agent prompt instructions are secondary; `search_knowledge_base` is still denied before language and region are selected. ToolCall results now flow back to the VoiceProvider.
## TZ-11 Handoff
`request_human_handoff` moves active conversations to `HANDOFF`. Repeated handoff requests are idempotent. `ENDED` remains immutable.