Spaces:
Running
Running
Upload 101 files
Browse files- 前端页面/components/用户体验_国际化.js +4 -2
- 前端页面/core/全局配置.js +2 -1
- 前端页面/market/Skill安装流程.js +20 -8
- 前端页面/market/资源安装引擎.js +6 -3
前端页面/components/用户体验_国际化.js
CHANGED
|
@@ -25,7 +25,7 @@ const translations = {
|
|
| 25 |
'skill.directory_truncated': "仅显示部分子文件夹,可直接输入完整目录地址。",
|
| 26 |
'skill.directory_ready': "核对当前目录后,点击“使用此目录”。",
|
| 27 |
'skill.local_update_required': "本地插件尚未支持目录选择,请更新并重启 ComfyUI。",
|
| 28 |
-
'skill.invalid_package': "
|
| 29 |
'skill.plan_invalid': "安装准备已失效,请重新选择目录。",
|
| 30 |
'skill.identity_changed': "登录状态或资源权限已变化,请重新确认后安装。",
|
| 31 |
'skill.source_changed': "资源地址已变化,请重新准备安装。",
|
|
@@ -40,6 +40,7 @@ const translations = {
|
|
| 40 |
'skill.preview_shared': "共用文件",
|
| 41 |
'skill.preparing': "正在准备 Skill 文件…",
|
| 42 |
'skill.prepared': "文件已准备,请核对安装内容。",
|
|
|
|
| 43 |
'skill.cancelled': "已取消;接收目录未写入。",
|
| 44 |
'skill.outcome_unknown': "安装结果暂时无法确认。请先检查所选接收目录,勿重复提交。",
|
| 45 |
|
|
@@ -1815,7 +1816,7 @@ const translations = {
|
|
| 1815 |
'skill.directory_truncated': "Only some subfolders are shown. You can enter the full folder path.",
|
| 1816 |
'skill.directory_ready': "Check the current folder, then select “Use this folder”.",
|
| 1817 |
'skill.local_update_required': "Update the local plugin and restart ComfyUI to enable folder selection.",
|
| 1818 |
-
'skill.invalid_package': "
|
| 1819 |
'skill.plan_invalid': "The installation preparation is no longer valid. Choose the folder again.",
|
| 1820 |
'skill.identity_changed': "Your login or resource permissions changed. Check them before installing.",
|
| 1821 |
'skill.source_changed': "The resource address changed. Prepare the installation again.",
|
|
@@ -1830,6 +1831,7 @@ const translations = {
|
|
| 1830 |
'skill.preview_shared': "Shared files",
|
| 1831 |
'skill.preparing': "Preparing Skill files…",
|
| 1832 |
'skill.prepared': "Files are ready. Review the installation contents.",
|
|
|
|
| 1833 |
'skill.cancelled': "Cancelled; the destination was not changed.",
|
| 1834 |
'skill.outcome_unknown': "The installation outcome is unconfirmed. Check the selected destination before submitting again.",
|
| 1835 |
|
|
|
|
| 25 |
'skill.directory_truncated': "仅显示部分子文件夹,可直接输入完整目录地址。",
|
| 26 |
'skill.directory_ready': "核对当前目录后,点击“使用此目录”。",
|
| 27 |
'skill.local_update_required': "本地插件尚未支持目录选择,请更新并重启 ComfyUI。",
|
| 28 |
+
'skill.invalid_package': "资源包含无法安全安装的文件,请发布者检查资源内容。",
|
| 29 |
'skill.plan_invalid': "安装准备已失效,请重新选择目录。",
|
| 30 |
'skill.identity_changed': "登录状态或资源权限已变化,请重新确认后安装。",
|
| 31 |
'skill.source_changed': "资源地址已变化,请重新准备安装。",
|
|
|
|
| 40 |
'skill.preview_shared': "共用文件",
|
| 41 |
'skill.preparing': "正在准备 Skill 文件…",
|
| 42 |
'skill.prepared': "文件已准备,请核对安装内容。",
|
| 43 |
+
'skill.checking_result': '正在核实安装结果...',
|
| 44 |
'skill.cancelled': "已取消;接收目录未写入。",
|
| 45 |
'skill.outcome_unknown': "安装结果暂时无法确认。请先检查所选接收目录,勿重复提交。",
|
| 46 |
|
|
|
|
| 1816 |
'skill.directory_truncated': "Only some subfolders are shown. You can enter the full folder path.",
|
| 1817 |
'skill.directory_ready': "Check the current folder, then select “Use this folder”.",
|
| 1818 |
'skill.local_update_required': "Update the local plugin and restart ComfyUI to enable folder selection.",
|
| 1819 |
+
'skill.invalid_package': "The resource contains files that cannot be installed safely. Ask the publisher to check the resource.",
|
| 1820 |
'skill.plan_invalid': "The installation preparation is no longer valid. Choose the folder again.",
|
| 1821 |
'skill.identity_changed': "Your login or resource permissions changed. Check them before installing.",
|
| 1822 |
'skill.source_changed': "The resource address changed. Prepare the installation again.",
|
|
|
|
| 1831 |
'skill.preview_shared': "Shared files",
|
| 1832 |
'skill.preparing': "Preparing Skill files…",
|
| 1833 |
'skill.prepared': "Files are ready. Review the installation contents.",
|
| 1834 |
+
'skill.checking_result': 'Checking installation result...',
|
| 1835 |
'skill.cancelled': "Cancelled; the destination was not changed.",
|
| 1836 |
'skill.outcome_unknown': "The installation outcome is unconfirmed. Check the selected destination before submitting again.",
|
| 1837 |
|
前端页面/core/全局配置.js
CHANGED
|
@@ -108,11 +108,12 @@ export const SKILL_INSTALL = Object.freeze({
|
|
| 108 |
PATH: '/community_hub/skill_install',
|
| 109 |
PREFLIGHT_TIMEOUT: 30000,
|
| 110 |
CONTROL_TIMEOUT: 45000,
|
|
|
|
| 111 |
STREAM_TIMEOUT: 1200000,
|
| 112 |
RESPONSE_MAX_BYTES: 1024 * 1024,
|
| 113 |
PATH_MAX_BYTES: 32768,
|
| 114 |
MAX_DIRECTORIES: 128,
|
| 115 |
-
MAX_ITEMS:
|
| 116 |
MODAL_WIDTH: '640px'
|
| 117 |
});
|
| 118 |
|
|
|
|
| 108 |
PATH: '/community_hub/skill_install',
|
| 109 |
PREFLIGHT_TIMEOUT: 30000,
|
| 110 |
CONTROL_TIMEOUT: 45000,
|
| 111 |
+
RESULT_TIMEOUT: 5000,
|
| 112 |
STREAM_TIMEOUT: 1200000,
|
| 113 |
RESPONSE_MAX_BYTES: 1024 * 1024,
|
| 114 |
PATH_MAX_BYTES: 32768,
|
| 115 |
MAX_DIRECTORIES: 128,
|
| 116 |
+
MAX_ITEMS: 1,
|
| 117 |
MODAL_WIDTH: '640px'
|
| 118 |
});
|
| 119 |
|
前端页面/market/Skill安装流程.js
CHANGED
|
@@ -45,12 +45,12 @@ export function skillErrorMessage(error) {
|
|
| 45 |
return t(errorKey);
|
| 46 |
}
|
| 47 |
|
| 48 |
-
async function control(action, body, signal) {
|
| 49 |
const controller = new AbortController();
|
| 50 |
const abort = () => controller.abort();
|
| 51 |
signal?.addEventListener('abort', abort, { once: true });
|
| 52 |
if (signal?.aborted) controller.abort();
|
| 53 |
-
const timer = setTimeout(abort,
|
| 54 |
try {
|
| 55 |
if (controller.signal.aborted) throw failure('operation_cancelled');
|
| 56 |
const response = await fetch(SKILL_INSTALL.PATH, {
|
|
@@ -59,7 +59,8 @@ async function control(action, body, signal) {
|
|
| 59 |
});
|
| 60 |
if (response.status === 404 || response.status === 405) throw failure('local_update_required');
|
| 61 |
const value = await readLocalJSON(response, controller, SKILL_INSTALL.RESPONSE_MAX_BYTES);
|
| 62 |
-
if (!response.ok || !object(value) || value.status !== 'success' || value.installed
|
|
|
|
| 63 |
|| Object.hasOwn(value, 'error') || Object.hasOwn(value, 'error_code')) {
|
| 64 |
throw failure(object(value) && typeof value.error_code === 'string' ? value.error_code : 'invalid_metadata');
|
| 65 |
}
|
|
@@ -145,6 +146,13 @@ export function chooseSkillDirectory(scope) {
|
|
| 145 |
});
|
| 146 |
}
|
| 147 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 148 |
function validReady(result, plan, target) {
|
| 149 |
return object(result) && result.status === 'success' && result.phase === 'ready'
|
| 150 |
&& result.installed === false && (!Object.hasOwn(result, 'outcomeUnknown') || result.outcomeUnknown === false)
|
|
@@ -183,14 +191,18 @@ export async function runSkillInstall({ target, credentials, scope, confirm, onP
|
|
| 183 |
try { result = await stream('commit'); }
|
| 184 |
catch (error) {
|
| 185 |
if (error?.fallbackSafe) return { status: 'error', error_code: 'local_update_required', outcomeUnknown: false };
|
| 186 |
-
return { status: 'error', outcomeUnknown: true };
|
| 187 |
}
|
| 188 |
-
if (
|
| 189 |
-
&& result.installed === true && (!Object.hasOwn(result, 'outcomeUnknown') || result.outcomeUnknown === false)
|
| 190 |
-
&& result.installed_version === ready.installed_version
|
| 191 |
-
&& !Object.hasOwn(result, 'error') && !Object.hasOwn(result, 'error_code')) return result;
|
| 192 |
if (object(result) && result.status === 'error' && result.outcomeUnknown === false
|
| 193 |
&& typeof result.error_code === 'string') return result;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
return { status: 'error', outcomeUnknown: true };
|
| 195 |
} catch (error) {
|
| 196 |
throw failure(error?.fallbackSafe ? 'local_update_required' : error?.code || 'install_failed');
|
|
|
|
| 45 |
return t(errorKey);
|
| 46 |
}
|
| 47 |
|
| 48 |
+
async function control(action, body, signal, timeout = SKILL_INSTALL.CONTROL_TIMEOUT) {
|
| 49 |
const controller = new AbortController();
|
| 50 |
const abort = () => controller.abort();
|
| 51 |
signal?.addEventListener('abort', abort, { once: true });
|
| 52 |
if (signal?.aborted) controller.abort();
|
| 53 |
+
const timer = setTimeout(abort, timeout);
|
| 54 |
try {
|
| 55 |
if (controller.signal.aborted) throw failure('operation_cancelled');
|
| 56 |
const response = await fetch(SKILL_INSTALL.PATH, {
|
|
|
|
| 59 |
});
|
| 60 |
if (response.status === 404 || response.status === 405) throw failure('local_update_required');
|
| 61 |
const value = await readLocalJSON(response, controller, SKILL_INSTALL.RESPONSE_MAX_BYTES);
|
| 62 |
+
if (!response.ok || !object(value) || value.status !== 'success' || !(value.installed === false
|
| 63 |
+
|| action === 'status' && value.phase === 'complete' && value.installed === true)
|
| 64 |
|| Object.hasOwn(value, 'error') || Object.hasOwn(value, 'error_code')) {
|
| 65 |
throw failure(object(value) && typeof value.error_code === 'string' ? value.error_code : 'invalid_metadata');
|
| 66 |
}
|
|
|
|
| 146 |
});
|
| 147 |
}
|
| 148 |
|
| 149 |
+
function confirmed(result, version) {
|
| 150 |
+
return object(result) && result.status === 'success' && result.phase === 'complete'
|
| 151 |
+
&& result.installed === true && (!Object.hasOwn(result, 'outcomeUnknown') || result.outcomeUnknown === false)
|
| 152 |
+
&& result.installed_version === version
|
| 153 |
+
&& !Object.hasOwn(result, 'error') && !Object.hasOwn(result, 'error_code');
|
| 154 |
+
}
|
| 155 |
+
|
| 156 |
function validReady(result, plan, target) {
|
| 157 |
return object(result) && result.status === 'success' && result.phase === 'ready'
|
| 158 |
&& result.installed === false && (!Object.hasOwn(result, 'outcomeUnknown') || result.outcomeUnknown === false)
|
|
|
|
| 191 |
try { result = await stream('commit'); }
|
| 192 |
catch (error) {
|
| 193 |
if (error?.fallbackSafe) return { status: 'error', error_code: 'local_update_required', outcomeUnknown: false };
|
|
|
|
| 194 |
}
|
| 195 |
+
if (confirmed(result, ready.installed_version)) return result;
|
|
|
|
|
|
|
|
|
|
| 196 |
if (object(result) && result.status === 'error' && result.outcomeUnknown === false
|
| 197 |
&& typeof result.error_code === 'string') return result;
|
| 198 |
+
if (scope.isCurrent() && !signal.aborted) {
|
| 199 |
+
try {
|
| 200 |
+
onProgress?.({ stage: 'validate', progress: 99, skillAction: 'status' });
|
| 201 |
+
const receipt = await control('status', parameters, signal, SKILL_INSTALL.RESULT_TIMEOUT);
|
| 202 |
+
if (scope.isCurrent() && !signal.aborted && receipt.plan_id === plan && receipt.target === target
|
| 203 |
+
&& confirmed(receipt, ready.installed_version)) return receipt;
|
| 204 |
+
} catch {}
|
| 205 |
+
}
|
| 206 |
return { status: 'error', outcomeUnknown: true };
|
| 207 |
} catch (error) {
|
| 208 |
throw failure(error?.fallbackSafe ? 'local_update_required' : error?.code || 'install_failed');
|
前端页面/market/资源安装引擎.js
CHANGED
|
@@ -436,11 +436,12 @@ export function setupResourceInstall(btnUse, itemData, currentUser, inlineStatus
|
|
| 436 |
const data = await response.json();
|
| 437 |
if (!isCurrent()) return;
|
| 438 |
if (isSkill && !response.ok) {
|
| 439 |
-
validationMessage = t(data?.error_code === '
|
|
|
|
| 440 |
throw new Error();
|
| 441 |
}
|
| 442 |
if (!response.ok || data?.status !== "success" || data.error) throw new Error();
|
| 443 |
-
if (isSkill && data.
|
| 444 |
validationMessage = t('skill.cloud_update_required');
|
| 445 |
throw new Error();
|
| 446 |
}
|
|
@@ -534,7 +535,9 @@ export function setupResourceInstall(btnUse, itemData, currentUser, inlineStatus
|
|
| 534 |
onProgress: event => {
|
| 535 |
if (!isCurrent()) return;
|
| 536 |
const stageKey = Object.hasOwn(INSTALL_STAGE_KEYS, event.stage) ? INSTALL_STAGE_KEYS[event.stage] : 'skill.preparing';
|
| 537 |
-
|
|
|
|
|
|
|
| 538 |
}
|
| 539 |
});
|
| 540 |
if (!isCurrent()) return;
|
|
|
|
| 436 |
const data = await response.json();
|
| 437 |
if (!isCurrent()) return;
|
| 438 |
if (isSkill && !response.ok) {
|
| 439 |
+
validationMessage = t(data?.error_code === 'invalid_repository' ? 'install.error_invalid_repository'
|
| 440 |
+
: data?.error_code === 'invalid_skill_package' ? 'skill.invalid_package' : 'skill.source_unavailable');
|
| 441 |
throw new Error();
|
| 442 |
}
|
| 443 |
if (!response.ok || data?.status !== "success" || data.error) throw new Error();
|
| 444 |
+
if (isSkill && data.skill_repository_verified !== true) {
|
| 445 |
validationMessage = t('skill.cloud_update_required');
|
| 446 |
throw new Error();
|
| 447 |
}
|
|
|
|
| 535 |
onProgress: event => {
|
| 536 |
if (!isCurrent()) return;
|
| 537 |
const stageKey = Object.hasOwn(INSTALL_STAGE_KEYS, event.stage) ? INSTALL_STAGE_KEYS[event.stage] : 'skill.preparing';
|
| 538 |
+
const label = event.skillAction === 'status' ? t('skill.checking_result')
|
| 539 |
+
: event.skillAction === 'prepare' && event.stage === 'complete' ? t('skill.prepared') : t(stageKey);
|
| 540 |
+
progress.update(event.progress, label);
|
| 541 |
}
|
| 542 |
});
|
| 543 |
if (!isCurrent()) return;
|