Files
LangBot/web/src/app/infra/http/index.ts
Junyan Qin bca710dbd4 feat(platform): show deployment outbound IPs on adapter config forms
Cloud/NAT deployments couldn't complete WeCom-family / Official Account /
QQ Official setup because the trusted-IP (IP whitelist) value — the
server's egress IPs — was nowhere visible in LangBot.

- config.yaml: new system.outbound_ips list (env: SYSTEM__OUTBOUND_IPS,
  comma-separated), exposed via GET /api/v1/system/info
- dynamic form: generic __system.*-named display-only fields resolved
  from systemContext (same namespace as show_if), one read-only row per
  value with a copy button, excluded from form state and emitted values;
  hidden entirely when the deployment provides no IPs
- manifests: trusted-IP display field for wecom, wecomcs, wecombot,
  officialaccount, qqofficial

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-06-10 19:41:17 +08:00

134 lines
3.6 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { BackendClient } from './BackendClient';
import { CloudServiceClient } from './CloudServiceClient';
import { ApiRespSystemInfo } from '@/app/infra/entities/api';
// 系统信息
export const systemInfo: ApiRespSystemInfo = {
debug: false,
version: '',
edition: 'community',
enable_marketplace: true,
cloud_service_url: '',
allow_modify_login_info: true,
disable_models_service: false,
limitation: {
max_bots: -1,
max_pipelines: -1,
max_extensions: -1,
},
outbound_ips: [],
wizard_status: 'none',
wizard_progress: null,
};
// 用户信息
export let userInfo: {
user: string;
account_type: 'local' | 'space';
has_password: boolean;
} | null = null;
/**
* 获取基础 URL
*/
const getBaseURL = (): string => {
if (typeof window !== 'undefined' && import.meta.env.VITE_API_BASE_URL) {
return import.meta.env.VITE_API_BASE_URL;
}
return '/';
};
// 创建后端客户端实例
export const backendClient = new BackendClient(getBaseURL());
// 为了兼容性,也导出为 httpClient
export const httpClient = backendClient;
// 创建云服务客户端实例(初始化时使用默认 URL
export const cloudServiceClient = new CloudServiceClient(
'https://space.langbot.app',
);
// 应用启动时自动初始化系统信息
if (typeof window !== 'undefined' && systemInfo.cloud_service_url === '') {
backendClient
.getSystemInfo()
.then((info) => {
Object.assign(systemInfo, info);
cloudServiceClient.updateBaseURL(info.cloud_service_url);
})
.catch((error) => {
console.error('Failed to initialize system info on startup:', error);
});
}
/**
* 获取云服务客户端
* 如果 cloud service URL 尚未初始化,会自动从后端获取
*/
export const getCloudServiceClient = async (): Promise<CloudServiceClient> => {
if (systemInfo.cloud_service_url === '') {
try {
Object.assign(systemInfo, await backendClient.getSystemInfo());
// 更新 cloud service client 的 baseURL
cloudServiceClient.updateBaseURL(systemInfo.cloud_service_url);
} catch (error) {
console.error('Failed to get system info:', error);
// 如果获取失败,继续使用默认 URL
}
}
return cloudServiceClient;
};
/**
* 获取云服务客户端(同步版本)
* 注意:如果 cloud service URL 尚未初始化,将使用默认 URL
*/
export const getCloudServiceClientSync = (): CloudServiceClient => {
return cloudServiceClient;
};
/**
* 手动初始化系统信息
* 可以在应用启动时调用此方法预先获取系统信息
*/
export const initializeSystemInfo = async (options?: {
throwOnError?: boolean;
}): Promise<void> => {
try {
Object.assign(systemInfo, await backendClient.getSystemInfo());
cloudServiceClient.updateBaseURL(systemInfo.cloud_service_url);
} catch (error) {
console.error('Failed to initialize system info:', error);
if (options?.throwOnError) {
throw error;
}
}
};
/**
* 初始化用户信息
* 应该在用户登录后调用此方法
*/
export const initializeUserInfo = async (): Promise<void> => {
try {
userInfo = await backendClient.getUserInfo();
} catch (error) {
console.error('Failed to initialize user info:', error);
userInfo = null;
}
};
/**
* 清除用户信息
* 应该在用户登出时调用此方法
*/
export const clearUserInfo = (): void => {
userInfo = null;
};
// 导出类型,以便其他地方使用
export type { ResponseData, RequestConfig } from './BaseHttpClient';
export { BaseHttpClient } from './BaseHttpClient';
export { BackendClient } from './BackendClient';
export { CloudServiceClient } from './CloudServiceClient';