Locked down bot provider secrets
This commit is contained in:
parent
64c5d8c590
commit
af5e45fb38
@ -213,6 +213,24 @@
|
||||
"get": {
|
||||
"summary": "Get Session",
|
||||
"operationId": "get_session_ai_voicebot_api_session_get",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "session_id",
|
||||
"in": "cookie",
|
||||
"required": false,
|
||||
"schema": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
],
|
||||
"title": "Session Id"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
@ -223,6 +241,16 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1223,9 +1251,9 @@
|
||||
}
|
||||
},
|
||||
"/ai-voicebot/{path}": {
|
||||
"patch": {
|
||||
"post": {
|
||||
"summary": "Proxy Static",
|
||||
"operationId": "proxy_static_ai_voicebot__path__patch",
|
||||
"operationId": "proxy_static_ai_voicebot__path__post",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "path",
|
||||
@ -1258,9 +1286,9 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"get": {
|
||||
"patch": {
|
||||
"summary": "Proxy Static",
|
||||
"operationId": "proxy_static_ai_voicebot__path__patch",
|
||||
"operationId": "proxy_static_ai_voicebot__path__post",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "path",
|
||||
@ -1295,42 +1323,7 @@
|
||||
},
|
||||
"delete": {
|
||||
"summary": "Proxy Static",
|
||||
"operationId": "proxy_static_ai_voicebot__path__patch",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "path",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Path"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"summary": "Proxy Static",
|
||||
"operationId": "proxy_static_ai_voicebot__path__patch",
|
||||
"operationId": "proxy_static_ai_voicebot__path__post",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "path",
|
||||
@ -1365,42 +1358,7 @@
|
||||
},
|
||||
"head": {
|
||||
"summary": "Proxy Static",
|
||||
"operationId": "proxy_static_ai_voicebot__path__patch",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "path",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Path"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"post": {
|
||||
"summary": "Proxy Static",
|
||||
"operationId": "proxy_static_ai_voicebot__path__patch",
|
||||
"operationId": "proxy_static_ai_voicebot__path__post",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "path",
|
||||
@ -1435,7 +1393,77 @@
|
||||
},
|
||||
"put": {
|
||||
"summary": "Proxy Static",
|
||||
"operationId": "proxy_static_ai_voicebot__path__patch",
|
||||
"operationId": "proxy_static_ai_voicebot__path__post",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "path",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Path"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"options": {
|
||||
"summary": "Proxy Static",
|
||||
"operationId": "proxy_static_ai_voicebot__path__post",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "path",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string",
|
||||
"title": "Path"
|
||||
}
|
||||
}
|
||||
],
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "Successful Response",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {}
|
||||
}
|
||||
}
|
||||
},
|
||||
"422": {
|
||||
"description": "Validation Error",
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/HTTPValidationError"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"get": {
|
||||
"summary": "Proxy Static",
|
||||
"operationId": "proxy_static_ai_voicebot__path__post",
|
||||
"parameters": [
|
||||
{
|
||||
"name": "path",
|
||||
@ -2134,7 +2162,7 @@
|
||||
"properties": {
|
||||
"providers": {
|
||||
"items": {
|
||||
"$ref": "#/components/schemas/BotProviderModel"
|
||||
"$ref": "#/components/schemas/BotProviderPublicModel"
|
||||
},
|
||||
"type": "array",
|
||||
"title": "Providers"
|
||||
@ -2147,16 +2175,12 @@
|
||||
"title": "BotProviderListResponse",
|
||||
"description": "Response listing all registered bot providers"
|
||||
},
|
||||
"BotProviderModel": {
|
||||
"BotProviderPublicModel": {
|
||||
"properties": {
|
||||
"provider_id": {
|
||||
"type": "string",
|
||||
"title": "Provider Id"
|
||||
},
|
||||
"base_url": {
|
||||
"type": "string",
|
||||
"title": "Base Url"
|
||||
},
|
||||
"name": {
|
||||
"type": "string",
|
||||
"title": "Name"
|
||||
@ -2166,10 +2190,6 @@
|
||||
"title": "Description",
|
||||
"default": ""
|
||||
},
|
||||
"provider_key": {
|
||||
"type": "string",
|
||||
"title": "Provider Key"
|
||||
},
|
||||
"registered_at": {
|
||||
"type": "number",
|
||||
"title": "Registered At"
|
||||
@ -2182,14 +2202,12 @@
|
||||
"type": "object",
|
||||
"required": [
|
||||
"provider_id",
|
||||
"base_url",
|
||||
"name",
|
||||
"provider_key",
|
||||
"registered_at",
|
||||
"last_seen"
|
||||
],
|
||||
"title": "BotProviderModel",
|
||||
"description": "Bot provider registration information"
|
||||
"title": "BotProviderPublicModel",
|
||||
"description": "Public bot provider information (safe for frontend)"
|
||||
},
|
||||
"BotProviderRegisterRequest": {
|
||||
"properties": {
|
||||
@ -2209,13 +2227,18 @@
|
||||
"provider_key": {
|
||||
"type": "string",
|
||||
"title": "Provider Key"
|
||||
},
|
||||
"provider_id": {
|
||||
"type": "string",
|
||||
"title": "Provider Id"
|
||||
}
|
||||
},
|
||||
"type": "object",
|
||||
"required": [
|
||||
"base_url",
|
||||
"name",
|
||||
"provider_key"
|
||||
"provider_key",
|
||||
"provider_id"
|
||||
],
|
||||
"title": "BotProviderRegisterRequest",
|
||||
"description": "Request to register a bot provider"
|
||||
|
@ -27,7 +27,7 @@ import {
|
||||
Refresh as RefreshIcon,
|
||||
Settings as SettingsIcon,
|
||||
} from "@mui/icons-material";
|
||||
import { botsApi, BotInfoModel, BotProviderModel, BotJoinLobbyRequest } from "./api-client";
|
||||
import { botsApi, BotInfoModel, BotProviderPublicModel, BotJoinLobbyRequest } from "./api-client";
|
||||
import BotConfig from "./BotConfig";
|
||||
import BotConfigComponent from "./BotConfig";
|
||||
|
||||
@ -40,7 +40,7 @@ interface BotManagerProps {
|
||||
const BotManager: React.FC<BotManagerProps> = ({ lobbyId, onBotAdded, sx }) => {
|
||||
const [bots, setBots] = useState<BotInfoModel[]>([]);
|
||||
const [providers, setProviders] = useState<Record<string, string>>({});
|
||||
const [botProviders, setBotProviders] = useState<BotProviderModel[]>([]);
|
||||
const [botProviders, setBotProviders] = useState<BotProviderPublicModel[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
const [addDialogOpen, setAddDialogOpen] = useState(false);
|
||||
@ -77,7 +77,7 @@ const BotManager: React.FC<BotManagerProps> = ({ lobbyId, onBotAdded, sx }) => {
|
||||
|
||||
setAddingBot(true);
|
||||
setError(""); // Clear any previous errors
|
||||
|
||||
|
||||
try {
|
||||
const request: BotJoinLobbyRequest = {
|
||||
lobby_id: lobbyId,
|
||||
@ -88,21 +88,21 @@ const BotManager: React.FC<BotManagerProps> = ({ lobbyId, onBotAdded, sx }) => {
|
||||
// Retry logic for handling service restart scenarios
|
||||
let retries = 3;
|
||||
let response;
|
||||
|
||||
|
||||
while (retries > 0) {
|
||||
try {
|
||||
response = await botsApi.requestJoinLobby(selectedBot, request);
|
||||
break; // Success, exit retry loop
|
||||
} catch (err: any) {
|
||||
retries--;
|
||||
|
||||
|
||||
// If it's a 404 error and we have retries left, wait and retry
|
||||
if (err?.status === 404 && retries > 0) {
|
||||
console.log(`Bot join failed with 404, retrying... (${retries} attempts left)`);
|
||||
await new Promise(resolve => setTimeout(resolve, 1000)); // Wait 1 second
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000)); // Wait 1 second
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// If it's not a 404 or we're out of retries, throw the error
|
||||
throw err;
|
||||
}
|
||||
@ -272,9 +272,6 @@ const BotManager: React.FC<BotManagerProps> = ({ lobbyId, onBotAdded, sx }) => {
|
||||
<Typography variant="body2" component="div">
|
||||
{provider.description || "No description"}
|
||||
</Typography>
|
||||
<Typography variant="caption" color="text.secondary">
|
||||
{provider.base_url}
|
||||
</Typography>
|
||||
</Box>
|
||||
}
|
||||
secondaryTypographyProps={{ component: "div" }}
|
||||
|
@ -28,7 +28,7 @@ export type BotLeaveLobbyResponse = components["schemas"]["BotLeaveLobbyResponse
|
||||
export type BotListResponse = components["schemas"]["BotListResponse"];
|
||||
export type BotLobbyConfig = components["schemas"]["BotLobbyConfig"];
|
||||
export type BotProviderListResponse = components["schemas"]["BotProviderListResponse"];
|
||||
export type BotProviderModel = components["schemas"]["BotProviderModel"];
|
||||
export type BotProviderPublicModel = components["schemas"]["BotProviderPublicModel"];
|
||||
export type BotProviderRegisterRequest = components["schemas"]["BotProviderRegisterRequest"];
|
||||
export type BotProviderRegisterResponse = components["schemas"]["BotProviderRegisterResponse"];
|
||||
export type ChatMessageModel = components["schemas"]["ChatMessageModel"];
|
||||
@ -277,33 +277,33 @@ export class ApiClient {
|
||||
return this.request<any>(this.getApiPath(`/ai-voicebot/api/metrics/export`), { method: "GET" });
|
||||
}
|
||||
|
||||
async updateProxyStatic(path: string): Promise<any> {
|
||||
return this.request<any>(this.getApiPath(`/ai-voicebot/${path}`), { method: "PATCH" });
|
||||
async createProxyStatic(path: string): Promise<any> {
|
||||
return this.request<any>(this.getApiPath(`/ai-voicebot/${path}`), { method: "POST" });
|
||||
}
|
||||
|
||||
async getProxyStatic(path: string): Promise<any> {
|
||||
return this.request<any>(this.getApiPath(`/ai-voicebot/${path}`), { method: "GET" });
|
||||
async updateProxyStatic(path: string): Promise<any> {
|
||||
return this.request<any>(this.getApiPath(`/ai-voicebot/${path}`), { method: "PATCH" });
|
||||
}
|
||||
|
||||
async deleteProxyStatic(path: string): Promise<any> {
|
||||
return this.request<any>(this.getApiPath(`/ai-voicebot/${path}`), { method: "DELETE" });
|
||||
}
|
||||
|
||||
async optionsProxyStatic(path: string): Promise<any> {
|
||||
return this.request<any>(this.getApiPath(`/ai-voicebot/${path}`), { method: "OPTIONS" });
|
||||
}
|
||||
|
||||
async headProxyStatic(path: string): Promise<any> {
|
||||
return this.request<any>(this.getApiPath(`/ai-voicebot/${path}`), { method: "HEAD" });
|
||||
}
|
||||
|
||||
async createProxyStatic(path: string): Promise<any> {
|
||||
return this.request<any>(this.getApiPath(`/ai-voicebot/${path}`), { method: "POST" });
|
||||
}
|
||||
|
||||
async replaceProxyStatic(path: string): Promise<any> {
|
||||
return this.request<any>(this.getApiPath(`/ai-voicebot/${path}`), { method: "PUT" });
|
||||
}
|
||||
|
||||
async optionsProxyStatic(path: string): Promise<any> {
|
||||
return this.request<any>(this.getApiPath(`/ai-voicebot/${path}`), { method: "OPTIONS" });
|
||||
}
|
||||
|
||||
async getProxyStatic(path: string): Promise<any> {
|
||||
return this.request<any>(this.getApiPath(`/ai-voicebot/${path}`), { method: "GET" });
|
||||
}
|
||||
}
|
||||
|
||||
// Default client instance
|
||||
|
@ -263,19 +263,19 @@ export interface paths {
|
||||
};
|
||||
"/ai-voicebot/{path}": {
|
||||
/** Proxy Static */
|
||||
get: operations["proxy_static_ai_voicebot__path__patch"];
|
||||
get: operations["proxy_static_ai_voicebot__path__post"];
|
||||
/** Proxy Static */
|
||||
put: operations["proxy_static_ai_voicebot__path__patch"];
|
||||
put: operations["proxy_static_ai_voicebot__path__post"];
|
||||
/** Proxy Static */
|
||||
post: operations["proxy_static_ai_voicebot__path__patch"];
|
||||
post: operations["proxy_static_ai_voicebot__path__post"];
|
||||
/** Proxy Static */
|
||||
delete: operations["proxy_static_ai_voicebot__path__patch"];
|
||||
delete: operations["proxy_static_ai_voicebot__path__post"];
|
||||
/** Proxy Static */
|
||||
options: operations["proxy_static_ai_voicebot__path__patch"];
|
||||
options: operations["proxy_static_ai_voicebot__path__post"];
|
||||
/** Proxy Static */
|
||||
head: operations["proxy_static_ai_voicebot__path__patch"];
|
||||
head: operations["proxy_static_ai_voicebot__path__post"];
|
||||
/** Proxy Static */
|
||||
patch: operations["proxy_static_ai_voicebot__path__patch"];
|
||||
patch: operations["proxy_static_ai_voicebot__path__post"];
|
||||
};
|
||||
}
|
||||
|
||||
@ -587,17 +587,15 @@ export interface components {
|
||||
*/
|
||||
BotProviderListResponse: {
|
||||
/** Providers */
|
||||
providers: components["schemas"]["BotProviderModel"][];
|
||||
providers: components["schemas"]["BotProviderPublicModel"][];
|
||||
};
|
||||
/**
|
||||
* BotProviderModel
|
||||
* @description Bot provider registration information
|
||||
* BotProviderPublicModel
|
||||
* @description Public bot provider information (safe for frontend)
|
||||
*/
|
||||
BotProviderModel: {
|
||||
BotProviderPublicModel: {
|
||||
/** Provider Id */
|
||||
provider_id: string;
|
||||
/** Base Url */
|
||||
base_url: string;
|
||||
/** Name */
|
||||
name: string;
|
||||
/**
|
||||
@ -605,8 +603,6 @@ export interface components {
|
||||
* @default
|
||||
*/
|
||||
description?: string;
|
||||
/** Provider Key */
|
||||
provider_key: string;
|
||||
/** Registered At */
|
||||
registered_at: number;
|
||||
/** Last Seen */
|
||||
@ -628,6 +624,8 @@ export interface components {
|
||||
description?: string;
|
||||
/** Provider Key */
|
||||
provider_key: string;
|
||||
/** Provider Id */
|
||||
provider_id: string;
|
||||
};
|
||||
/**
|
||||
* BotProviderRegisterResponse
|
||||
@ -944,6 +942,11 @@ export interface operations {
|
||||
};
|
||||
/** Get Session */
|
||||
get_session_ai_voicebot_api_session_get: {
|
||||
parameters: {
|
||||
cookie?: {
|
||||
session_id?: string | null;
|
||||
};
|
||||
};
|
||||
responses: {
|
||||
/** @description Successful Response */
|
||||
200: {
|
||||
@ -951,6 +954,12 @@ export interface operations {
|
||||
"application/json": components["schemas"]["SessionResponse"];
|
||||
};
|
||||
};
|
||||
/** @description Validation Error */
|
||||
422: {
|
||||
content: {
|
||||
"application/json": components["schemas"]["HTTPValidationError"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
/** List Lobbies */
|
||||
@ -1568,7 +1577,7 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
/** Proxy Static */
|
||||
proxy_static_ai_voicebot__path__patch: {
|
||||
proxy_static_ai_voicebot__path__post: {
|
||||
parameters: {
|
||||
path: {
|
||||
path: string;
|
||||
|
@ -19,6 +19,7 @@ sys.path.append(
|
||||
)
|
||||
from shared.models import (
|
||||
BotProviderModel,
|
||||
BotProviderPublicModel,
|
||||
BotProviderRegisterRequest,
|
||||
BotProviderRegisterResponse,
|
||||
BotProviderListResponse,
|
||||
@ -190,23 +191,20 @@ class BotManager:
|
||||
logger.warning(f"Rejected bot provider registration with invalid key: {request.provider_key}")
|
||||
raise ValueError("Invalid provider key. Bot provider is not authorized to register.")
|
||||
|
||||
# Check if there's already an active provider with this key and remove it
|
||||
providers_to_remove: List[str] = []
|
||||
with self.lock:
|
||||
for existing_provider_id, existing_provider in self.bot_providers.items():
|
||||
if existing_provider.provider_key == request.provider_key:
|
||||
providers_to_remove.append(existing_provider_id)
|
||||
logger.info(f"Removing stale bot provider: {existing_provider.name} (ID: {existing_provider_id})")
|
||||
# Require provider_id for static registration
|
||||
if not request.provider_id:
|
||||
logger.warning("Rejected bot provider registration without provider_id")
|
||||
raise ValueError("provider_id is required for bot provider registration.")
|
||||
|
||||
# Remove stale providers
|
||||
for provider_id_to_remove in providers_to_remove:
|
||||
del self.bot_providers[provider_id_to_remove]
|
||||
|
||||
# Save after removing stale providers
|
||||
if providers_to_remove:
|
||||
self._save_bot_providers()
|
||||
provider_id = request.provider_id
|
||||
|
||||
provider_id = str(uuid.uuid4())
|
||||
# Remove any existing provider with the same provider_id (this handles restarts/re-registration)
|
||||
with self.lock:
|
||||
if provider_id in self.bot_providers:
|
||||
logger.info(
|
||||
f"Removing existing provider with ID: {provider_id} for re-registration"
|
||||
)
|
||||
del self.bot_providers[provider_id]
|
||||
now = time.time()
|
||||
|
||||
provider = BotProviderModel(
|
||||
@ -232,9 +230,21 @@ class BotManager:
|
||||
return BotProviderRegisterResponse(provider_id=provider_id)
|
||||
|
||||
def list_providers(self) -> BotProviderListResponse:
|
||||
"""List all registered bot providers"""
|
||||
"""List all registered bot providers (public information only)"""
|
||||
with self.lock:
|
||||
return BotProviderListResponse(providers=list(self.bot_providers.values()))
|
||||
# Create safe public versions of provider info
|
||||
public_providers: List[BotProviderPublicModel] = []
|
||||
for provider in self.bot_providers.values():
|
||||
public_provider = BotProviderPublicModel(
|
||||
provider_id=provider.provider_id,
|
||||
name=provider.name,
|
||||
description=provider.description,
|
||||
registered_at=provider.registered_at,
|
||||
last_seen=provider.last_seen
|
||||
)
|
||||
public_providers.append(public_provider)
|
||||
|
||||
return BotProviderListResponse(providers=public_providers)
|
||||
|
||||
async def list_bots(self) -> BotListResponse:
|
||||
"""List all available bots from all registered providers"""
|
||||
|
@ -447,6 +447,7 @@ class BotProviderRegisterRequest(BaseModel):
|
||||
name: str
|
||||
description: str = ""
|
||||
provider_key: str
|
||||
provider_id: str # Required static provider ID
|
||||
|
||||
|
||||
class BotProviderRegisterResponse(BaseModel):
|
||||
@ -456,10 +457,20 @@ class BotProviderRegisterResponse(BaseModel):
|
||||
status: str = "registered"
|
||||
|
||||
|
||||
class BotProviderPublicModel(BaseModel):
|
||||
"""Public bot provider information (safe for frontend)"""
|
||||
|
||||
provider_id: str
|
||||
name: str
|
||||
description: str = ""
|
||||
registered_at: float
|
||||
last_seen: float
|
||||
|
||||
|
||||
class BotProviderListResponse(BaseModel):
|
||||
"""Response listing all registered bot providers"""
|
||||
|
||||
providers: List[BotProviderModel]
|
||||
providers: List[BotProviderPublicModel]
|
||||
|
||||
|
||||
class BotListResponse(BaseModel):
|
||||
|
@ -529,16 +529,24 @@ async def register_with_server(server_url: str, voicebot_url: str, insecure: boo
|
||||
# Import httpx locally to avoid dependency issues
|
||||
import httpx
|
||||
|
||||
# Get provider key from environment variable
|
||||
provider_key = os.getenv('VOICEBOT_PROVIDER_KEY', 'default-voicebot')
|
||||
# Get provider key and ID from environment variables
|
||||
provider_key = os.getenv('VOICEBOT_PROVIDER_KEY')
|
||||
provider_id = os.getenv('VOICEBOT_PROVIDER_ID')
|
||||
|
||||
if not provider_key:
|
||||
raise ValueError("VOICEBOT_PROVIDER_KEY environment variable is required")
|
||||
if not provider_id:
|
||||
raise ValueError("VOICEBOT_PROVIDER_ID environment variable is required")
|
||||
|
||||
payload = {
|
||||
"base_url": voicebot_url.rstrip('/'),
|
||||
"name": "voicebot-provider",
|
||||
"description": "AI voicebot provider with speech recognition and synthetic media capabilities",
|
||||
"provider_key": provider_key
|
||||
"provider_key": provider_key,
|
||||
"provider_id": provider_id
|
||||
}
|
||||
|
||||
logger.info(f"📍 Using static provider ID: {provider_id}")
|
||||
logger.info(f"📤 Sending registration payload: {payload}")
|
||||
|
||||
# Prepare SSL context if needed
|
||||
|
@ -265,6 +265,7 @@ async def handle_track_received(peer: Peer, track: MediaStreamTrack):
|
||||
# Receive audio frame
|
||||
frame = await track.recv()
|
||||
if isinstance(frame, AudioFrame):
|
||||
logger.info(f"Received audio frame: {frame.sample_rate}Hz, {frame.format.name}, {frame.layout.name}")
|
||||
# Convert AudioFrame to numpy array
|
||||
audio_data = frame.to_ndarray()
|
||||
|
||||
@ -292,6 +293,8 @@ async def handle_track_received(peer: Peer, track: MediaStreamTrack):
|
||||
# Send to audio processor
|
||||
if _audio_processor:
|
||||
_audio_processor.add_audio_data(audio_data_float32)
|
||||
else:
|
||||
logger.warning(f"Received non-audio frame on audio track from {peer.peer_name}")
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error processing audio track from {peer.peer_name}: {e}", exc_info=True)
|
||||
|
Loading…
x
Reference in New Issue
Block a user