fix: harden workflow smoke issues
This commit is contained in:
@@ -421,7 +421,7 @@ export BOOSAPI_SERVER__PORT=4000
|
||||
export BOOSAPI_AUTH__AUTH_TOKEN=your-admin-token
|
||||
export BOOSAPI_AUTH__PROXY_TOKEN=sk-your-proxy-token
|
||||
export BOOSAPI_UPSTREAM_BASE=https://api.boos.lat/v1
|
||||
export BOOSAPI_UPSTREAM_KEY=sk-boos4721
|
||||
export BOOSAPI_UPSTREAM_KEY=sk-your-upstream-key
|
||||
```
|
||||
|
||||
### 前端(React SPA)
|
||||
|
||||
@@ -359,6 +359,7 @@ mod tests {
|
||||
site_id INTEGER NOT NULL,
|
||||
access_token TEXT NOT NULL,
|
||||
api_token TEXT,
|
||||
unit_cost REAL,
|
||||
status TEXT NOT NULL DEFAULT 'active'
|
||||
)",
|
||||
)
|
||||
|
||||
@@ -368,6 +368,8 @@ async fn status_handler(
|
||||
"keyName": key_name,
|
||||
"userId": auth.user_id,
|
||||
"role": auth.role,
|
||||
"apiBase": upstream_base,
|
||||
"upstreamBase": upstream_base,
|
||||
"upstreamLabel": upstream_label,
|
||||
"comfyui": state.comfyui.status_response().await,
|
||||
})))
|
||||
|
||||
@@ -1570,6 +1570,7 @@ mod tests {
|
||||
site_id INTEGER NOT NULL,
|
||||
access_token TEXT NOT NULL,
|
||||
api_token TEXT,
|
||||
unit_cost REAL,
|
||||
status TEXT NOT NULL DEFAULT 'active'
|
||||
)",
|
||||
)
|
||||
|
||||
+20
-45
@@ -5183,55 +5183,30 @@ async fn workflow_context(state: &AppState, caller: &WorkflowCaller) -> AppResul
|
||||
}
|
||||
|
||||
fn inject_bootstrap(html: String, config: &crate::config::ComfyUIConfig) -> String {
|
||||
let cloud_api_key = workflow_cloud_api_key(config);
|
||||
if config.uses_native_backend() && !config.uses_cloud_backend() {
|
||||
return inject_external_bootstrap(html, cloud_api_key);
|
||||
return inject_external_bootstrap(html);
|
||||
}
|
||||
inject_enhanced_bootstrap(html, cloud_api_key)
|
||||
inject_enhanced_bootstrap(html)
|
||||
}
|
||||
|
||||
fn workflow_api_key_bootstrap(api_key: Option<&str>) -> String {
|
||||
let Some(api_key) = api_key else {
|
||||
return String::new();
|
||||
};
|
||||
let api_key = serde_json::to_string(api_key).unwrap_or_else(|_| "null".to_string());
|
||||
format!(
|
||||
fn workflow_secret_cleanup_bootstrap() -> &'static str {
|
||||
r#"<script>
|
||||
(function () {{
|
||||
const apiKey = {api_key};
|
||||
if (!apiKey) return;
|
||||
const installComfyApiKey = () => {{
|
||||
try {{
|
||||
localStorage.setItem('comfy_api_key', apiKey);
|
||||
sessionStorage.setItem('comfy_api_key', apiKey);
|
||||
for (const api of [window.app?.api, window.comfyAPI?.api, window.api]) {{
|
||||
if (api) {{
|
||||
api.apiKey = api.apiKey || apiKey;
|
||||
if (!api.__boosapiCloudApiKeyQueuePatch && typeof api.queuePrompt === 'function') {{
|
||||
const originalQueuePrompt = api.queuePrompt.bind(api);
|
||||
api.queuePrompt = function() {{
|
||||
if (!this.apiKey) this.apiKey = apiKey;
|
||||
return originalQueuePrompt(...arguments);
|
||||
}};
|
||||
api.__boosapiCloudApiKeyQueuePatch = true;
|
||||
}}
|
||||
}}
|
||||
}}
|
||||
document.cookie = 'comfy_api_key=' + encodeURIComponent(apiKey) + '; Path=/workflow-ui; SameSite=Lax';
|
||||
}} catch (err) {{}}
|
||||
}};
|
||||
installComfyApiKey();
|
||||
window.addEventListener('DOMContentLoaded', installComfyApiKey);
|
||||
window.setTimeout(installComfyApiKey, 300);
|
||||
window.setTimeout(installComfyApiKey, 1200);
|
||||
window.setInterval(installComfyApiKey, 5000);
|
||||
}})();
|
||||
(function () {
|
||||
const clearLeakedComfyApiKey = () => {
|
||||
try {
|
||||
localStorage.removeItem('comfy_api_key');
|
||||
sessionStorage.removeItem('comfy_api_key');
|
||||
document.cookie = 'comfy_api_key=; Path=/workflow-ui; Max-Age=0; SameSite=Lax';
|
||||
} catch (err) {}
|
||||
};
|
||||
clearLeakedComfyApiKey();
|
||||
window.addEventListener('DOMContentLoaded', clearLeakedComfyApiKey);
|
||||
})();
|
||||
</script>"#
|
||||
)
|
||||
}
|
||||
|
||||
fn inject_external_bootstrap(html: String, cloud_api_key: Option<&str>) -> String {
|
||||
let api_key_bootstrap = workflow_api_key_bootstrap(cloud_api_key);
|
||||
fn inject_external_bootstrap(html: String) -> String {
|
||||
let secret_cleanup_bootstrap = workflow_secret_cleanup_bootstrap();
|
||||
let shell = r#"<script>
|
||||
(function () {
|
||||
const renameComfyUiBrand = () => {
|
||||
@@ -5310,12 +5285,12 @@ fn inject_external_bootstrap(html: String, cloud_api_key: Option<&str>) -> Strin
|
||||
window.setTimeout(installWorkflowValidationButton, 1800);
|
||||
})();
|
||||
</script>"#;
|
||||
let bootstrap = format!("{api_key_bootstrap}{shell}");
|
||||
let bootstrap = format!("{secret_cleanup_bootstrap}{shell}");
|
||||
html.replace("</head>", &format!("{bootstrap}\n</head>"))
|
||||
}
|
||||
|
||||
fn inject_enhanced_bootstrap(html: String, cloud_api_key: Option<&str>) -> String {
|
||||
let api_key_bootstrap = workflow_api_key_bootstrap(cloud_api_key);
|
||||
fn inject_enhanced_bootstrap(html: String) -> String {
|
||||
let secret_cleanup_bootstrap = workflow_secret_cleanup_bootstrap();
|
||||
let shell = r#"<style id="boosapi-workflow-shell-style">
|
||||
</style>
|
||||
<script>
|
||||
@@ -5713,7 +5688,7 @@ fn inject_enhanced_bootstrap(html: String, cloud_api_key: Option<&str>) -> Strin
|
||||
window.setTimeout(patchWorkflowShell, 1200);
|
||||
})();
|
||||
</script>"#;
|
||||
let bootstrap = format!("{api_key_bootstrap}{shell}");
|
||||
let bootstrap = format!("{secret_cleanup_bootstrap}{shell}");
|
||||
html.replace("</head>", &format!("{bootstrap}\n</head>"))
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ describe('Login surface', () => {
|
||||
));
|
||||
|
||||
expect(pageText).toContain('BoosAPI');
|
||||
expect(pageText).toContain('中转站的中转站');
|
||||
expect(pageText).toContain('AI 应用平台');
|
||||
expect(pageText).not.toContain('一个 API Key,一个入口');
|
||||
expect(pageText).toContain('兼容 New API / One API / OneHub / DoneHub / Veloera / AnyRouter / Sub2API');
|
||||
expect(pageText).toContain('统一代理网关');
|
||||
|
||||
@@ -19,6 +19,8 @@ const zhToEn: Record<string, string> = {
|
||||
'仅校验本地服务访问权限,不会把令牌发送到第三方。': 'Only checks local service access and never sends the token to a third party.',
|
||||
'验证中...': 'Verifying...',
|
||||
'登录': 'Sign In',
|
||||
'AI 应用平台': 'AI Application Platform',
|
||||
'聚合多模型、多模态、工作流与智能路由,把对话、生图、视频和数字人生产放进一个统一平台。': 'Unify multi-model routing, multimodal creation, workflows, chat, image generation, video, and digital human production in one platform.',
|
||||
'中转站的中转站': 'The Hub of Hubs',
|
||||
'把分散的 New API / One API / OneHub 等站点聚合成统一网关,自动发现模型、智能路由、成本更优。': 'Turn fragmented New API / One API / OneHub sites into one unified gateway with auto model discovery, smart routing, and better cost control.',
|
||||
'兼容 New API / One API / OneHub / DoneHub / Veloera / AnyRouter / Sub2API': 'Compatible with New API / One API / OneHub / DoneHub / Veloera / AnyRouter / Sub2API',
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta name="description" content="BoosAPI - 中转站的中转站,聚合多个 AI API 中转站为统一网关" />
|
||||
<meta name="description" content="BossAI 聚合多模型多模态的 AI 应用平台" />
|
||||
<title>BoosAPI</title>
|
||||
<link rel="icon" type="image/png" href="/favicon.png" />
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com" />
|
||||
|
||||
@@ -53,7 +53,7 @@ export default function LoginShell({
|
||||
>
|
||||
<div className="login-brand-name">BoosAPI</div>
|
||||
<div className="login-brand-kicker">
|
||||
{variant === 'user' ? t('用户登录') : t('中转站的中转站')}
|
||||
{variant === 'user' ? t('用户登录') : t('AI 应用平台')}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -62,7 +62,7 @@ export default function LoginShell({
|
||||
<>
|
||||
<div className="login-brand-copy-block">
|
||||
<p className="login-brand-copy">
|
||||
{t('把分散的 New API / One API / OneHub 等站点聚合成统一网关,自动发现模型、智能路由、成本更优。')}
|
||||
{t('聚合多模型、多模态、工作流与智能路由,把对话、生图、视频和数字人生产放进一个统一平台。')}
|
||||
</p>
|
||||
</div>
|
||||
<div className="login-compat-line">
|
||||
|
||||
Reference in New Issue
Block a user