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