v0.1.4-p6
parent
4c99826863
commit
02a4000416
|
|
@ -34,7 +34,6 @@ DEFAULT_BOT_SYSTEM_TIMEZONE=Asia/Shanghai
|
||||||
# The following platform-level items are initialized by SQL and managed in sys_setting / 平台参数:
|
# The following platform-level items are initialized by SQL and managed in sys_setting / 平台参数:
|
||||||
# - page_size
|
# - page_size
|
||||||
# - chat_pull_page_size
|
# - chat_pull_page_size
|
||||||
# - command_auto_unlock_seconds
|
|
||||||
# - upload_max_mb
|
# - upload_max_mb
|
||||||
# - allowed_attachment_extensions
|
# - allowed_attachment_extensions
|
||||||
# - workspace_download_extensions
|
# - workspace_download_extensions
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ from services.bot_management_service import (
|
||||||
list_bots_with_cache,
|
list_bots_with_cache,
|
||||||
update_bot_record,
|
update_bot_record,
|
||||||
)
|
)
|
||||||
|
from services.image_service import list_registered_images
|
||||||
from services.provider_service import test_provider_connection
|
from services.provider_service import test_provider_connection
|
||||||
|
|
||||||
router = APIRouter()
|
router = APIRouter()
|
||||||
|
|
@ -28,6 +29,22 @@ async def test_provider(payload: dict):
|
||||||
return await test_provider_connection(payload)
|
return await test_provider_connection(payload)
|
||||||
|
|
||||||
|
|
||||||
|
@router.post("/api/bots/{bot_id}/providers/test")
|
||||||
|
async def test_bot_provider(bot_id: str, payload: dict, session: Session = Depends(get_session)):
|
||||||
|
bot = session.get(BotInstance, bot_id)
|
||||||
|
if not bot:
|
||||||
|
raise HTTPException(status_code=404, detail="Bot not found")
|
||||||
|
return await test_provider_connection(payload)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/api/bots/{bot_id}/images")
|
||||||
|
def list_bot_images(bot_id: str, session: Session = Depends(get_session)):
|
||||||
|
bot = session.get(BotInstance, bot_id)
|
||||||
|
if not bot:
|
||||||
|
raise HTTPException(status_code=404, detail="Bot not found")
|
||||||
|
return list_registered_images(session)
|
||||||
|
|
||||||
|
|
||||||
@router.post("/api/bots")
|
@router.post("/api/bots")
|
||||||
def create_bot(payload: BotCreateRequest, session: Session = Depends(get_session)):
|
def create_bot(payload: BotCreateRequest, session: Session = Depends(get_session)):
|
||||||
return create_bot_record(session, payload=payload)
|
return create_bot_record(session, payload=payload)
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ def get_system_defaults():
|
||||||
"chat": {
|
"chat": {
|
||||||
"pull_page_size": platform_settings.chat_pull_page_size,
|
"pull_page_size": platform_settings.chat_pull_page_size,
|
||||||
"page_size": platform_settings.page_size,
|
"page_size": platform_settings.page_size,
|
||||||
"command_auto_unlock_seconds": platform_settings.command_auto_unlock_seconds,
|
|
||||||
},
|
},
|
||||||
"topic_presets": get_topic_presets()["presets"],
|
"topic_presets": get_topic_presets()["presets"],
|
||||||
"speech": {
|
"speech": {
|
||||||
|
|
|
||||||
|
|
@ -45,7 +45,6 @@ REQUIRED_TABLES = (
|
||||||
REQUIRED_SYS_SETTING_KEYS = (
|
REQUIRED_SYS_SETTING_KEYS = (
|
||||||
"page_size",
|
"page_size",
|
||||||
"chat_pull_page_size",
|
"chat_pull_page_size",
|
||||||
"command_auto_unlock_seconds",
|
|
||||||
"auth_token_ttl_hours",
|
"auth_token_ttl_hours",
|
||||||
"auth_token_max_active",
|
"auth_token_max_active",
|
||||||
"upload_max_mb",
|
"upload_max_mb",
|
||||||
|
|
|
||||||
|
|
@ -187,7 +187,6 @@ DATABASE_POOL_RECYCLE: Final[int] = _env_int("DATABASE_POOL_RECYCLE", 1800, 30,
|
||||||
DEFAULT_UPLOAD_MAX_MB: Final[int] = 100
|
DEFAULT_UPLOAD_MAX_MB: Final[int] = 100
|
||||||
DEFAULT_PAGE_SIZE: Final[int] = 10
|
DEFAULT_PAGE_SIZE: Final[int] = 10
|
||||||
DEFAULT_CHAT_PULL_PAGE_SIZE: Final[int] = 60
|
DEFAULT_CHAT_PULL_PAGE_SIZE: Final[int] = 60
|
||||||
DEFAULT_COMMAND_AUTO_UNLOCK_SECONDS: Final[int] = 10
|
|
||||||
DEFAULT_AUTH_TOKEN_TTL_HOURS: Final[int] = _env_int("AUTH_TOKEN_TTL_HOURS", 24, 1, 720)
|
DEFAULT_AUTH_TOKEN_TTL_HOURS: Final[int] = _env_int("AUTH_TOKEN_TTL_HOURS", 24, 1, 720)
|
||||||
DEFAULT_AUTH_TOKEN_MAX_ACTIVE: Final[int] = _env_int("AUTH_TOKEN_MAX_ACTIVE", 2, 1, 20)
|
DEFAULT_AUTH_TOKEN_MAX_ACTIVE: Final[int] = _env_int("AUTH_TOKEN_MAX_ACTIVE", 2, 1, 20)
|
||||||
DEFAULT_BOT_SYSTEM_TIMEZONE: Final[str] = str(
|
DEFAULT_BOT_SYSTEM_TIMEZONE: Final[str] = str(
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ from pydantic import BaseModel, Field
|
||||||
class PlatformSettingsPayload(BaseModel):
|
class PlatformSettingsPayload(BaseModel):
|
||||||
page_size: int = Field(default=10, ge=1, le=100)
|
page_size: int = Field(default=10, ge=1, le=100)
|
||||||
chat_pull_page_size: int = Field(default=60, ge=10, le=500)
|
chat_pull_page_size: int = Field(default=60, ge=10, le=500)
|
||||||
command_auto_unlock_seconds: int = Field(default=10, ge=1, le=600)
|
|
||||||
auth_token_ttl_hours: int = Field(default=24, ge=1, le=720)
|
auth_token_ttl_hours: int = Field(default=24, ge=1, le=720)
|
||||||
auth_token_max_active: int = Field(default=2, ge=1, le=20)
|
auth_token_max_active: int = Field(default=2, ge=1, le=20)
|
||||||
upload_max_mb: int = Field(default=100, ge=1, le=2048)
|
upload_max_mb: int = Field(default=100, ge=1, le=2048)
|
||||||
|
|
|
||||||
|
|
@ -424,6 +424,7 @@ def serialize_bot_detail(bot: BotInstance) -> Dict[str, Any]:
|
||||||
"image_tag": bot.image_tag,
|
"image_tag": bot.image_tag,
|
||||||
"llm_provider": runtime["llm_provider"],
|
"llm_provider": runtime["llm_provider"],
|
||||||
"llm_model": runtime["llm_model"],
|
"llm_model": runtime["llm_model"],
|
||||||
|
"api_key": runtime["api_key"],
|
||||||
"api_base": runtime["api_base"],
|
"api_base": runtime["api_base"],
|
||||||
"temperature": runtime["temperature"],
|
"temperature": runtime["temperature"],
|
||||||
"top_p": runtime["top_p"],
|
"top_p": runtime["top_p"],
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,6 @@ from core.settings import (
|
||||||
DEFAULT_AUTH_TOKEN_MAX_ACTIVE,
|
DEFAULT_AUTH_TOKEN_MAX_ACTIVE,
|
||||||
DEFAULT_AUTH_TOKEN_TTL_HOURS,
|
DEFAULT_AUTH_TOKEN_TTL_HOURS,
|
||||||
DEFAULT_CHAT_PULL_PAGE_SIZE,
|
DEFAULT_CHAT_PULL_PAGE_SIZE,
|
||||||
DEFAULT_COMMAND_AUTO_UNLOCK_SECONDS,
|
|
||||||
DEFAULT_PAGE_SIZE,
|
DEFAULT_PAGE_SIZE,
|
||||||
DEFAULT_UPLOAD_MAX_MB,
|
DEFAULT_UPLOAD_MAX_MB,
|
||||||
DEFAULT_WORKSPACE_DOWNLOAD_EXTENSIONS,
|
DEFAULT_WORKSPACE_DOWNLOAD_EXTENSIONS,
|
||||||
|
|
@ -24,7 +23,6 @@ ACTIVITY_EVENT_RETENTION_SETTING_KEY = "activity_event_retention_days"
|
||||||
SETTING_KEYS = (
|
SETTING_KEYS = (
|
||||||
"page_size",
|
"page_size",
|
||||||
"chat_pull_page_size",
|
"chat_pull_page_size",
|
||||||
"command_auto_unlock_seconds",
|
|
||||||
"auth_token_ttl_hours",
|
"auth_token_ttl_hours",
|
||||||
"auth_token_max_active",
|
"auth_token_max_active",
|
||||||
"upload_max_mb",
|
"upload_max_mb",
|
||||||
|
|
@ -52,15 +50,6 @@ SYSTEM_SETTING_DEFINITIONS: Dict[str, Dict[str, Any]] = {
|
||||||
"is_public": True,
|
"is_public": True,
|
||||||
"sort_order": 8,
|
"sort_order": 8,
|
||||||
},
|
},
|
||||||
"command_auto_unlock_seconds": {
|
|
||||||
"name": "发送按钮自动恢复秒数",
|
|
||||||
"category": "chat",
|
|
||||||
"description": "对话发送后按钮保持停止态的最长秒数,超时后自动恢复为可发送状态。",
|
|
||||||
"value_type": "integer",
|
|
||||||
"value": DEFAULT_COMMAND_AUTO_UNLOCK_SECONDS,
|
|
||||||
"is_public": True,
|
|
||||||
"sort_order": 9,
|
|
||||||
},
|
|
||||||
"auth_token_ttl_hours": {
|
"auth_token_ttl_hours": {
|
||||||
"name": "认证 Token 过期小时数",
|
"name": "认证 Token 过期小时数",
|
||||||
"category": "auth",
|
"category": "auth",
|
||||||
|
|
|
||||||
|
|
@ -50,7 +50,6 @@ def get_platform_settings(session: Session) -> PlatformSettingsPayload:
|
||||||
{
|
{
|
||||||
"page_size": max(1, min(100, int(data["page_size"]))),
|
"page_size": max(1, min(100, int(data["page_size"]))),
|
||||||
"chat_pull_page_size": max(10, min(500, int(data["chat_pull_page_size"]))),
|
"chat_pull_page_size": max(10, min(500, int(data["chat_pull_page_size"]))),
|
||||||
"command_auto_unlock_seconds": max(1, min(600, int(data["command_auto_unlock_seconds"]))),
|
|
||||||
"auth_token_ttl_hours": max(1, min(720, int(data["auth_token_ttl_hours"]))),
|
"auth_token_ttl_hours": max(1, min(720, int(data["auth_token_ttl_hours"]))),
|
||||||
"auth_token_max_active": max(1, min(20, int(data["auth_token_max_active"]))),
|
"auth_token_max_active": max(1, min(20, int(data["auth_token_max_active"]))),
|
||||||
"upload_max_mb": int(data["upload_max_mb"]),
|
"upload_max_mb": int(data["upload_max_mb"]),
|
||||||
|
|
@ -70,7 +69,6 @@ def save_platform_settings(session: Session, payload: PlatformSettingsPayload) -
|
||||||
normalized = PlatformSettingsPayload(
|
normalized = PlatformSettingsPayload(
|
||||||
page_size=max(1, min(100, int(payload.page_size))),
|
page_size=max(1, min(100, int(payload.page_size))),
|
||||||
chat_pull_page_size=max(10, min(500, int(payload.chat_pull_page_size))),
|
chat_pull_page_size=max(10, min(500, int(payload.chat_pull_page_size))),
|
||||||
command_auto_unlock_seconds=max(1, min(600, int(payload.command_auto_unlock_seconds))),
|
|
||||||
auth_token_ttl_hours=max(1, min(720, int(payload.auth_token_ttl_hours))),
|
auth_token_ttl_hours=max(1, min(720, int(payload.auth_token_ttl_hours))),
|
||||||
auth_token_max_active=max(1, min(20, int(payload.auth_token_max_active))),
|
auth_token_max_active=max(1, min(20, int(payload.auth_token_max_active))),
|
||||||
upload_max_mb=payload.upload_max_mb,
|
upload_max_mb=payload.upload_max_mb,
|
||||||
|
|
|
||||||
|
|
@ -15,9 +15,23 @@ from services.platform_settings_core import (
|
||||||
)
|
)
|
||||||
|
|
||||||
REQUIRED_SYSTEM_SETTING_KEYS = tuple(SYSTEM_SETTING_DEFINITIONS.keys())
|
REQUIRED_SYSTEM_SETTING_KEYS = tuple(SYSTEM_SETTING_DEFINITIONS.keys())
|
||||||
|
DEPRECATED_SYSTEM_SETTING_KEYS = ("command_auto_unlock_seconds",)
|
||||||
|
|
||||||
|
|
||||||
|
def _prune_deprecated_system_settings(session: Session) -> None:
|
||||||
|
removed = False
|
||||||
|
for key in DEPRECATED_SYSTEM_SETTING_KEYS:
|
||||||
|
row = session.get(PlatformSetting, key)
|
||||||
|
if row is None:
|
||||||
|
continue
|
||||||
|
session.delete(row)
|
||||||
|
removed = True
|
||||||
|
if removed:
|
||||||
|
session.commit()
|
||||||
|
|
||||||
|
|
||||||
def validate_required_system_settings(session: Session) -> None:
|
def validate_required_system_settings(session: Session) -> None:
|
||||||
|
_prune_deprecated_system_settings(session)
|
||||||
stmt = select(PlatformSetting.key).where(PlatformSetting.key.in_(REQUIRED_SYSTEM_SETTING_KEYS))
|
stmt = select(PlatformSetting.key).where(PlatformSetting.key.in_(REQUIRED_SYSTEM_SETTING_KEYS))
|
||||||
present = {
|
present = {
|
||||||
str(key or "").strip()
|
str(key or "").strip()
|
||||||
|
|
@ -53,6 +67,8 @@ def list_system_settings(session: Session, search: str = "") -> List[Dict[str, A
|
||||||
|
|
||||||
def create_or_update_system_setting(session: Session, payload: SystemSettingPayload) -> Dict[str, Any]:
|
def create_or_update_system_setting(session: Session, payload: SystemSettingPayload) -> Dict[str, Any]:
|
||||||
normalized_key = _normalize_setting_key(payload.key)
|
normalized_key = _normalize_setting_key(payload.key)
|
||||||
|
if normalized_key in DEPRECATED_SYSTEM_SETTING_KEYS:
|
||||||
|
raise ValueError("Setting key has been removed")
|
||||||
definition = SYSTEM_SETTING_DEFINITIONS.get(normalized_key, {})
|
definition = SYSTEM_SETTING_DEFINITIONS.get(normalized_key, {})
|
||||||
row = _upsert_setting_row(
|
row = _upsert_setting_row(
|
||||||
session,
|
session,
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ export const dashboardEn = {
|
||||||
feedbackSaveFail: 'Failed to save feedback.',
|
feedbackSaveFail: 'Failed to save feedback.',
|
||||||
feedbackMessagePending: 'Message is not synced yet. Please retry in a moment.',
|
feedbackMessagePending: 'Message is not synced yet. Please retry in a moment.',
|
||||||
sendFailMsg: (msg: string) => `Command delivery failed: ${msg}`,
|
sendFailMsg: (msg: string) => `Command delivery failed: ${msg}`,
|
||||||
providerRequired: 'Set provider/model/new API key before testing.',
|
providerRequired: 'Set provider/model/API key before testing.',
|
||||||
connOk: (preview: string) => (preview ? `Connection passed, models: ${preview}` : 'Connection passed'),
|
connOk: (preview: string) => (preview ? `Connection passed, models: ${preview}` : 'Connection passed'),
|
||||||
connFail: (msg: string) => `Failed: ${msg}`,
|
connFail: (msg: string) => `Failed: ${msg}`,
|
||||||
configUpdated: 'Configuration updated (effective after bot restart).',
|
configUpdated: 'Configuration updated (effective after bot restart).',
|
||||||
|
|
@ -265,8 +265,8 @@ export const dashboardEn = {
|
||||||
baseImageReadonly: 'Base Image',
|
baseImageReadonly: 'Base Image',
|
||||||
modelName: 'Model Name',
|
modelName: 'Model Name',
|
||||||
modelNamePlaceholder: 'e.g. qwen-plus',
|
modelNamePlaceholder: 'e.g. qwen-plus',
|
||||||
newApiKey: 'New API Key (optional)',
|
newApiKey: 'API Key',
|
||||||
newApiKeyPlaceholder: 'Only updated when filled',
|
newApiKeyPlaceholder: 'Enter API Key',
|
||||||
testing: 'Testing...',
|
testing: 'Testing...',
|
||||||
testModelConnection: 'Test model connection',
|
testModelConnection: 'Test model connection',
|
||||||
cancel: 'Cancel',
|
cancel: 'Cancel',
|
||||||
|
|
|
||||||
|
|
@ -69,7 +69,7 @@ export const dashboardZhCn = {
|
||||||
feedbackSaveFail: '反馈保存失败。',
|
feedbackSaveFail: '反馈保存失败。',
|
||||||
feedbackMessagePending: '消息尚未同步,暂不可反馈。',
|
feedbackMessagePending: '消息尚未同步,暂不可反馈。',
|
||||||
sendFailMsg: (msg: string) => `指令发送失败:${msg}`,
|
sendFailMsg: (msg: string) => `指令发送失败:${msg}`,
|
||||||
providerRequired: '请填写 Provider、模型和新 API Key 后再测试。',
|
providerRequired: '请填写 Provider、模型和 API Key 后再测试。',
|
||||||
connOk: (preview: string) => (preview ? `连接成功,模型: ${preview}` : '连接成功'),
|
connOk: (preview: string) => (preview ? `连接成功,模型: ${preview}` : '连接成功'),
|
||||||
connFail: (msg: string) => `连接失败: ${msg}`,
|
connFail: (msg: string) => `连接失败: ${msg}`,
|
||||||
configUpdated: '配置已更新(重启 Bot 后生效)。',
|
configUpdated: '配置已更新(重启 Bot 后生效)。',
|
||||||
|
|
@ -265,8 +265,8 @@ export const dashboardZhCn = {
|
||||||
baseImageReadonly: '基础镜像',
|
baseImageReadonly: '基础镜像',
|
||||||
modelName: '模型名称',
|
modelName: '模型名称',
|
||||||
modelNamePlaceholder: '如 qwen-plus',
|
modelNamePlaceholder: '如 qwen-plus',
|
||||||
newApiKey: '新的 API Key(留空不更新)',
|
newApiKey: 'API Key',
|
||||||
newApiKeyPlaceholder: '输入新 Key 才会更新',
|
newApiKeyPlaceholder: '请输入 API Key',
|
||||||
testing: '测试中...',
|
testing: '测试中...',
|
||||||
testModelConnection: '测试模型连接',
|
testModelConnection: '测试模型连接',
|
||||||
cancel: '取消',
|
cancel: '取消',
|
||||||
|
|
|
||||||
|
|
@ -44,7 +44,6 @@ export function useBotDashboardModule({
|
||||||
const fileNotPreviewableLabel = locale === 'zh' ? '当前文件类型不支持预览' : 'This file type is not previewable';
|
const fileNotPreviewableLabel = locale === 'zh' ? '当前文件类型不支持预览' : 'This file type is not previewable';
|
||||||
const [botListPageSize, setBotListPageSize] = useState(10);
|
const [botListPageSize, setBotListPageSize] = useState(10);
|
||||||
const [chatPullPageSize, setChatPullPageSize] = useState(60);
|
const [chatPullPageSize, setChatPullPageSize] = useState(60);
|
||||||
const [commandAutoUnlockSeconds, setCommandAutoUnlockSeconds] = useState(10);
|
|
||||||
const isZh = locale === 'zh';
|
const isZh = locale === 'zh';
|
||||||
const botSearchInputName = `nbot-search-${useId().replace(/:/g, '-')}`;
|
const botSearchInputName = `nbot-search-${useId().replace(/:/g, '-')}`;
|
||||||
const workspaceSearchInputName = `nbot-workspace-search-${useId().replace(/:/g, '-')}`;
|
const workspaceSearchInputName = `nbot-workspace-search-${useId().replace(/:/g, '-')}`;
|
||||||
|
|
@ -63,7 +62,6 @@ export function useBotDashboardModule({
|
||||||
notify,
|
notify,
|
||||||
setBotListPageSize,
|
setBotListPageSize,
|
||||||
setChatPullPageSize,
|
setChatPullPageSize,
|
||||||
setCommandAutoUnlockSeconds,
|
|
||||||
});
|
});
|
||||||
const {
|
const {
|
||||||
botListMenuOpen,
|
botListMenuOpen,
|
||||||
|
|
@ -435,7 +433,6 @@ export function useBotDashboardModule({
|
||||||
filePickerRef,
|
filePickerRef,
|
||||||
interruptExecution,
|
interruptExecution,
|
||||||
isInterrupting,
|
isInterrupting,
|
||||||
isSendingBlocked,
|
|
||||||
jumpConversationToDate,
|
jumpConversationToDate,
|
||||||
loadInitialChatPage,
|
loadInitialChatPage,
|
||||||
onChatScroll,
|
onChatScroll,
|
||||||
|
|
@ -466,7 +463,6 @@ export function useBotDashboardModule({
|
||||||
canChat,
|
canChat,
|
||||||
isTaskRunningExternally: isBotThinking,
|
isTaskRunningExternally: isBotThinking,
|
||||||
chatPullPageSize,
|
chatPullPageSize,
|
||||||
commandAutoUnlockSeconds,
|
|
||||||
pendingAttachments,
|
pendingAttachments,
|
||||||
setPendingAttachments,
|
setPendingAttachments,
|
||||||
isUploadingAttachments,
|
isUploadingAttachments,
|
||||||
|
|
@ -500,7 +496,6 @@ export function useBotDashboardModule({
|
||||||
isChatEnabled,
|
isChatEnabled,
|
||||||
} = useDashboardInteractionState({
|
} = useDashboardInteractionState({
|
||||||
canChat,
|
canChat,
|
||||||
isSendingBlocked,
|
|
||||||
isVoiceRecording,
|
isVoiceRecording,
|
||||||
isVoiceTranscribing,
|
isVoiceTranscribing,
|
||||||
selectedBot,
|
selectedBot,
|
||||||
|
|
|
||||||
|
|
@ -97,7 +97,7 @@ export function useDashboardBotEditor({
|
||||||
llm_provider: provider,
|
llm_provider: provider,
|
||||||
llm_model: bot.llm_model || '',
|
llm_model: bot.llm_model || '',
|
||||||
image_tag: bot.image_tag || '',
|
image_tag: bot.image_tag || '',
|
||||||
api_key: '',
|
api_key: bot.api_key || '',
|
||||||
api_base: bot.api_base || '',
|
api_base: bot.api_base || '',
|
||||||
temperature: clampTemperature(bot.temperature ?? 0.2),
|
temperature: clampTemperature(bot.temperature ?? 0.2),
|
||||||
top_p: bot.top_p ?? 1,
|
top_p: bot.top_p ?? 1,
|
||||||
|
|
@ -193,10 +193,14 @@ export function useDashboardBotEditor({
|
||||||
notify(t.providerRequired, { tone: 'warning' });
|
notify(t.providerRequired, { tone: 'warning' });
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
const targetBotId = String(selectedBot?.id || selectedBotId || '').trim();
|
||||||
|
const endpoint = targetBotId
|
||||||
|
? `${APP_ENDPOINTS.apiBase}/bots/${encodeURIComponent(targetBotId)}/providers/test`
|
||||||
|
: `${APP_ENDPOINTS.apiBase}/providers/test`;
|
||||||
setIsTestingProvider(true);
|
setIsTestingProvider(true);
|
||||||
setProviderTestResult('');
|
setProviderTestResult('');
|
||||||
try {
|
try {
|
||||||
const res = await axios.post(`${APP_ENDPOINTS.apiBase}/providers/test`, {
|
const res = await axios.post(endpoint, {
|
||||||
provider: editForm.llm_provider,
|
provider: editForm.llm_provider,
|
||||||
model: editForm.llm_model,
|
model: editForm.llm_model,
|
||||||
api_key: editForm.api_key.trim(),
|
api_key: editForm.api_key.trim(),
|
||||||
|
|
@ -214,7 +218,7 @@ export function useDashboardBotEditor({
|
||||||
} finally {
|
} finally {
|
||||||
setIsTestingProvider(false);
|
setIsTestingProvider(false);
|
||||||
}
|
}
|
||||||
}, [editForm.api_base, editForm.api_key, editForm.llm_model, editForm.llm_provider, notify, t]);
|
}, [editForm.api_base, editForm.api_key, editForm.llm_model, editForm.llm_provider, notify, selectedBot?.id, selectedBotId, t]);
|
||||||
|
|
||||||
const saveBot = useCallback(async (mode: 'params' | 'agent' | 'base') => {
|
const saveBot = useCallback(async (mode: 'params' | 'agent' | 'base') => {
|
||||||
const targetBotId = String(selectedBot?.id || selectedBotId || '').trim();
|
const targetBotId = String(selectedBot?.id || selectedBotId || '').trim();
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
import { useCallback, useEffect, useState, type Dispatch, type SetStateAction } from 'react';
|
import { useCallback, useState, type Dispatch, type SetStateAction } from 'react';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
|
|
||||||
import { APP_ENDPOINTS } from '../../../config/env';
|
import { APP_ENDPOINTS } from '../../../config/env';
|
||||||
|
|
@ -42,7 +42,6 @@ interface UseDashboardChatCommandDispatchOptions {
|
||||||
selectedBot?: { id: string } | null;
|
selectedBot?: { id: string } | null;
|
||||||
canChat: boolean;
|
canChat: boolean;
|
||||||
isTaskRunningExternally: boolean;
|
isTaskRunningExternally: boolean;
|
||||||
commandAutoUnlockSeconds: number;
|
|
||||||
command: string;
|
command: string;
|
||||||
pendingAttachments: string[];
|
pendingAttachments: string[];
|
||||||
quotedReply: QuotedReply | null;
|
quotedReply: QuotedReply | null;
|
||||||
|
|
@ -62,7 +61,6 @@ export function useDashboardChatCommandDispatch({
|
||||||
selectedBot,
|
selectedBot,
|
||||||
canChat,
|
canChat,
|
||||||
isTaskRunningExternally,
|
isTaskRunningExternally,
|
||||||
commandAutoUnlockSeconds,
|
|
||||||
command,
|
command,
|
||||||
pendingAttachments,
|
pendingAttachments,
|
||||||
quotedReply,
|
quotedReply,
|
||||||
|
|
@ -78,40 +76,15 @@ export function useDashboardChatCommandDispatch({
|
||||||
t,
|
t,
|
||||||
}: UseDashboardChatCommandDispatchOptions) {
|
}: UseDashboardChatCommandDispatchOptions) {
|
||||||
const [sendingByBot, setSendingByBot] = useState<Record<string, number>>({});
|
const [sendingByBot, setSendingByBot] = useState<Record<string, number>>({});
|
||||||
const [commandAutoUnlockDeadlineByBot, setCommandAutoUnlockDeadlineByBot] = useState<Record<string, number>>({});
|
|
||||||
const [interruptingByBot, setInterruptingByBot] = useState<Record<string, boolean>>({});
|
const [interruptingByBot, setInterruptingByBot] = useState<Record<string, boolean>>({});
|
||||||
const [controlCommandByBot, setControlCommandByBot] = useState<Record<string, string>>({});
|
const [controlCommandByBot, setControlCommandByBot] = useState<Record<string, string>>({});
|
||||||
|
|
||||||
const selectedBotSendingCount = selectedBot ? Number(sendingByBot[selectedBot.id] || 0) : 0;
|
const selectedBotSendingCount = selectedBot ? Number(sendingByBot[selectedBot.id] || 0) : 0;
|
||||||
const selectedBotAutoUnlockDeadline = selectedBot ? Number(commandAutoUnlockDeadlineByBot[selectedBot.id] || 0) : 0;
|
|
||||||
const activeControlCommand = selectedBot ? controlCommandByBot[selectedBot.id] || '' : '';
|
const activeControlCommand = selectedBot ? controlCommandByBot[selectedBot.id] || '' : '';
|
||||||
const isSending = selectedBotSendingCount > 0;
|
const isSending = selectedBotSendingCount > 0;
|
||||||
const isTaskRunning = Boolean(selectedBot && (isSending || isTaskRunningExternally));
|
const isTaskRunning = Boolean(selectedBot && (isSending || isTaskRunningExternally));
|
||||||
const isCommandAutoUnlockWindowActive = selectedBotAutoUnlockDeadline > Date.now();
|
|
||||||
const isSendingBlocked = isSending && isCommandAutoUnlockWindowActive;
|
|
||||||
const isInterrupting = Boolean(selectedBot && interruptingByBot[selectedBot.id]);
|
const isInterrupting = Boolean(selectedBot && interruptingByBot[selectedBot.id]);
|
||||||
|
|
||||||
useEffect(() => {
|
|
||||||
if (!selectedBot?.id || selectedBotAutoUnlockDeadline <= 0) return;
|
|
||||||
const remaining = selectedBotAutoUnlockDeadline - Date.now();
|
|
||||||
if (remaining <= 0) {
|
|
||||||
setCommandAutoUnlockDeadlineByBot((prev) => {
|
|
||||||
const next = { ...prev };
|
|
||||||
delete next[selectedBot.id];
|
|
||||||
return next;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const timer = window.setTimeout(() => {
|
|
||||||
setCommandAutoUnlockDeadlineByBot((prev) => {
|
|
||||||
const next = { ...prev };
|
|
||||||
delete next[selectedBot.id];
|
|
||||||
return next;
|
|
||||||
});
|
|
||||||
}, remaining + 20);
|
|
||||||
return () => window.clearTimeout(timer);
|
|
||||||
}, [selectedBot?.id, selectedBotAutoUnlockDeadline]);
|
|
||||||
|
|
||||||
const submitChatPayload = useCallback(async ({
|
const submitChatPayload = useCallback(async ({
|
||||||
commandRaw,
|
commandRaw,
|
||||||
attachmentsRaw,
|
attachmentsRaw,
|
||||||
|
|
@ -137,10 +110,6 @@ export function useDashboardChatCommandDispatch({
|
||||||
try {
|
try {
|
||||||
requestAnimationFrame(() => scrollConversationToBottom('auto'));
|
requestAnimationFrame(() => scrollConversationToBottom('auto'));
|
||||||
setSendingByBot((prev) => ({ ...prev, [selectedBot.id]: Number(prev[selectedBot.id] || 0) + 1 }));
|
setSendingByBot((prev) => ({ ...prev, [selectedBot.id]: Number(prev[selectedBot.id] || 0) + 1 }));
|
||||||
setCommandAutoUnlockDeadlineByBot((prev) => ({
|
|
||||||
...prev,
|
|
||||||
[selectedBot.id]: Date.now() + (commandAutoUnlockSeconds * 1000),
|
|
||||||
}));
|
|
||||||
const res = await axios.post<CommandResponse>(
|
const res = await axios.post<CommandResponse>(
|
||||||
`${APP_ENDPOINTS.apiBase}/bots/${selectedBot.id}/command`,
|
`${APP_ENDPOINTS.apiBase}/bots/${selectedBot.id}/command`,
|
||||||
{ command: payloadText, attachments },
|
{ command: payloadText, attachments },
|
||||||
|
|
@ -168,11 +137,6 @@ export function useDashboardChatCommandDispatch({
|
||||||
return true;
|
return true;
|
||||||
} catch (error: unknown) {
|
} catch (error: unknown) {
|
||||||
const msg = resolveApiErrorMessage(error, t.sendFail);
|
const msg = resolveApiErrorMessage(error, t.sendFail);
|
||||||
setCommandAutoUnlockDeadlineByBot((prev) => {
|
|
||||||
const next = { ...prev };
|
|
||||||
delete next[selectedBot.id];
|
|
||||||
return next;
|
|
||||||
});
|
|
||||||
addBotMessage(selectedBot.id, {
|
addBotMessage(selectedBot.id, {
|
||||||
role: 'assistant',
|
role: 'assistant',
|
||||||
text: t.sendFailMsg(msg),
|
text: t.sendFailMsg(msg),
|
||||||
|
|
@ -196,7 +160,6 @@ export function useDashboardChatCommandDispatch({
|
||||||
}, [
|
}, [
|
||||||
addBotMessage,
|
addBotMessage,
|
||||||
canChat,
|
canChat,
|
||||||
commandAutoUnlockSeconds,
|
|
||||||
completeLeadingStagedSubmission,
|
completeLeadingStagedSubmission,
|
||||||
notify,
|
notify,
|
||||||
scrollConversationToBottom,
|
scrollConversationToBottom,
|
||||||
|
|
@ -302,7 +265,6 @@ export function useDashboardChatCommandDispatch({
|
||||||
interruptExecution,
|
interruptExecution,
|
||||||
isInterrupting,
|
isInterrupting,
|
||||||
isSending,
|
isSending,
|
||||||
isSendingBlocked,
|
|
||||||
isTaskRunning,
|
isTaskRunning,
|
||||||
sendControlCommand,
|
sendControlCommand,
|
||||||
sendCurrentDraft,
|
sendCurrentDraft,
|
||||||
|
|
|
||||||
|
|
@ -16,7 +16,6 @@ interface UseDashboardChatComposerOptions {
|
||||||
selectedBot?: { id: string } | null;
|
selectedBot?: { id: string } | null;
|
||||||
canChat: boolean;
|
canChat: boolean;
|
||||||
isTaskRunningExternally: boolean;
|
isTaskRunningExternally: boolean;
|
||||||
commandAutoUnlockSeconds: number;
|
|
||||||
pendingAttachments: string[];
|
pendingAttachments: string[];
|
||||||
setPendingAttachments: Dispatch<SetStateAction<string[]>>;
|
setPendingAttachments: Dispatch<SetStateAction<string[]>>;
|
||||||
isUploadingAttachments: boolean;
|
isUploadingAttachments: boolean;
|
||||||
|
|
@ -41,7 +40,6 @@ export function useDashboardChatComposer({
|
||||||
selectedBot,
|
selectedBot,
|
||||||
canChat,
|
canChat,
|
||||||
isTaskRunningExternally,
|
isTaskRunningExternally,
|
||||||
commandAutoUnlockSeconds,
|
|
||||||
pendingAttachments,
|
pendingAttachments,
|
||||||
setPendingAttachments,
|
setPendingAttachments,
|
||||||
isUploadingAttachments,
|
isUploadingAttachments,
|
||||||
|
|
@ -111,7 +109,6 @@ export function useDashboardChatComposer({
|
||||||
interruptExecution,
|
interruptExecution,
|
||||||
isInterrupting,
|
isInterrupting,
|
||||||
isSending,
|
isSending,
|
||||||
isSendingBlocked,
|
|
||||||
isTaskRunning,
|
isTaskRunning,
|
||||||
sendControlCommand,
|
sendControlCommand,
|
||||||
sendCurrentDraft,
|
sendCurrentDraft,
|
||||||
|
|
@ -120,7 +117,6 @@ export function useDashboardChatComposer({
|
||||||
selectedBot,
|
selectedBot,
|
||||||
canChat,
|
canChat,
|
||||||
isTaskRunningExternally,
|
isTaskRunningExternally,
|
||||||
commandAutoUnlockSeconds,
|
|
||||||
command,
|
command,
|
||||||
pendingAttachments,
|
pendingAttachments,
|
||||||
quotedReply,
|
quotedReply,
|
||||||
|
|
@ -281,7 +277,6 @@ export function useDashboardChatComposer({
|
||||||
interruptExecution,
|
interruptExecution,
|
||||||
isInterrupting,
|
isInterrupting,
|
||||||
isSending,
|
isSending,
|
||||||
isSendingBlocked,
|
|
||||||
onComposerKeyDown,
|
onComposerKeyDown,
|
||||||
quoteAssistantReply,
|
quoteAssistantReply,
|
||||||
quotedReply,
|
quotedReply,
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,6 @@ interface UseDashboardConversationOptions {
|
||||||
canChat: boolean;
|
canChat: boolean;
|
||||||
isTaskRunningExternally: boolean;
|
isTaskRunningExternally: boolean;
|
||||||
chatPullPageSize: number;
|
chatPullPageSize: number;
|
||||||
commandAutoUnlockSeconds: number;
|
|
||||||
pendingAttachments: string[];
|
pendingAttachments: string[];
|
||||||
setPendingAttachments: Dispatch<SetStateAction<string[]>>;
|
setPendingAttachments: Dispatch<SetStateAction<string[]>>;
|
||||||
isUploadingAttachments: boolean;
|
isUploadingAttachments: boolean;
|
||||||
|
|
@ -50,7 +49,6 @@ export function useDashboardConversation(options: UseDashboardConversationOption
|
||||||
selectedBot: options.selectedBot,
|
selectedBot: options.selectedBot,
|
||||||
canChat: options.canChat,
|
canChat: options.canChat,
|
||||||
isTaskRunningExternally: options.isTaskRunningExternally,
|
isTaskRunningExternally: options.isTaskRunningExternally,
|
||||||
commandAutoUnlockSeconds: options.commandAutoUnlockSeconds,
|
|
||||||
pendingAttachments: options.pendingAttachments,
|
pendingAttachments: options.pendingAttachments,
|
||||||
setPendingAttachments: options.setPendingAttachments,
|
setPendingAttachments: options.setPendingAttachments,
|
||||||
isUploadingAttachments: options.isUploadingAttachments,
|
isUploadingAttachments: options.isUploadingAttachments,
|
||||||
|
|
|
||||||
|
|
@ -30,7 +30,6 @@ interface UseDashboardBaseStateOptions {
|
||||||
|
|
||||||
interface UseDashboardInteractionStateOptions {
|
interface UseDashboardInteractionStateOptions {
|
||||||
canChat: boolean;
|
canChat: boolean;
|
||||||
isSendingBlocked?: boolean;
|
|
||||||
isVoiceRecording?: boolean;
|
isVoiceRecording?: boolean;
|
||||||
isVoiceTranscribing?: boolean;
|
isVoiceTranscribing?: boolean;
|
||||||
selectedBot?: BotState;
|
selectedBot?: BotState;
|
||||||
|
|
@ -227,12 +226,11 @@ export function useDashboardBaseState({
|
||||||
|
|
||||||
export function useDashboardInteractionState({
|
export function useDashboardInteractionState({
|
||||||
canChat,
|
canChat,
|
||||||
isSendingBlocked = false,
|
|
||||||
isVoiceRecording = false,
|
isVoiceRecording = false,
|
||||||
isVoiceTranscribing = false,
|
isVoiceTranscribing = false,
|
||||||
selectedBot,
|
selectedBot,
|
||||||
}: UseDashboardInteractionStateOptions) {
|
}: UseDashboardInteractionStateOptions) {
|
||||||
const isChatEnabled = Boolean(canChat && !isSendingBlocked);
|
const isChatEnabled = Boolean(canChat);
|
||||||
const canSendControlCommand = Boolean(
|
const canSendControlCommand = Boolean(
|
||||||
selectedBot && canChat && !isVoiceRecording && !isVoiceTranscribing,
|
selectedBot && canChat && !isVoiceRecording && !isVoiceTranscribing,
|
||||||
);
|
);
|
||||||
|
|
|
||||||
|
|
@ -71,15 +71,19 @@ export function useDashboardRuntimeControl({
|
||||||
);
|
);
|
||||||
|
|
||||||
const loadImageOptions = useCallback(async () => {
|
const loadImageOptions = useCallback(async () => {
|
||||||
|
const targetBotId = String(selectedBotId || forcedBotId || '').trim();
|
||||||
|
const endpoint = targetBotId
|
||||||
|
? `${APP_ENDPOINTS.apiBase}/bots/${encodeURIComponent(targetBotId)}/images`
|
||||||
|
: `${APP_ENDPOINTS.apiBase}/images`;
|
||||||
const [imagesRes] = await Promise.allSettled([
|
const [imagesRes] = await Promise.allSettled([
|
||||||
axios.get<NanobotImage[]>(`${APP_ENDPOINTS.apiBase}/images`),
|
axios.get<NanobotImage[]>(endpoint),
|
||||||
]);
|
]);
|
||||||
if (imagesRes.status === 'fulfilled') {
|
if (imagesRes.status === 'fulfilled') {
|
||||||
setAvailableImages(Array.isArray(imagesRes.value.data) ? imagesRes.value.data : []);
|
setAvailableImages(Array.isArray(imagesRes.value.data) ? imagesRes.value.data : []);
|
||||||
} else {
|
} else {
|
||||||
setAvailableImages([]);
|
setAvailableImages([]);
|
||||||
}
|
}
|
||||||
}, []);
|
}, [forcedBotId, selectedBotId]);
|
||||||
|
|
||||||
const refresh = useCallback(async () => {
|
const refresh = useCallback(async () => {
|
||||||
const forced = String(forcedBotId || '').trim();
|
const forced = String(forcedBotId || '').trim();
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,6 @@ interface UseDashboardSystemDefaultsOptions {
|
||||||
notify: (message: string, options?: { tone?: 'error' | 'success' | 'warning' | 'info' }) => void;
|
notify: (message: string, options?: { tone?: 'error' | 'success' | 'warning' | 'info' }) => void;
|
||||||
setBotListPageSize: Dispatch<SetStateAction<number>>;
|
setBotListPageSize: Dispatch<SetStateAction<number>>;
|
||||||
setChatPullPageSize?: Dispatch<SetStateAction<number>>;
|
setChatPullPageSize?: Dispatch<SetStateAction<number>>;
|
||||||
setCommandAutoUnlockSeconds?: Dispatch<SetStateAction<number>>;
|
|
||||||
setVoiceCountdown?: Dispatch<SetStateAction<number>>;
|
setVoiceCountdown?: Dispatch<SetStateAction<number>>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -34,18 +33,11 @@ function resolveChatPullPageSize(raw: unknown) {
|
||||||
return Math.max(10, Math.min(500, Math.floor(configured)));
|
return Math.max(10, Math.min(500, Math.floor(configured)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolveCommandAutoUnlockSeconds(raw: unknown) {
|
|
||||||
const configured = Number(raw);
|
|
||||||
if (!Number.isFinite(configured) || configured <= 0) return 10;
|
|
||||||
return Math.max(1, Math.min(600, Math.floor(configured)));
|
|
||||||
}
|
|
||||||
|
|
||||||
export function useDashboardSystemDefaults({
|
export function useDashboardSystemDefaults({
|
||||||
isZh,
|
isZh,
|
||||||
notify,
|
notify,
|
||||||
setBotListPageSize,
|
setBotListPageSize,
|
||||||
setChatPullPageSize,
|
setChatPullPageSize,
|
||||||
setCommandAutoUnlockSeconds,
|
|
||||||
setVoiceCountdown,
|
setVoiceCountdown,
|
||||||
}: UseDashboardSystemDefaultsOptions) {
|
}: UseDashboardSystemDefaultsOptions) {
|
||||||
const [botListPageSizeReady, setBotListPageSizeReady] = useState(false);
|
const [botListPageSizeReady, setBotListPageSizeReady] = useState(false);
|
||||||
|
|
@ -66,7 +58,6 @@ export function useDashboardSystemDefaults({
|
||||||
|
|
||||||
setBotListPageSize(normalizePlatformPageSize(data?.chat?.page_size, 10));
|
setBotListPageSize(normalizePlatformPageSize(data?.chat?.page_size, 10));
|
||||||
setChatPullPageSize?.(resolveChatPullPageSize(data?.chat?.pull_page_size));
|
setChatPullPageSize?.(resolveChatPullPageSize(data?.chat?.pull_page_size));
|
||||||
setCommandAutoUnlockSeconds?.(resolveCommandAutoUnlockSeconds(data?.chat?.command_auto_unlock_seconds));
|
|
||||||
setAllowedAttachmentExtensions(
|
setAllowedAttachmentExtensions(
|
||||||
parseAllowedAttachmentExtensions(data?.workspace?.allowed_attachment_extensions),
|
parseAllowedAttachmentExtensions(data?.workspace?.allowed_attachment_extensions),
|
||||||
);
|
);
|
||||||
|
|
@ -85,7 +76,7 @@ export function useDashboardSystemDefaults({
|
||||||
setVoiceMaxSeconds(nextVoiceMaxSeconds);
|
setVoiceMaxSeconds(nextVoiceMaxSeconds);
|
||||||
setVoiceCountdown?.(nextVoiceMaxSeconds);
|
setVoiceCountdown?.(nextVoiceMaxSeconds);
|
||||||
}
|
}
|
||||||
}, [setBotListPageSize, setChatPullPageSize, setCommandAutoUnlockSeconds, setVoiceCountdown]);
|
}, [setBotListPageSize, setChatPullPageSize, setVoiceCountdown]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
let alive = true;
|
let alive = true;
|
||||||
|
|
|
||||||
|
|
@ -280,7 +280,6 @@ export interface SystemDefaultsResponse {
|
||||||
chat?: {
|
chat?: {
|
||||||
page_size?: number;
|
page_size?: number;
|
||||||
pull_page_size?: number;
|
pull_page_size?: number;
|
||||||
command_auto_unlock_seconds?: number;
|
|
||||||
};
|
};
|
||||||
topic_presets?: unknown;
|
topic_presets?: unknown;
|
||||||
speech?: {
|
speech?: {
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
export interface PlatformSettings {
|
export interface PlatformSettings {
|
||||||
page_size: number;
|
page_size: number;
|
||||||
chat_pull_page_size: number;
|
chat_pull_page_size: number;
|
||||||
command_auto_unlock_seconds: number;
|
|
||||||
auth_token_ttl_hours: number;
|
auth_token_ttl_hours: number;
|
||||||
auth_token_max_active: number;
|
auth_token_max_active: number;
|
||||||
upload_max_mb: number;
|
upload_max_mb: number;
|
||||||
|
|
|
||||||
|
|
@ -71,6 +71,7 @@ export const useAppStore = create<AppStore>((set) => ({
|
||||||
image_tag: preferDefined(bot.image_tag, prev?.image_tag),
|
image_tag: preferDefined(bot.image_tag, prev?.image_tag),
|
||||||
llm_provider: preferDefined(bot.llm_provider, prev?.llm_provider),
|
llm_provider: preferDefined(bot.llm_provider, prev?.llm_provider),
|
||||||
llm_model: preferDefined(bot.llm_model, prev?.llm_model),
|
llm_model: preferDefined(bot.llm_model, prev?.llm_model),
|
||||||
|
api_key: preferDefined(bot.api_key, prev?.api_key),
|
||||||
api_base: preferDefined(bot.api_base, prev?.api_base),
|
api_base: preferDefined(bot.api_base, prev?.api_base),
|
||||||
temperature: preferDefined(bot.temperature, prev?.temperature),
|
temperature: preferDefined(bot.temperature, prev?.temperature),
|
||||||
top_p: preferDefined(bot.top_p, prev?.top_p),
|
top_p: preferDefined(bot.top_p, prev?.top_p),
|
||||||
|
|
@ -108,6 +109,7 @@ export const useAppStore = create<AppStore>((set) => ({
|
||||||
enabled: preferDefined(bot.enabled, prev?.enabled),
|
enabled: preferDefined(bot.enabled, prev?.enabled),
|
||||||
created_at: preferDefined(bot.created_at, prev?.created_at),
|
created_at: preferDefined(bot.created_at, prev?.created_at),
|
||||||
updated_at: preferDefined(bot.updated_at, prev?.updated_at),
|
updated_at: preferDefined(bot.updated_at, prev?.updated_at),
|
||||||
|
api_key: preferDefined(bot.api_key, prev?.api_key),
|
||||||
logs: prev?.logs ?? bot.logs ?? [],
|
logs: prev?.logs ?? bot.logs ?? [],
|
||||||
messages: prev?.messages ?? bot.messages ?? [],
|
messages: prev?.messages ?? bot.messages ?? [],
|
||||||
events: prev?.events ?? bot.events ?? [],
|
events: prev?.events ?? bot.events ?? [],
|
||||||
|
|
|
||||||
|
|
@ -28,6 +28,7 @@ export interface BotState {
|
||||||
image_tag?: string;
|
image_tag?: string;
|
||||||
llm_provider?: string;
|
llm_provider?: string;
|
||||||
llm_model?: string;
|
llm_model?: string;
|
||||||
|
api_key?: string;
|
||||||
api_base?: string;
|
api_base?: string;
|
||||||
temperature?: number;
|
temperature?: number;
|
||||||
top_p?: number;
|
top_p?: number;
|
||||||
|
|
|
||||||
|
|
@ -150,7 +150,6 @@ docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" exec -T \
|
||||||
|
|
||||||
PAGE_SIZE_JSON="10"
|
PAGE_SIZE_JSON="10"
|
||||||
CHAT_PULL_PAGE_SIZE_JSON="60"
|
CHAT_PULL_PAGE_SIZE_JSON="60"
|
||||||
COMMAND_AUTO_UNLOCK_SECONDS_JSON="10"
|
|
||||||
AUTH_TOKEN_TTL_HOURS_JSON="24"
|
AUTH_TOKEN_TTL_HOURS_JSON="24"
|
||||||
AUTH_TOKEN_MAX_ACTIVE_JSON="2"
|
AUTH_TOKEN_MAX_ACTIVE_JSON="2"
|
||||||
UPLOAD_MAX_MB_JSON="$UPLOAD_MAX_MB"
|
UPLOAD_MAX_MB_JSON="$UPLOAD_MAX_MB"
|
||||||
|
|
@ -171,7 +170,6 @@ docker compose --env-file "$ENV_FILE" -f "$COMPOSE_FILE" exec -T \
|
||||||
-v ON_ERROR_STOP=1 \
|
-v ON_ERROR_STOP=1 \
|
||||||
-v page_size_json="$PAGE_SIZE_JSON" \
|
-v page_size_json="$PAGE_SIZE_JSON" \
|
||||||
-v chat_pull_page_size_json="$CHAT_PULL_PAGE_SIZE_JSON" \
|
-v chat_pull_page_size_json="$CHAT_PULL_PAGE_SIZE_JSON" \
|
||||||
-v command_auto_unlock_seconds_json="$COMMAND_AUTO_UNLOCK_SECONDS_JSON" \
|
|
||||||
-v auth_token_ttl_hours_json="$AUTH_TOKEN_TTL_HOURS_JSON" \
|
-v auth_token_ttl_hours_json="$AUTH_TOKEN_TTL_HOURS_JSON" \
|
||||||
-v auth_token_max_active_json="$AUTH_TOKEN_MAX_ACTIVE_JSON" \
|
-v auth_token_max_active_json="$AUTH_TOKEN_MAX_ACTIVE_JSON" \
|
||||||
-v upload_max_mb_json="$UPLOAD_MAX_MB_JSON" \
|
-v upload_max_mb_json="$UPLOAD_MAX_MB_JSON" \
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ INSERT INTO sys_setting (
|
||||||
VALUES
|
VALUES
|
||||||
('page_size', '分页大小', 'ui', '平台各类列表默认每页条数。', 'integer', :'page_size_json', TRUE, 5, NOW(), NOW()),
|
('page_size', '分页大小', 'ui', '平台各类列表默认每页条数。', 'integer', :'page_size_json', TRUE, 5, NOW(), NOW()),
|
||||||
('chat_pull_page_size', '对话懒加载条数', 'chat', 'Bot 对话区向上懒加载时每次读取的消息条数。', 'integer', :'chat_pull_page_size_json', TRUE, 8, NOW(), NOW()),
|
('chat_pull_page_size', '对话懒加载条数', 'chat', 'Bot 对话区向上懒加载时每次读取的消息条数。', 'integer', :'chat_pull_page_size_json', TRUE, 8, NOW(), NOW()),
|
||||||
('command_auto_unlock_seconds', '发送按钮自动恢复秒数', 'chat', '对话发送后按钮保持停止态的最长秒数,超时后自动恢复为可发送状态。', 'integer', :'command_auto_unlock_seconds_json', TRUE, 9, NOW(), NOW()),
|
|
||||||
('auth_token_ttl_hours', '认证 Token 过期小时数', 'auth', 'Panel 与 Bot 登录 Token 的统一有效时长,单位小时。', 'integer', :'auth_token_ttl_hours_json', FALSE, 10, NOW(), NOW()),
|
('auth_token_ttl_hours', '认证 Token 过期小时数', 'auth', 'Panel 与 Bot 登录 Token 的统一有效时长,单位小时。', 'integer', :'auth_token_ttl_hours_json', FALSE, 10, NOW(), NOW()),
|
||||||
('auth_token_max_active', '认证 Token 最大并发数', 'auth', '同一主体允许同时活跃的 Token 数量,超过时自动撤销最旧 Token。', 'integer', :'auth_token_max_active_json', FALSE, 11, NOW(), NOW()),
|
('auth_token_max_active', '认证 Token 最大并发数', 'auth', '同一主体允许同时活跃的 Token 数量,超过时自动撤销最旧 Token。', 'integer', :'auth_token_max_active_json', FALSE, 11, NOW(), NOW()),
|
||||||
('upload_max_mb', '上传大小限制', 'upload', '单文件上传大小限制,单位 MB。', 'integer', :'upload_max_mb_json', FALSE, 20, NOW(), NOW()),
|
('upload_max_mb', '上传大小限制', 'upload', '单文件上传大小限制,单位 MB。', 'integer', :'upload_max_mb_json', FALSE, 20, NOW(), NOW()),
|
||||||
|
|
@ -35,6 +34,8 @@ SET
|
||||||
sort_order = EXCLUDED.sort_order,
|
sort_order = EXCLUDED.sort_order,
|
||||||
updated_at = NOW();
|
updated_at = NOW();
|
||||||
|
|
||||||
|
DELETE FROM sys_setting WHERE key = 'command_auto_unlock_seconds';
|
||||||
|
|
||||||
INSERT INTO skill_market_item (
|
INSERT INTO skill_market_item (
|
||||||
skill_key,
|
skill_key,
|
||||||
display_name,
|
display_name,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue