ai-chatbot/scripts/test-agent-detail-replacement-recovery.ts

293 lines
8.2 KiB
TypeScript

import {
getAllResultUrlsFromAgentProjectState,
mergeAgentProjectStateForSave,
} from "@/lib/agents/agent-project-save-merge";
import { normalizeAgentGenerationProjectPersistedState } from "@/lib/agents/generation-project-state";
import type { AgentGenerationProjectPersistedState } from "@/types/agent";
const DETAIL_RESULT_URL = "https://scqny.jiansun.vip/uploads/1785470582893-rmh0xr.png";
const DETAIL_RESULT_URL_2 = "https://scqny.jiansun.vip/uploads/1785470577924-owj79k.png";
const SKU_RESULT_URL = "https://scqny.jiansun.vip/uploads/1785470458027-c6yuar.png";
const DETAIL_REFERENCE_URL = "https://example.com/detail-reference.png";
function createWorkflowState(params?: {
detailReferences?: number;
skuReferences?: number;
}) {
return {
inputs: {
primarySku: "",
secondarySku: "",
brand: "",
store: "",
thirdCategory: "",
fourthCategory: "",
fifthCategory: "",
priceBand: "",
},
selections: {},
currentStage: "mode",
agentModeState: {
detailReplacement: {
query: "766308902517",
references: Array.from({ length: params?.detailReferences || 0 }, (_, index) => ({
id: `detail-card-${index + 1}`,
label: `Detail ${index + 1}`,
imageUrl: DETAIL_REFERENCE_URL,
previewUrl: DETAIL_REFERENCE_URL,
})),
},
skuReplacement: {
query: "sku-query",
references: Array.from({ length: params?.skuReferences || 0 }, (_, index) => ({
id: `sku-card-${index + 1}`,
label: `SKU ${index + 1}`,
imageUrl: DETAIL_REFERENCE_URL,
previewUrl: DETAIL_REFERENCE_URL,
})),
},
},
};
}
function createExistingDetailProjectState(): AgentGenerationProjectPersistedState {
return normalizeAgentGenerationProjectPersistedState({
workflowState: createWorkflowState({ detailReferences: 1 }),
workspaceState: {
input: "legacy detail replacement",
selectedModelId: "auto",
},
resultCollections: {
detail_replacement: [DETAIL_RESULT_URL],
},
replacementResultState: {
detail_replacement: {
"detail-card-1": {
url: DETAIL_RESULT_URL,
text: "completed",
status: "completed",
updatedAt: 1,
compareSourceUrl: DETAIL_REFERENCE_URL,
referenceImageUrl: DETAIL_REFERENCE_URL,
referencePreviewUrl: DETAIL_REFERENCE_URL,
label: "Detail 1",
},
},
},
});
}
function expect(condition: boolean, message: string) {
if (!condition) {
throw new Error(message);
}
}
function expectEqual<T>(actual: T, expected: T, label: string) {
if (!Object.is(actual, expected)) {
throw new Error(`${label}: expected ${String(expected)}, received ${String(actual)}`);
}
}
function expectIncludesUrl(urls: string[] | undefined, url: string) {
expect(Boolean(urls?.includes(url)), `expected ${url} to be present`);
}
function expectExcludesUrl(urls: string[] | undefined, url: string) {
expect(!urls?.includes(url), `expected ${url} to be absent`);
}
const legacyDetailState = createExistingDetailProjectState();
expectEqual(
legacyDetailState.workspaceState?.activeBusinessModeKey,
"detail",
"legacy detail mode"
);
expectIncludesUrl(legacyDetailState.resultCollections?.detail_replacement, DETAIL_RESULT_URL);
expectEqual(
legacyDetailState.workflowState.agentModeState?.detailReplacement.references.length,
1,
"legacy detail reference count"
);
const resultOnlyLegacyState = normalizeAgentGenerationProjectPersistedState({
workflowState: createWorkflowState(),
workspaceState: {
input: "legacy result-only detail replacement",
selectedModelId: "auto",
},
resultCollections: {
detail_replacement: [DETAIL_RESULT_URL_2],
},
});
expectEqual(
resultOnlyLegacyState.workspaceState?.activeBusinessModeKey,
"detail",
"result-only detail mode"
);
expectIncludesUrl(
resultOnlyLegacyState.resultCollections?.detail_replacement,
DETAIL_RESULT_URL_2
);
const emptyProjectState = normalizeAgentGenerationProjectPersistedState({
workflowState: createWorkflowState(),
workspaceState: {
input: "",
selectedModelId: "auto",
},
});
expectEqual(
emptyProjectState.workspaceState?.activeBusinessModeKey,
"main_sku",
"empty project mode"
);
const staleEmptySaveState = mergeAgentProjectStateForSave({
existingState: legacyDetailState,
incomingState: {
workflowState: createWorkflowState(),
workspaceState: {
input: "",
selectedModelId: "auto",
activeBusinessModeKey: "main_sku",
imageParams: {
aspectRatio: "auto",
imageSize: "2K",
imageCount: 1,
},
},
resultImageUrls: [],
resultCollections: {},
replacementResultState: {},
},
});
expectEqual(
staleEmptySaveState.workspaceState?.activeBusinessModeKey,
"detail",
"stale empty save mode"
);
expectIncludesUrl(
staleEmptySaveState.resultCollections?.detail_replacement,
DETAIL_RESULT_URL
);
expectIncludesUrl(getAllResultUrlsFromAgentProjectState(staleEmptySaveState), DETAIL_RESULT_URL);
expectEqual(
staleEmptySaveState.workflowState.agentModeState?.detailReplacement.references.length,
1,
"stale empty save reference count"
);
expectEqual(
staleEmptySaveState.replacementResultState?.detail_replacement?.["detail-card-1"]?.url,
DETAIL_RESULT_URL,
"stale empty save replacement record"
);
const replacementStateOnlySave = mergeAgentProjectStateForSave({
existingState: normalizeAgentGenerationProjectPersistedState({
workflowState: createWorkflowState({ detailReferences: 1 }),
workspaceState: {
input: "",
selectedModelId: "auto",
},
}),
incomingState: {
workflowState: createWorkflowState({ detailReferences: 1 }),
workspaceState: {
input: "",
selectedModelId: "auto",
},
replacementResultState: {
detail_replacement: {
"detail-card-1": {
url: DETAIL_RESULT_URL_2,
text: "completed",
status: "completed",
updatedAt: 2,
},
},
},
},
});
expectEqual(
replacementStateOnlySave.workspaceState?.activeBusinessModeKey,
"detail",
"replacement-state-only mode"
);
expectIncludesUrl(
replacementStateOnlySave.resultCollections?.detail_replacement,
DETAIL_RESULT_URL_2
);
expectIncludesUrl(
getAllResultUrlsFromAgentProjectState(replacementStateOnlySave),
DETAIL_RESULT_URL_2
);
const deletedResultSave = mergeAgentProjectStateForSave({
existingState: legacyDetailState,
incomingState: {
workflowState: createWorkflowState({ detailReferences: 1 }),
workspaceState: {
input: "",
selectedModelId: "auto",
activeBusinessModeKey: "detail",
},
deletedResultCollections: {
detail_replacement: [DETAIL_RESULT_URL],
},
resultCollections: {},
replacementResultState: {},
},
});
expectExcludesUrl(deletedResultSave.resultCollections?.detail_replacement, DETAIL_RESULT_URL);
expectExcludesUrl(getAllResultUrlsFromAgentProjectState(deletedResultSave), DETAIL_RESULT_URL);
expectEqual(
deletedResultSave.replacementResultState?.detail_replacement?.["detail-card-1"],
undefined,
"deleted replacement record"
);
const skuReplacementState = normalizeAgentGenerationProjectPersistedState({
workflowState: createWorkflowState({ skuReferences: 1 }),
workspaceState: {
input: "",
selectedModelId: "auto",
},
replacementResultState: {
sku_replacement: {
"sku-card-1": {
url: SKU_RESULT_URL,
text: "completed",
status: "completed",
updatedAt: 3,
},
},
},
});
expectEqual(
skuReplacementState.workspaceState?.activeBusinessModeKey,
"detail",
"sku replacement mode"
);
expectIncludesUrl(skuReplacementState.resultCollections?.sku_replacement, SKU_RESULT_URL);
console.log(
JSON.stringify(
{
ok: true,
covered: [
"legacy detail mode inference",
"result-only detail mode inference",
"empty project stays main_sku",
"stale empty save keeps detail results",
"stale empty save keeps detail reference cards",
"replacementResultState repopulates resultCollections",
"explicit deletion is respected",
"sku replacement recovery",
],
},
null,
2
)
);