feat: 将部分逻辑移到后端,简化脚本

This commit is contained in:
PKC278
2026-03-18 17:48:28 +08:00
parent b50a3b9aae
commit 78c4ec8bfe
2 changed files with 29 additions and 99 deletions

View File

@@ -149,6 +149,19 @@ class MoviePilotToolsManager:
return True return True
return value return value
@staticmethod
def _parse_array_string(value: str, key: str, item_type: str = "string") -> list:
"""
将逗号分隔的字符串解析为列表,并根据 item_type 转换元素类型
"""
trimmed = value.strip()
if not trimmed:
return []
return [
MoviePilotToolsManager._normalize_scalar_value(item_type, item.strip(), key)
for item in trimmed.split(",") if item.strip()
]
@staticmethod @staticmethod
def _normalize_arguments(tool_instance: Any, arguments: Dict[str, Any]) -> Dict[str, Any]: def _normalize_arguments(tool_instance: Any, arguments: Dict[str, Any]) -> Dict[str, Any]:
""" """
@@ -185,6 +198,12 @@ class MoviePilotToolsManager:
field_info = MoviePilotToolsManager._resolve_field_schema(properties[key]) field_info = MoviePilotToolsManager._resolve_field_schema(properties[key])
field_type = field_info.get("type") field_type = field_info.get("type")
# 数组类型:将字符串解析为列表
if field_type == "array" and isinstance(value, str):
item_type = field_info.get("items", {}).get("type", "string")
normalized[key] = MoviePilotToolsManager._parse_array_string(value, key, item_type)
continue
# 根据类型进行转换 # 根据类型进行转换
normalized[key] = MoviePilotToolsManager._normalize_scalar_value(field_type, value, key) normalized[key] = MoviePilotToolsManager._normalize_scalar_value(field_type, value, key)

View File

@@ -149,7 +149,7 @@ function normalizeCommand(tool = {}) {
}; };
} }
function request(method, targetUrl, headers = {}, body) { function request(method, targetUrl, headers = {}, body, timeout = 120000) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
let url; let url;
try { try {
@@ -180,6 +180,10 @@ function request(method, targetUrl, headers = {}, body) {
} }
); );
req.setTimeout(timeout, () => {
req.destroy(new Error(`Request timed out after ${timeout}ms`));
});
req.on('error', reject); req.on('error', reject);
if (body !== undefined) { if (body !== undefined) {
@@ -225,7 +229,7 @@ async function loadCommandJson(commandName) {
if (statusCode === '404') { if (statusCode === '404') {
console.error(`Error: command '${commandName}' not found`); console.error(`Error: command '${commandName}' not found`);
console.error(`Run '${SCRIPT_NAME} list' to see available commands`); console.error(`Run 'node ${SCRIPT_NAME} list' to see available commands`);
process.exit(1); process.exit(1);
} }
@@ -345,80 +349,7 @@ async function cmdShow(commandName) {
process.stdout.write(`\n${usageLabel} ${usageLine}${reqPart}${optPart}\n`); process.stdout.write(`\n${usageLabel} ${usageLine}${reqPart}${optPart}\n`);
} }
function parseBoolean(value) { function buildArguments(pairs) {
return value === 'true' || value === '1' || value === 'yes';
}
function parseNumber(value, key) {
if (value === '') {
fail(`Error: invalid numeric value for '${key}'`);
}
const result = Number(value);
if (Number.isNaN(result)) {
fail(`Error: invalid numeric value for '${key}': '${value}'`);
}
return result;
}
function parseScalarValue(value, key, type = 'string') {
if (type === 'integer' || type === 'number') {
return parseNumber(value, key);
}
if (type === 'boolean') {
return parseBoolean(value);
}
return value;
}
function parseArrayValue(value, key, itemType = 'string') {
const trimmed = value.trim();
if (!trimmed) {
return [];
}
if (trimmed.startsWith('[')) {
let parsed;
try {
parsed = JSON.parse(trimmed);
} catch {
fail(`Error: invalid array value for '${key}': '${value}'`);
}
if (!Array.isArray(parsed)) {
fail(`Error: invalid array value for '${key}': '${value}'`);
}
return parsed.map((item) => {
if (typeof item === 'string') {
return parseScalarValue(item.trim(), key, itemType);
}
if (itemType === 'integer' || itemType === 'number') {
if (typeof item !== 'number') {
fail(`Error: invalid numeric value for '${key}': '${item}'`);
}
return item;
}
if (itemType === 'boolean') {
if (typeof item !== 'boolean') {
fail(`Error: invalid boolean value for '${key}': '${item}'`);
}
return item;
}
return item;
});
}
return trimmed
.split(',')
.map((item) => item.trim())
.filter(Boolean)
.map((item) => parseScalarValue(item, key, itemType));
}
function buildArguments(command, pairs) {
const args = { explanation: 'CLI invocation' }; const args = { explanation: 'CLI invocation' };
for (const kv of pairs) { for (const kv of pairs) {
@@ -427,40 +358,20 @@ function buildArguments(command, pairs) {
} }
const index = kv.indexOf('='); const index = kv.indexOf('=');
const key = kv.slice(0, index); args[kv.slice(0, index)] = kv.slice(index + 1);
const value = kv.slice(index + 1);
const field = command.fields.find((item) => item.name === key);
const fieldType = field?.type || 'string';
const itemType = field?.item_type || 'string';
if (fieldType === 'array') {
args[key] = parseArrayValue(value, key, itemType);
continue;
}
args[key] = parseScalarValue(value, key, fieldType);
} }
return args; return args;
} }
async function cmdRun(commandName, pairs) { async function cmdRun(commandName, pairs) {
await loadCommandsJson();
if (!commandName) { if (!commandName) {
fail(`Usage: ${SCRIPT_NAME} <command> [key=value ...]`); fail(`Usage: ${SCRIPT_NAME} <command> [key=value ...]`);
} }
const command = commandsJson.find((item) => item.name === commandName);
if (!command) {
console.error(`Error: command '${commandName}' not found`);
console.error(`Run 'node ${SCRIPT_NAME} list' to see available commands`);
process.exit(1);
}
const requestBody = JSON.stringify({ const requestBody = JSON.stringify({
tool_name: commandName, tool_name: commandName,
arguments: buildArguments(command, pairs), arguments: buildArguments(pairs),
}); });
const { statusCode, body } = await request( const { statusCode, body } = await request(
@@ -490,7 +401,7 @@ async function cmdRun(commandName, pairs) {
try { try {
printValue(JSON.parse(parsed.result)); printValue(JSON.parse(parsed.result));
} catch { } catch {
printValue({ result: parsed.result }); printValue(parsed.result);
} }
} else { } else {
printValue(parsed.result); printValue(parsed.result);