SuperAI_Forecast / frontend /analysis-runtime.js
Thang6822
Update HF Space deployment
4106e0f
(() => {
const MODEL_CONFIG = window.AIFORECAST_MODEL_CONFIG || null;
const ANALYSIS_CACHE_VERSION = window.AIFORECAST_ANALYSIS_CACHE_VERSION || 'chronos2-v1';
window.AIFORECAST_ANALYSIS_CACHE_VERSION = ANALYSIS_CACHE_VERSION;
const AI_CONTEXT_POLICY = window.AIFORECAST_FORECAST_CONTEXT_CONFIG || window.AI_CONTEXT_POLICY || Object.freeze({
default: 384,
allowed: [128, 256, 384, 512],
scope: "workspace",
});
function normalizeModels(selection = null) {
if (MODEL_CONFIG && typeof MODEL_CONFIG.normalizeSelection === 'function') {
return MODEL_CONFIG.normalizeSelection(selection);
}
return {
kronos: Boolean(selection?.kronos),
timesfm: Boolean(selection?.timesfm),
chronos: Boolean(selection?.chronos),
};
}
function getModelSignature(selection = null) {
if (MODEL_CONFIG && typeof MODEL_CONFIG.signature === 'function') {
return MODEL_CONFIG.signature(selection);
}
const normalized = normalizeModels(selection);
return Object.entries(normalized)
.filter(([, enabled]) => enabled)
.map(([modelKey]) => modelKey)
.join('+') || 'none';
}
function normalizeContextLength(contextLength, fallback = AI_CONTEXT_POLICY.default || 384) {
const numericValue = Number(contextLength);
if (Number.isFinite(numericValue) && AI_CONTEXT_POLICY.allowed.includes(numericValue)) {
return numericValue;
}
return fallback;
}
function normalizeHorizon(value) {
const numericValue = Number(value);
return Number.isFinite(numericValue) && numericValue > 0
? numericValue
: null;
}
function buildAnalysisRequestContext(requestMeta = {}, pane = null, payload = null) {
const workspaceContextLength = typeof window.getWorkspaceForecastContextLength === 'function'
? window.getWorkspaceForecastContextLength()
: (window.Workspace?.forecastSettings?.contextLength ?? AI_CONTEXT_POLICY.default);
const models = normalizeModels(
requestMeta.models
|| payload?.model_selection?.requested
|| pane?.aiModels
|| null,
);
return {
symbol: requestMeta.symbol ?? payload?.symbol ?? pane?.symbol ?? null,
interval: requestMeta.interval ?? payload?.interval ?? pane?.interval ?? null,
horizon: normalizeHorizon(requestMeta.horizon ?? payload?.horizon ?? pane?.horizon),
models,
modelSignature: requestMeta.modelSignature ?? getModelSignature(models),
cacheVersion: ANALYSIS_CACHE_VERSION,
contextLength: normalizeContextLength(
requestMeta.contextLength
?? payload?.model_selection?.shared_context_length
?? workspaceContextLength,
AI_CONTEXT_POLICY.default || 384,
),
};
}
function contextsMatch(left, right, options = {}) {
if (!left || !right) {
return false;
}
const requireHorizon = options.requireHorizon !== false;
return (
left.symbol === right.symbol
&& left.interval === right.interval
&& left.modelSignature === right.modelSignature
&& left.cacheVersion === right.cacheVersion
&& left.contextLength === right.contextLength
&& (
!requireHorizon
|| left.horizon === right.horizon
)
);
}
function buildPaneAnalysisCacheKey(requestMeta = {}, pane = null, payload = null) {
const context = buildAnalysisRequestContext(requestMeta, pane, payload);
return [
context.symbol || 'unknown',
context.interval || 'unknown',
`h=${context.horizon ?? 'na'}`,
`m=${context.modelSignature}`,
`ctx=${context.contextLength}`,
`rv=${ANALYSIS_CACHE_VERSION}`,
].join('|');
}
function createPaneAnalysisCacheEntry(payload, requestMeta = {}, pane = null) {
return {
payload,
...buildAnalysisRequestContext(requestMeta, pane, payload),
};
}
function isPayloadCommitReady(payload, pane = null) {
if (!payload?.analysis) {
return false;
}
if (pane?.lastAnalysis?.payload === payload) {
if (pane.lastAnalysis.commitReady === true) {
return true;
}
if (pane.lastAnalysis.complete === true) {
return true;
}
}
const aggregation = payload?.analysis?.presentation?.aggregation || {};
const aiModels = payload?.analysis?.ai_models || {};
if (aggregation.commit_ready === true || aiModels.commit_ready === true) {
return true;
}
if (aggregation.complete === true || aiModels.complete === true) {
return true;
}
return false;
}
function matchesPanePayloadCurrentContext(
pane,
payload,
options = {},
) {
if (!pane || !payload?.analysis) {
return false;
}
const currentContext = buildAnalysisRequestContext({}, pane);
const requireComplete = options.requireComplete === true;
const allowTechnicalFallback = options.allowTechnicalFallback === true;
if (pane.lastAnalysis?.payload === payload) {
const storedContext = buildAnalysisRequestContext(pane.lastAnalysis, pane, payload);
return (
contextsMatch(storedContext, currentContext)
&& (!requireComplete || isPayloadCommitReady(payload, pane))
);
}
if (pane.lastTechnicalAnalysis?.payload === payload) {
return (
allowTechnicalFallback
&& pane.lastTechnicalAnalysis.symbol === currentContext.symbol
&& pane.lastTechnicalAnalysis.interval === currentContext.interval
);
}
const payloadContext = buildAnalysisRequestContext({}, pane, payload);
return (
contextsMatch(payloadContext, currentContext)
&& (!requireComplete || isPayloadCommitReady(payload, pane))
);
}
function resolvePaneDisplayPayload(pane, preferredPayload = null) {
const currentContext = buildAnalysisRequestContext({}, pane);
const displaySnapshotPayload = pane?.aiSession?.displaySnapshot?.payload || null;
if (matchesPanePayloadCurrentContext(pane, displaySnapshotPayload, { requireComplete: true })) {
return displaySnapshotPayload;
}
if (matchesPanePayloadCurrentContext(pane, preferredPayload)) {
return preferredPayload;
}
if (matchesPanePayloadCurrentContext(pane, pane?.lastAnalysis?.payload)) {
return pane.lastAnalysis.payload;
}
const cachedPayload = getCachedPaneAnalysisPayload(pane, currentContext);
if (matchesPanePayloadCurrentContext(pane, cachedPayload, { requireComplete: true })) {
return cachedPayload;
}
if (matchesPanePayloadCurrentContext(pane, pane?.lastTechnicalAnalysis?.payload, { allowTechnicalFallback: true })) {
return pane.lastTechnicalAnalysis.payload;
}
return null;
}
function getCachedPaneAnalysisPayload(pane, requestMeta = {}) {
const cacheKey = buildPaneAnalysisCacheKey(requestMeta, pane);
const cacheEntry = pane?.analysisPayloadCache?.[cacheKey];
if (!cacheEntry) {
return null;
}
const entry = cacheEntry?.payload
? cacheEntry
: createPaneAnalysisCacheEntry(cacheEntry, requestMeta, pane);
const requestedContext = buildAnalysisRequestContext(requestMeta, pane);
const cachedContext = buildAnalysisRequestContext(entry, pane, entry.payload);
return contextsMatch(cachedContext, requestedContext)
? entry.payload
: null;
}
window.AIForecastAnalysisRuntime = Object.freeze({
ANALYSIS_CACHE_VERSION,
normalizeModels,
getModelSignature,
normalizeContextLength,
buildAnalysisRequestContext,
buildPaneAnalysisCacheKey,
createPaneAnalysisCacheEntry,
getCachedPaneAnalysisPayload,
matchesPanePayloadCurrentContext,
resolvePaneDisplayPayload,
});
})();