type Cluster =
| "finance"
| "product"
| "hr"
| "marketing"
| "compliance"
| "supply_chain"
| (string & {});
type Goal =
| "revenue_forecast"
| "cashflow_forecast"
| "break_even"
| "profitability"
| "roi_forecast"
| "valuation_dcf"
| "price_elasticity"
| "anomaly_detection"
| "demand_forecast"
| "inventory_coverage"
| "return_rate_forecast"
| "headcount_forecast"
| "attrition_forecast"
| "mql_forecast"
| "cac_ltv_projection"
| "esg_risk_score"
| (string & {});
type BacktestMetric = "WAPE" | "MAE" | "RMSE";
interface RunOptions {
confidence?: number;
includeIntervals?: boolean;
sensitivity?: { topK?: number };
backtest?: { from: string; to: string; metric?: BacktestMetric };
retrain?: "auto" | "never";
tags?: string[];
metadata?: Record<string, unknown>;
}
interface RunParams {
projectId: string;
cluster: Cluster;
goal: Goal;
horizon: "3M" | "6M" | "12M" | (string & {});
inputs: Record<string, unknown>;
explainability?: boolean;
options?: RunOptions;
}
interface RunResult {
run_id: string;
forecast: Array<{ date: string; value: number }>;
intervals?: Array<{ date: string; lower: number; upper: number; confidence: number }>;
explanations?: {
global_top_features: Array<{ feature: string; weight: number }>;
local?: Array<{ date: string; contributions: Array<{ feature: string; weight: number }> }>;
};
diagnostics?: {
metrics?: Partial<Record<BacktestMetric, number>>;
retrain?: boolean;
warnings?: string[];
};
}
class MockCNode {
constructor(
private cfg: {
baseUrl?: string;
apiKey?: string;
apiVersion?: string;
} = {}
) {
this.cfg.apiVersion ??= "2025-09-01";
}
scenarios = {
run: async (p: RunParams): Promise<RunResult> => {
if (this.cfg.baseUrl) {
const res = await fetch(`${this.cfg.baseUrl}/scenarios:run`, {
method: "POST",
headers: {
"Content-Type": "application/json",
"X-API-Version": this.cfg.apiVersion!,
"X-Demo-Mode": "true",
Authorization: this.cfg.apiKey ? `Bearer ${this.cfg.apiKey}` : undefined
} as Record<string, string>,
body: JSON.stringify({
project_id: p.projectId,
cluster: p.cluster,
goal: p.goal,
horizon: p.horizon,
inputs: p.inputs,
explainability: p.explainability ?? true,
options: p.options,
_note: "SDK-preview: replace mock route with production once live"
})
});
if (!res.ok) {
const err = await res.json().catch(() => ({}));
throw new Error(`Mock SDK ${res.status}: ${err.message ?? res.statusText}`);
}
return res.json();
}
const months = parseHorizonToMonths(p.horizon);
const start = new Date(Date.UTC(2025, 0, 1));
const base = 42000;
const step = 3500;
const forecast = Array.from({ length: months }, (_, i) => {
const d = new Date(start);
d.setUTCMonth(d.getUTCMonth() + i);
const trend = base + step * i;
const season = 1 + 0.1 * Math.sin((2 * Math.PI * i) / 12);
return { date: d.toISOString().slice(0, 10), value: Math.round(trend * season) };
});
const intervals = forecast.map((pnt) => ({
date: pnt.date,
lower: Math.round(pnt.value * 0.9),
upper: Math.round(pnt.value * 1.1),
confidence: (p.options?.confidence ?? 0.8)
}));
const explanations: RunResult["explanations"] = {
global_top_features: [
{ feature: "trend", weight: 0.45 },
{ feature: "seasonality", weight: 0.32 },
{ feature: "promo_index", weight: 0.11 }
]
};
const diagnostics: RunResult["diagnostics"] = {
metrics: p.options?.backtest ? { WAPE: 0.14, MAE: 5200, RMSE: 7300 } : undefined,
retrain: p.options?.retrain === "auto",
warnings: []
};
return {
run_id: "mock-sdk-run-001",
forecast,
intervals: p.options?.includeIntervals !== false ? intervals : undefined,
explanations: p.explainability === false ? undefined : explanations,
diagnostics
};
}
};
}
function parseHorizonToMonths(h: RunParams["horizon"]): number {
if (typeof h !== "string") return 12;
const m = h.match(/^(\d+)\s*(M|m|months?)$/);
if (m) return Math.max(1, parseInt(m[1], 10));
const y = h.match(/^(\d+)\s*(Y|y|years?)$/);
if (y) return Math.max(1, parseInt(y[1], 10) * 12);
if (h === "3M") return 3;
if (h === "6M") return 6;
if (h === "12M") return 12;
return 12;
}
(async () => {
const cnode = new MockCNode();
const run = await cnode.scenarios.run({
projectId: "demo-finance",
cluster: "finance",
goal: "revenue_forecast",
horizon: "12M",
inputs: {
currency: "EUR",
revenue_history: [
{ date: "2024-09-01", value: 42000 },
{ date: "2025-08-01", value: 86500 }
],
cost_history: [
{ date: "2024-09-01", value: -28000 },
{ date: "2025-08-01", value: -52500 }
],
promo_index: [{ date: "2025-06-01", value: 0.6 }]
},
explainability: true,
options: {
confidence: 0.8,
includeIntervals: true,
sensitivity: { topK: 5 },
backtest: { from: "2025-01-01", to: "2025-08-01", metric: "WAPE" },
retrain: "auto",
tags: ["homepage-demo"],
metadata: { source: "marketing-site" }
}
});
console.log("Run:", run.run_id);
console.table(run.forecast.slice(0, 6));
if (run.intervals) console.table(run.intervals.slice(0, 3));
console.log("Top drivers:", run.explanations?.global_top_features?.slice(0, 5));
console.log("Metrics:", run.diagnostics?.metrics);
})();