mirror of
https://github.com/flash555588/ai-model-workbench.git
synced 2026-07-22 06:56:38 +00:00
Normalize oversized schema-marked part profiles
This commit is contained in:
parent
afe4787fe4
commit
eb3226871e
4 changed files with 224 additions and 161 deletions
|
|
@ -25,6 +25,7 @@
|
|||
- Performance: lazy-load the full settings tab UI and model import modal so normal workspace startup only registers lightweight entry points.
|
||||
- Performance: combine model profile normalization and compact-state change detection into one pass, reducing startup work for large `data.json` registered-part lists.
|
||||
- Performance: reuse already-normalized registered part arrays while loading model profiles, avoiding repeated object allocation for compact `data.json` state.
|
||||
- Performance: normalize schema-marked but oversized registered-part lists on load so anomalous large `data.json` profiles are compacted back under the startup budget.
|
||||
- Performance: cache Three.js root bounds and pre-index grouped part descendants so large converted models do less repeated scene traversal after loading.
|
||||
- Performance: reuse Three.js child-mesh descendant indexes for picking, evidence grouping, and disassembly setup so large assemblies avoid repeated subtree scans during selection.
|
||||
- Performance: reuse shared Three.js focus-dim materials across meshes with the same source material, reducing material churn when focusing parts in large assemblies.
|
||||
|
|
|
|||
320
main.js
320
main.js
File diff suppressed because one or more lines are too long
|
|
@ -370,6 +370,65 @@ describe("createPluginStore persistence", () => {
|
|||
expect(saveData).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("normalizes schema-marked profiles that still contain oversized registered part lists", async () => {
|
||||
const now = "2026-06-22T00:00:00.000Z";
|
||||
const createPart = (index: number, partial: Partial<PartRecord> = {}): PartRecord => ({
|
||||
partId: `part-${index}`,
|
||||
assetId: "models/oversized.glb",
|
||||
name: `mesh-${index}`,
|
||||
source: "mesh",
|
||||
meshRefs: [`mesh-${index}`],
|
||||
materialRefs: [],
|
||||
confidence: 0.2,
|
||||
observations: [],
|
||||
inferredFunctions: [],
|
||||
knowledgeTags: [],
|
||||
reviewed: false,
|
||||
...partial,
|
||||
});
|
||||
const saved: PersistedPluginState = {
|
||||
stateSchemaVersion: 1,
|
||||
settings: { ...DEFAULT_SETTINGS },
|
||||
convertedAssetRecords: [],
|
||||
modelAssetProfiles: {
|
||||
"models/oversized.glb": {
|
||||
tags: [],
|
||||
notes: "",
|
||||
annotations: [],
|
||||
registeredParts: [
|
||||
...Array.from({ length: 300 }, (_value, index) => createPart(index)),
|
||||
createPart(1000, { partId: "reviewed-part", name: "Reviewed part", reviewed: true }),
|
||||
createPart(1001, { partId: "component-part", name: "Component", source: "component", confidence: 0.82 }),
|
||||
],
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
},
|
||||
},
|
||||
agentDraft: "",
|
||||
agentPlan: null,
|
||||
lastKnowledgeGeneration: null,
|
||||
};
|
||||
const normalizedSaves: PersistedPluginState[] = [];
|
||||
const { plugin, saveData } = createFakePlugin(async (data) => {
|
||||
normalizedSaves.push(data);
|
||||
}, saved);
|
||||
const pluginStore = createPluginStore(plugin);
|
||||
|
||||
await pluginStore.load();
|
||||
|
||||
const parts = pluginStore.store.getState().modelAssetProfiles["models/oversized.glb"]?.registeredParts ?? [];
|
||||
expect(parts).toHaveLength(256);
|
||||
expect(parts.some((part) => part.partId === "reviewed-part")).toBe(true);
|
||||
expect(parts.some((part) => part.partId === "component-part")).toBe(true);
|
||||
|
||||
await vi.advanceTimersByTimeAsync(50);
|
||||
await settlePromises();
|
||||
|
||||
expect(saveData).toHaveBeenCalledTimes(1);
|
||||
expect(normalizedSaves[0].stateSchemaVersion).toBe(1);
|
||||
expect(normalizedSaves[0].modelAssetProfiles["models/oversized.glb"]?.registeredParts).toHaveLength(256);
|
||||
});
|
||||
|
||||
it("persists the current schema marker once for legacy compact state", async () => {
|
||||
const now = "2026-06-22T00:00:00.000Z";
|
||||
const saved: PersistedPluginState = {
|
||||
|
|
|
|||
|
|
@ -240,7 +240,10 @@ function isReusableModelAssetProfile(profile: Partial<ModelAssetProfile>): profi
|
|||
return Array.isArray(profile.tags) &&
|
||||
typeof profile.notes === "string" &&
|
||||
Array.isArray(profile.annotations) &&
|
||||
(profile.registeredParts === undefined || Array.isArray(profile.registeredParts)) &&
|
||||
(
|
||||
profile.registeredParts === undefined ||
|
||||
(Array.isArray(profile.registeredParts) && profile.registeredParts.length <= MAX_REGISTERED_PARTS_PER_PROFILE)
|
||||
) &&
|
||||
isNormalizedOptionalString(profile.analysisVersion) &&
|
||||
isNormalizedOptionalString(profile.reportNotePath) &&
|
||||
isNormalizedOptionalString(profile.analysisSidecarPath) &&
|
||||
|
|
|
|||
Loading…
Reference in a new issue