161 lines
5.7 KiB
JavaScript
161 lines
5.7 KiB
JavaScript
import { getCustomNodeOriginalIdentity } from "../custom_nodes/registry.js";
|
|
|
|
export const workflowIdentityMethods = {
|
|
encodeMissingModelKeyPart(value) {
|
|
return encodeURIComponent(String(value ?? '').trim());
|
|
},
|
|
|
|
getMissingModelIdentityPart(missing = {}) {
|
|
return getCustomNodeOriginalIdentity(missing)
|
|
|| missing.original_path
|
|
|| missing.expected_filename
|
|
|| missing.name
|
|
|| missing.filename
|
|
|| missing.urn_string
|
|
|| '';
|
|
},
|
|
|
|
getMissingModelKey(missing = {}) {
|
|
if (missing.missing_key) {
|
|
return String(missing.missing_key);
|
|
}
|
|
|
|
const nodeId = missing.node_id ?? '';
|
|
const widgetIndex = missing.widget_index ?? '';
|
|
const subgraphId = missing.subgraph_id || '';
|
|
const scope = missing.is_top_level !== false ? 'T' : 'F';
|
|
const nestedKey = missing.nested_key || '';
|
|
const category = missing.category || '';
|
|
const identity = this.getMissingModelIdentityPart(missing);
|
|
return [
|
|
nodeId,
|
|
widgetIndex,
|
|
subgraphId,
|
|
scope,
|
|
nestedKey,
|
|
category,
|
|
identity
|
|
].map(value => this.encodeMissingModelKeyPart(value)).join(':');
|
|
},
|
|
|
|
getMissingModelWorkflowSlotKeys(missing = {}) {
|
|
const references = [missing];
|
|
if (Array.isArray(missing.all_node_refs)) {
|
|
references.push(...missing.all_node_refs);
|
|
}
|
|
|
|
const seen = new Set();
|
|
const keys = [];
|
|
for (const reference of references) {
|
|
const nodeId = reference?.node_id;
|
|
if (nodeId === undefined || nodeId === null || nodeId === '') continue;
|
|
|
|
const scope = reference.is_top_level !== false ? 'T' : 'F';
|
|
const key = [
|
|
scope,
|
|
reference.subgraph_id || '',
|
|
nodeId,
|
|
reference.widget_index ?? '',
|
|
reference.nested_key || ''
|
|
].map(value => this.encodeMissingModelKeyPart(value)).join(':');
|
|
if (seen.has(key)) continue;
|
|
seen.add(key);
|
|
keys.push(key);
|
|
}
|
|
return keys;
|
|
},
|
|
|
|
findMissingModelReplacement(previousMissing = {}, missingModels = [], preferredIndex = 0) {
|
|
const previousSlots = this.getMissingModelWorkflowSlotKeys(previousMissing);
|
|
if (!previousSlots.length || !Array.isArray(missingModels) || !missingModels.length) {
|
|
return null;
|
|
}
|
|
|
|
const previousSlotPositions = new Map(
|
|
previousSlots.map((slotKey, index) => [slotKey, index])
|
|
);
|
|
let best = null;
|
|
missingModels.forEach((missing, index) => {
|
|
const candidateSlots = this.getMissingModelWorkflowSlotKeys(missing);
|
|
let slotRank = Number.POSITIVE_INFINITY;
|
|
candidateSlots.forEach((slotKey, candidateSlotIndex) => {
|
|
const previousSlotIndex = previousSlotPositions.get(slotKey);
|
|
if (previousSlotIndex === undefined) return;
|
|
slotRank = Math.min(slotRank, previousSlotIndex + candidateSlotIndex);
|
|
});
|
|
if (!Number.isFinite(slotRank)) return;
|
|
|
|
const rank = [
|
|
slotRank,
|
|
Math.abs(index - preferredIndex),
|
|
index
|
|
];
|
|
if (
|
|
!best
|
|
|| rank[0] < best.rank[0]
|
|
|| (rank[0] === best.rank[0] && rank[1] < best.rank[1])
|
|
|| (rank[0] === best.rank[0] && rank[1] === best.rank[1] && rank[2] < best.rank[2])
|
|
) {
|
|
best = { missing, rank };
|
|
}
|
|
});
|
|
return best?.missing || null;
|
|
},
|
|
|
|
resolvePreservedMissingModelKey(missingModels = [], previousMissingModels = [], previousKey = '') {
|
|
if (!previousKey || !Array.isArray(missingModels) || !missingModels.length) return '';
|
|
|
|
const exact = missingModels.find(missing => this.getMissingModelKey(missing) === previousKey);
|
|
if (exact) return previousKey;
|
|
|
|
const previousIndex = previousMissingModels.findIndex(
|
|
missing => this.getMissingModelKey(missing) === previousKey
|
|
);
|
|
if (previousIndex < 0) return '';
|
|
|
|
const replacement = this.findMissingModelReplacement(
|
|
previousMissingModels[previousIndex],
|
|
missingModels,
|
|
previousIndex
|
|
);
|
|
return replacement ? this.getMissingModelKey(replacement) : '';
|
|
},
|
|
|
|
remapMissingModelKeys(
|
|
missingModels = [],
|
|
previousMissingModels = [],
|
|
previousKeys = null,
|
|
currentMissingModels = null
|
|
) {
|
|
const currentKeys = new Set(
|
|
(Array.isArray(currentMissingModels) ? currentMissingModels : missingModels)
|
|
.map(missing => this.getMissingModelKey(missing))
|
|
);
|
|
const remappedKeys = new Set();
|
|
for (const previousKey of previousKeys || []) {
|
|
if (
|
|
currentKeys.has(previousKey)
|
|
&& !missingModels.some(missing => this.getMissingModelKey(missing) === previousKey)
|
|
) {
|
|
continue;
|
|
}
|
|
const nextKey = this.resolvePreservedMissingModelKey(
|
|
missingModels,
|
|
previousMissingModels,
|
|
previousKey
|
|
);
|
|
if (nextKey) remappedKeys.add(nextKey);
|
|
}
|
|
return remappedKeys;
|
|
},
|
|
|
|
getMissingModelDomKey(missing = {}) {
|
|
const key = this.getMissingModelKey(missing);
|
|
try {
|
|
return btoa(key).replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/g, '');
|
|
} catch (_e) {
|
|
return key.replace(/[^A-Za-z0-9_-]/g, char => `_${char.charCodeAt(0).toString(16)}_`);
|
|
}
|
|
},
|
|
};
|