type CriterionValues = Record; type DecisionOption = { optionId: string; name: string; values: CriterionValues }; type ExecutionRequest = { decisionId: string; profileId: string; scenarioId: string; algorithm: string; weightStrategy: string; runSensitivity: boolean; requestContext: { correlationId: string }; options: DecisionOption[]; }; const required = (name: string): string => { const value = process.env[name]; if (!value) throw new Error(`Set ${name} before running this example.`); return value; }; const identityUrl = process.env.DECISIOQ_IDENTITY_URL ?? "https://identity.vinquery.com/connect/token"; const catalogUrl = (process.env.DECISIOQ_DKS_URL ?? "https://dks.vinquery.com").replace(/\/$/, ""); const decisionServiceUrl = (process.env.DECISIOQ_DDE_URL ?? "https://dde.vinquery.com").replace(/\/$/, ""); const correlationId = `auto-rent-008-ts-${crypto.randomUUID()}`; const values = (fit: number, demand: number, margin: number, cost: number, risk: number, customer: number): CriterionValues => ({ assign_rental_vehicle_customer_fit_score: fit, assign_rental_vehicle_vehicle_or_resource_fit: demand, assign_rental_vehicle_operational_readiness: margin, assign_rental_vehicle_financial_impact: cost, assign_rental_vehicle_risk_exposure: risk, assign_rental_vehicle_time_sensitivity: customer }); const tokenResponse = await fetch(identityUrl, { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ clientId: required("DECISIOQ_CLIENT_ID"), clientSecret: required("DECISIOQ_CLIENT_SECRET"), audience: process.env.DECISIOQ_AUDIENCE ?? "vinquery:api:decisioq" }) }); if (!tokenResponse.ok) throw new Error(await tokenResponse.text()); const token = await tokenResponse.json() as { jwtToken: string }; const detailResponse = await fetch(`${catalogUrl}/decisioncatalog/decisions/AUTO-RENT-008`, { headers: { Authorization: `Bearer ${token.jwtToken}`, "X-Correlation-Id": correlationId } }); if (!detailResponse.ok) throw new Error(`Decision detail failed: ${detailResponse.status}`); const decisionDetail = await detailResponse.json(); const constraints = decisionDetail.constraints ?? []; if (constraints.length === 0) { console.log("No catalog-defined hard constraints; all validated candidates proceed to criteria-based ranking."); } const executionRequest: ExecutionRequest = { decisionId: "AUTO-RENT-008", profileId: "balanced", scenarioId: "standard_rental", algorithm: "TOPSIS", weightStrategy: "Expert", runSensitivity: false, requestContext: { correlationId }, options: [ { optionId: "OPTION-001", name: "Compact SUV Unit", values: values(88, 91, 84, 76, 20, 26) }, { optionId: "OPTION-002", name: "Standard Sedan Unit", values: values(79, 85, 92, 70, 18, 34) }, { optionId: "OPTION-003", name: "Premium SUV Unit", values: values(92, 73, 68, 88, 42, 50) } ] }; const executionResponse = await fetch(`${decisionServiceUrl}/api/v1/decide`, { method: "POST", headers: { Authorization: `Bearer ${token.jwtToken}`, "Content-Type": "application/json", "X-Correlation-Id": correlationId }, body: JSON.stringify(executionRequest) }); const responseText = await executionResponse.text(); console.log(responseText); try { const response = JSON.parse(responseText); console.log("Constraint summary:", response.constraintSummary ?? { excludedOptions: response.decisionResult?.excludedOptions ?? [] }); } catch { // Non-JSON errors are printed above. } if (!executionResponse.ok) process.exitCode = 1;