Files
go-sip/cmd/sip-go-agent/current_agent_scenario.go
T

70 lines
2.9 KiB
Go

package main
import (
"bytes"
"encoding/base64"
"encoding/json"
"errors"
"io"
"os"
"strings"
"git.ipao.vip/rogee/go-sip/internal/ai"
)
const maxApprovedMockScenarioBytes = 4 << 20
type approvedMockScenario struct {
InboundPCM16 []byte
Script ai.ApprovedMockScript
MaxWAVBytes int64
ExpectedRecording bool
Outcome string
ReasonMessage string
}
// loadApprovedMockScenario reads only explicit synthetic media facts. It does
// not read or override the AI business configuration delivered by Dispatcher.
func loadApprovedMockScenario(path string) (approvedMockScenario, error) {
if strings.TrimSpace(path) == "" {
return approvedMockScenario{}, errors.New("AGENT_MOCK_SCENARIO_FILE is required")
}
file, err := os.Open(path)
if err != nil {
return approvedMockScenario{}, errors.New("AGENT_MOCK_SCENARIO_FILE cannot be opened")
}
defer file.Close()
data, err := io.ReadAll(io.LimitReader(file, maxApprovedMockScenarioBytes+1))
if err != nil || len(data) > maxApprovedMockScenarioBytes {
return approvedMockScenario{}, errors.New("AGENT_MOCK_SCENARIO_FILE exceeds its size limit or cannot be read")
}
var encoded struct {
InboundPCM16 *string `json:"inbound_pcm16"`
Script *ai.ApprovedMockScript `json:"script"`
MaxWAVBytes *int64 `json:"max_wav_bytes"`
ExpectedRecording *bool `json:"expected_recording"`
Outcome *string `json:"outcome"`
ReasonMessage *string `json:"reason_message"`
}
decoder := json.NewDecoder(bytes.NewReader(data))
decoder.DisallowUnknownFields()
if err := decoder.Decode(&encoded); err != nil {
return approvedMockScenario{}, errors.New("AGENT_MOCK_SCENARIO_FILE has invalid fields")
}
if err := decoder.Decode(new(any)); err != io.EOF {
return approvedMockScenario{}, errors.New("AGENT_MOCK_SCENARIO_FILE contains extra data")
}
if encoded.InboundPCM16 == nil || encoded.Script == nil || encoded.MaxWAVBytes == nil || encoded.ExpectedRecording == nil || encoded.Outcome == nil || encoded.ReasonMessage == nil {
return approvedMockScenario{}, errors.New("AGENT_MOCK_SCENARIO_FILE requires explicit media, script, outcome and recording facts")
}
pcm, err := base64.StdEncoding.DecodeString(*encoded.InboundPCM16)
if err != nil || len(encoded.Script.Turns) == 0 || *encoded.MaxWAVBytes <= 44 || strings.TrimSpace(*encoded.ReasonMessage) == "" ||
(*encoded.Outcome != "answered" && *encoded.Outcome != "no_answer" && *encoded.Outcome != "failed") {
return approvedMockScenario{}, errors.New("AGENT_MOCK_SCENARIO_FILE has invalid synthetic media or outcome")
}
return approvedMockScenario{
InboundPCM16: pcm, Script: *encoded.Script, MaxWAVBytes: *encoded.MaxWAVBytes,
ExpectedRecording: *encoded.ExpectedRecording, Outcome: *encoded.Outcome, ReasonMessage: *encoded.ReasonMessage,
}, nil
}