优化模型配置和节回显
This commit is contained in:
@@ -141,6 +141,15 @@ These rules capture long-term repository preferences confirmed by the user and s
|
||||
- When code changes appear not to take effect, check in this order: compile/HMR status, render conditions, API data, then style overrides.
|
||||
- Turn repeated low-level mistakes into explicit workflow checks and follow those checks in future edits.
|
||||
|
||||
### Environment and Tool Selection Rules
|
||||
|
||||
- Before running environment-dependent commands, first follow the known runtime context already provided by the IDE, such as OS and default shell.
|
||||
- On Windows projects with PowerShell as the active shell, prefer PowerShell-native commands and scripts by default.
|
||||
- Do not assume Python, bash, sed, awk, or other non-default tooling is installed locally unless the user or repository explicitly indicates that they are available.
|
||||
- For reading and editing repository files, prefer dedicated file tools first; use shell-based text replacement only when file tools are not suitable for the change.
|
||||
- When a replacement fails once, do not keep retrying the same method blindly. Re-read the exact target content and switch to a smaller or more reliable edit strategy that matches the current environment.
|
||||
- Avoid trial-and-error probing for basic tooling when the available environment is already known from context.
|
||||
|
||||
### Componentization and Structure Rules
|
||||
|
||||
- If a view block has an independent responsibility, prefer extracting it into a component instead of keeping it inside a large page file.
|
||||
|
||||
@@ -118,15 +118,22 @@ interface ModelItem {
|
||||
apiKey?: string;
|
||||
isPrivate?: number;
|
||||
isChatModel?: number;
|
||||
headMsg?: string;
|
||||
headMsg?: string | Record<string, string>;
|
||||
operatorName?: string;
|
||||
responseBody?: Record<string, unknown>;
|
||||
responseTokenField?: string;
|
||||
tokenConfig?: Record<string, unknown> | string;
|
||||
extendMapping?: Record<string, unknown> | string;
|
||||
queryConfig?: Record<string, unknown>;
|
||||
streamConfig?: Record<string, unknown>;
|
||||
form?: ModelFormEntry[] | Record<string, unknown>;
|
||||
requestMapping?: Record<string, unknown>;
|
||||
requiredFields?: string[];
|
||||
firstFrame?: string;
|
||||
lastFrame?: string;
|
||||
responseMapping?: Record<string, unknown>;
|
||||
callMode?: number;
|
||||
isAsync?: number;
|
||||
maxConcurrency?: number;
|
||||
queueLimit?: number;
|
||||
timeoutSeconds?: number;
|
||||
@@ -271,74 +278,71 @@ const fieldsToUnknownObject = (fields: Array<{ key: string; value: string }>) =>
|
||||
return obj;
|
||||
};
|
||||
|
||||
const flattenNestedObject = (obj: Record<string, unknown>, prefix = ''): Array<{ key: string; value: string }> => {
|
||||
const rows: Array<{ key: string; value: string }> = [];
|
||||
Object.entries(obj || {}).forEach(([k, v]) => {
|
||||
const fk = prefix ? `${prefix}.${k}` : k;
|
||||
if (v && typeof v === 'object' && !Array.isArray(v)) {
|
||||
rows.push(...flattenNestedObject(v as Record<string, unknown>, fk));
|
||||
return;
|
||||
const parseFormEntries = (raw: unknown): ModelFormEntry[] => {
|
||||
if (Array.isArray(raw)) {
|
||||
return (raw as ModelFormEntry[])
|
||||
.filter((item) => item && item.key !== undefined)
|
||||
.map((item) => ({
|
||||
key: String(item.key ?? '').trim(),
|
||||
value: String(item.value ?? ''),
|
||||
}))
|
||||
.filter((item) => item.key !== '');
|
||||
}
|
||||
rows.push({ key: fk, value: String(v ?? '') });
|
||||
|
||||
if (raw && typeof raw === 'object') {
|
||||
return Object.entries(raw as Record<string, unknown>).map(([key, value]) => {
|
||||
let nextValue = value;
|
||||
if (nextValue && typeof nextValue === 'object' && !Array.isArray(nextValue) && 'value' in nextValue) {
|
||||
nextValue = (nextValue as { value: unknown }).value;
|
||||
}
|
||||
return {
|
||||
key: String(key).trim(),
|
||||
value: String(nextValue ?? ''),
|
||||
};
|
||||
});
|
||||
return rows;
|
||||
}
|
||||
|
||||
return [];
|
||||
};
|
||||
|
||||
const nestFieldsToObject = (fields: Array<{ key: string; value: string }>) => {
|
||||
const root: Record<string, unknown> = {};
|
||||
fields.forEach((f) => {
|
||||
const path = String(f.key || '').trim();
|
||||
if (!path) return;
|
||||
const parts = path
|
||||
.split('.')
|
||||
.map((p) => p.trim())
|
||||
.filter(Boolean);
|
||||
if (!parts.length) return;
|
||||
let cur: Record<string, unknown> = root;
|
||||
parts.forEach((part, idx) => {
|
||||
if (idx === parts.length - 1) {
|
||||
cur[part] = String(f.value ?? '');
|
||||
return;
|
||||
const normalizeQueryConfig = (raw: unknown): Record<string, unknown> => {
|
||||
if (raw && typeof raw === 'object' && !Array.isArray(raw)) {
|
||||
return raw as Record<string, unknown>;
|
||||
}
|
||||
if (!cur[part] || typeof cur[part] !== 'object' || Array.isArray(cur[part])) {
|
||||
cur[part] = {};
|
||||
}
|
||||
cur = cur[part] as Record<string, unknown>;
|
||||
});
|
||||
});
|
||||
return root;
|
||||
return {};
|
||||
};
|
||||
|
||||
const buildQueryConfigFromRaw = (rawQc: Record<string, unknown> | null): Record<string, unknown> => {
|
||||
if (!rawQc) return { responseType: 'sync', callbackUrl: '' };
|
||||
const rt = String(rawQc.responseType || 'sync');
|
||||
if (rt === 'callback') return { responseType: 'callback', callbackUrl: String(rawQc.callbackUrl || '') };
|
||||
if (rt === 'pull') {
|
||||
const hFields = Object.entries((rawQc.headers as Record<string, unknown>) || {}).map(([k, v]) => ({ key: k, value: String(v ?? '') }));
|
||||
const bFields = flattenNestedObject((rawQc.body as Record<string, unknown>) || {});
|
||||
return {
|
||||
responseType: 'pull',
|
||||
callbackUrl: '',
|
||||
method: String(rawQc.method || 'GET'),
|
||||
url: String(rawQc.url || ''),
|
||||
headers: fieldsToUnknownObject(hFields),
|
||||
body: nestFieldsToObject(bFields),
|
||||
response: ((rawQc.response as unknown[]) || [])
|
||||
.map((item) => {
|
||||
if (typeof item === 'string') {
|
||||
return { value: item, isTokenField: false, isMainBody: false };
|
||||
const parseHeadMsgRecord = (raw: ModelItem['headMsg']) => {
|
||||
const headMsgRecord: Record<string, string> = {};
|
||||
if (typeof raw === 'string') {
|
||||
try {
|
||||
const parsed = JSON.parse(raw);
|
||||
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
||||
Object.entries(parsed).forEach(([k, v]) => {
|
||||
headMsgRecord[k] = String(v);
|
||||
});
|
||||
return headMsgRecord;
|
||||
}
|
||||
const row = item as Record<string, unknown>;
|
||||
return {
|
||||
value: String(row.value ?? ''),
|
||||
isTokenField: Boolean(row.isTokenField),
|
||||
isMainBody: Boolean(row.isMainBody),
|
||||
};
|
||||
})
|
||||
.filter((row) => row.value !== ''),
|
||||
};
|
||||
} catch {
|
||||
const pairs = raw.split(',');
|
||||
pairs.forEach((pair) => {
|
||||
const idx = pair.indexOf(':');
|
||||
if (idx === -1) return;
|
||||
const key = pair.slice(0, idx).trim();
|
||||
const value = pair.slice(idx + 1).trim();
|
||||
if (key) {
|
||||
headMsgRecord[key] = value;
|
||||
}
|
||||
return { responseType: 'sync', callbackUrl: '' };
|
||||
});
|
||||
return headMsgRecord;
|
||||
}
|
||||
}
|
||||
if (raw && typeof raw === 'object' && !Array.isArray(raw)) {
|
||||
Object.entries(raw).forEach(([k, v]) => {
|
||||
headMsgRecord[k] = String(v);
|
||||
});
|
||||
}
|
||||
return headMsgRecord;
|
||||
};
|
||||
|
||||
const fetchModelList = async () => {
|
||||
@@ -396,43 +400,7 @@ const handleCreatePrivateModel = async () => {
|
||||
creatingModel.value = true;
|
||||
|
||||
const builtInModel = builtInModelToClone.value;
|
||||
const formList: ModelFormEntry[] = Array.isArray(builtInModel.form)
|
||||
? (builtInModel.form as ModelFormEntry[])
|
||||
: Object.entries((builtInModel.form as Record<string, unknown>) || {}).map(([key, value]) => ({
|
||||
key: String(key),
|
||||
value: String(value ?? ''),
|
||||
}));
|
||||
|
||||
// Parse headMsg to Record<string, string> - it might be stored as string or already as object
|
||||
let headMsgRecord: Record<string, string> = {};
|
||||
if (builtInModel.headMsg && typeof builtInModel.headMsg === 'string') {
|
||||
// Try to parse as JSON first (new format stored as string)
|
||||
try {
|
||||
const parsed = JSON.parse(builtInModel.headMsg);
|
||||
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {
|
||||
Object.entries(parsed).forEach(([k, v]) => {
|
||||
headMsgRecord[k] = String(v);
|
||||
});
|
||||
}
|
||||
} catch {
|
||||
// If JSON parse fails, parse as old format "key1:value1,key2:value2"
|
||||
const pairs = builtInModel.headMsg.split(',');
|
||||
pairs.forEach((pair) => {
|
||||
const idx = pair.indexOf(':');
|
||||
if (idx === -1) return;
|
||||
const key = pair.slice(0, idx).trim();
|
||||
const value = pair.slice(idx + 1).trim();
|
||||
if (key) {
|
||||
headMsgRecord[key] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
} else if (builtInModel.headMsg && typeof builtInModel.headMsg === 'object' && !Array.isArray(builtInModel.headMsg)) {
|
||||
// Already an object
|
||||
Object.entries(builtInModel.headMsg).forEach(([k, v]) => {
|
||||
headMsgRecord[k] = String(v);
|
||||
});
|
||||
}
|
||||
const formList = parseFormEntries(builtInModel.form);
|
||||
|
||||
const createParams: CreateModelParams = {
|
||||
modelName: apiKeyForm.modelName,
|
||||
@@ -440,7 +408,7 @@ const handleCreatePrivateModel = async () => {
|
||||
operatorName: builtInModel.operatorName || '',
|
||||
baseUrl: builtInModel.baseUrl,
|
||||
httpMethod: builtInModel.httpMethod || 'POST',
|
||||
headMsg: headMsgRecord,
|
||||
headMsg: parseHeadMsgRecord(builtInModel.headMsg),
|
||||
isPrivate: builtInModel.isPrivate ?? 1,
|
||||
enabled: builtInModel.enabled ?? 1,
|
||||
isChatModel: builtInModel.isChatModel || 0,
|
||||
@@ -466,14 +434,13 @@ const handleCreatePrivateModel = async () => {
|
||||
tokenConfig: fieldsToUnknownObject(
|
||||
Object.entries(parseJsonObjectField(builtInModel.tokenConfig)).map(([k, v]) => ({ key: k, value: String(v ?? '') }))
|
||||
),
|
||||
queryConfig: buildQueryConfigFromRaw(
|
||||
builtInModel.queryConfig && typeof builtInModel.queryConfig === 'object' && !Array.isArray(builtInModel.queryConfig)
|
||||
? (builtInModel.queryConfig as Record<string, unknown>)
|
||||
: null
|
||||
),
|
||||
queryConfig: normalizeQueryConfig(builtInModel.queryConfig),
|
||||
responseTokenField: String(builtInModel.responseTokenField || ''),
|
||||
streamConfig:
|
||||
builtInModel.streamConfig && typeof builtInModel.streamConfig === 'object' && !Array.isArray(builtInModel.streamConfig)
|
||||
Number(builtInModel.callMode ?? builtInModel.isAsync ?? 0) === 2
|
||||
? builtInModel.streamConfig && typeof builtInModel.streamConfig === 'object' && !Array.isArray(builtInModel.streamConfig)
|
||||
? (builtInModel.streamConfig as Record<string, unknown>)
|
||||
: {}
|
||||
: undefined,
|
||||
};
|
||||
|
||||
|
||||
@@ -1116,6 +1116,11 @@ const availableParentParams = computed(() => {
|
||||
|
||||
const allParentIds = findAllParentNodes(selectedElement.value.id);
|
||||
const params: Array<{ label: string; value: string }> = [];
|
||||
const pushParentParam = (label: string, value: string) => {
|
||||
if (!label || !value) return;
|
||||
if (params.some((item) => item.value === value)) return;
|
||||
params.push({ label, value });
|
||||
};
|
||||
|
||||
// 遍历所有上级节点
|
||||
allParentIds.forEach((parentId) => {
|
||||
@@ -1133,15 +1138,14 @@ const availableParentParams = computed(() => {
|
||||
// 如果是判断节点,跳过不添加其字段
|
||||
if (isJudge) return;
|
||||
|
||||
pushParentParam(`${parentNodeName}.输出结果`, `\${${parentId}.nodeOutputResult}`);
|
||||
|
||||
const modelOutputFields = Array.isArray(parentProps.modelOutputFields) ? parentProps.modelOutputFields : [];
|
||||
if (modelOutputFields.length > 0) {
|
||||
modelOutputFields.forEach((field: any) => {
|
||||
const fieldName = String(field || '').trim();
|
||||
if (!fieldName) return;
|
||||
params.push({
|
||||
label: `${parentNodeName}.${fieldName}`,
|
||||
value: `\${${parentId}.${fieldName}}`,
|
||||
});
|
||||
pushParentParam(`${parentNodeName}.${fieldName}`, `\${${parentId}.${fieldName}}`);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1163,10 +1167,7 @@ const availableParentParams = computed(() => {
|
||||
if (responseValue && typeof responseValue === 'object' && !Array.isArray(responseValue)) {
|
||||
Object.keys(responseValue).forEach((key) => {
|
||||
if (!key || key.startsWith('_temp_')) return;
|
||||
params.push({
|
||||
label: `${parentNodeName}.${key}`,
|
||||
value: `\${${parentId}.${key}}`,
|
||||
});
|
||||
pushParentParam(`${parentNodeName}.${key}`, `\${${parentId}.${key}}`);
|
||||
});
|
||||
}
|
||||
return;
|
||||
@@ -1174,10 +1175,7 @@ const availableParentParams = computed(() => {
|
||||
|
||||
parentProps.formConfig.forEach((field: any) => {
|
||||
if (field.label) {
|
||||
params.push({
|
||||
label: `${parentNodeName}.${field.label}`,
|
||||
value: `\${${parentId}.${field.label}}`,
|
||||
});
|
||||
pushParentParam(`${parentNodeName}.${field.label}`, `\${${parentId}.${field.label}}`);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user