189 lines
4.6 KiB
TypeScript
189 lines
4.6 KiB
TypeScript
type IdleCallbackHandle = number;
|
|
|
|
type IdleCallbackOptions = {
|
|
timeout?: number;
|
|
};
|
|
|
|
type WindowWithIdleCallback = Window & {
|
|
requestIdleCallback?: (
|
|
callback: () => void,
|
|
options?: IdleCallbackOptions,
|
|
) => IdleCallbackHandle;
|
|
};
|
|
|
|
type NavigatorWithConnection = Navigator & {
|
|
connection?: {
|
|
effectiveType?: string;
|
|
saveData?: boolean;
|
|
};
|
|
deviceMemory?: number;
|
|
};
|
|
|
|
const prefetchedGroups = new Set<string>();
|
|
const scheduledGroups = new Set<string>();
|
|
|
|
type PrefetchTask = {
|
|
key: string;
|
|
load: () => Promise<unknown>;
|
|
};
|
|
|
|
const corePrefetchTasks: PrefetchTask[] = [
|
|
{ key: 'system-user', load: () => import('#/views/_core/user/index.vue') },
|
|
{ key: 'system-menu', load: () => import('#/views/_core/menu/index.vue') },
|
|
{ key: 'system-role', load: () => import('#/views/_core/role/index.vue') },
|
|
];
|
|
|
|
const aiPrefetchTasks = {
|
|
agent: {
|
|
key: 'ai-agent',
|
|
load: () => import('#/views/ai-platform/agent/index.vue'),
|
|
},
|
|
agentChat: {
|
|
key: 'agent-chat',
|
|
load: () => import('#/views/_core/agent-chat/index.vue'),
|
|
},
|
|
aiChatPanel: {
|
|
key: 'ai-chat-panel',
|
|
load: () => import('#/components/ai-chat-panel/AiChatPanel.vue'),
|
|
},
|
|
knowledge: {
|
|
key: 'ai-knowledge',
|
|
load: () => import('#/views/ai-platform/knowledge/index.vue'),
|
|
},
|
|
model: {
|
|
key: 'ai-model',
|
|
load: () => import('#/views/ai-platform/model/index.vue'),
|
|
},
|
|
workflow: {
|
|
key: 'ai-workflow',
|
|
load: () => import('#/views/ai-platform/workflow/index.vue'),
|
|
},
|
|
workflowRuns: {
|
|
key: 'ai-workflow-runs',
|
|
load: () => import('#/views/ai-platform/workflow-runs/index.vue'),
|
|
},
|
|
} as const;
|
|
|
|
function scheduleIdle(callback: () => void) {
|
|
const browserWindow = window as WindowWithIdleCallback;
|
|
|
|
if (browserWindow.requestIdleCallback) {
|
|
browserWindow.requestIdleCallback(callback, { timeout: 8000 });
|
|
return;
|
|
}
|
|
|
|
window.setTimeout(callback, 8000);
|
|
}
|
|
|
|
function canPrefetch() {
|
|
if (typeof document !== 'undefined' && document.visibilityState !== 'visible') {
|
|
return false;
|
|
}
|
|
|
|
const connection = (navigator as NavigatorWithConnection).connection;
|
|
if (connection?.saveData) {
|
|
return false;
|
|
}
|
|
|
|
const deviceMemory = (navigator as NavigatorWithConnection).deviceMemory;
|
|
if (deviceMemory && deviceMemory < 4) {
|
|
return false;
|
|
}
|
|
|
|
return !/(^|-)2g$/.test(connection?.effectiveType || '');
|
|
}
|
|
|
|
async function runTasksSequentially(tasks: PrefetchTask[]) {
|
|
for (const task of tasks) {
|
|
if (!canPrefetch()) {
|
|
return;
|
|
}
|
|
if (prefetchedGroups.has(task.key)) {
|
|
continue;
|
|
}
|
|
prefetchedGroups.add(task.key);
|
|
await task.load().catch(() => undefined);
|
|
await new Promise((resolve) => window.setTimeout(resolve, 300));
|
|
}
|
|
}
|
|
|
|
function delayedPrefetch(groupKey: string, tasks: PrefetchTask[], delay: number) {
|
|
if (!tasks.length || typeof window === 'undefined') {
|
|
return;
|
|
}
|
|
if (scheduledGroups.has(groupKey)) {
|
|
return;
|
|
}
|
|
scheduledGroups.add(groupKey);
|
|
|
|
window.setTimeout(() => {
|
|
scheduleIdle(() => {
|
|
void runTasksSequentially(tasks);
|
|
});
|
|
}, delay);
|
|
}
|
|
|
|
function isSystemRoute(path: string) {
|
|
return path.startsWith('/system/') || path.startsWith('/message/');
|
|
}
|
|
|
|
function isAiPlatformRoute(path: string) {
|
|
return path.startsWith('/ai-platform/');
|
|
}
|
|
|
|
function isAgentChatRoute(path: string) {
|
|
return path.startsWith('/agent-chat/');
|
|
}
|
|
|
|
function getAiRoutePrefetchTasks(path: string): PrefetchTask[] {
|
|
if (path.startsWith('/ai-platform/agent')) {
|
|
return [aiPrefetchTasks.workflow, aiPrefetchTasks.model];
|
|
}
|
|
if (path.startsWith('/ai-platform/workflow-runs')) {
|
|
return [aiPrefetchTasks.workflow];
|
|
}
|
|
if (path.startsWith('/ai-platform/workflow')) {
|
|
return [aiPrefetchTasks.workflowRuns, aiPrefetchTasks.agent];
|
|
}
|
|
if (path.startsWith('/ai-platform/model')) {
|
|
return [aiPrefetchTasks.agent, aiPrefetchTasks.workflow];
|
|
}
|
|
if (path.startsWith('/ai-platform/knowledge')) {
|
|
return [aiPrefetchTasks.agent];
|
|
}
|
|
return [aiPrefetchTasks.agent, aiPrefetchTasks.workflow];
|
|
}
|
|
|
|
function prefetchAiPlatformPages(currentPath = '') {
|
|
if (typeof window === 'undefined') {
|
|
return;
|
|
}
|
|
|
|
if (isSystemRoute(currentPath)) {
|
|
delayedPrefetch(`core:${currentPath}`, corePrefetchTasks, 18_000);
|
|
return;
|
|
}
|
|
|
|
if (isAgentChatRoute(currentPath)) {
|
|
delayedPrefetch(
|
|
`agent-chat:${currentPath}`,
|
|
[aiPrefetchTasks.agentChat, aiPrefetchTasks.aiChatPanel],
|
|
14_000,
|
|
);
|
|
return;
|
|
}
|
|
|
|
if (isAiPlatformRoute(currentPath)) {
|
|
delayedPrefetch(
|
|
`ai:${currentPath}`,
|
|
getAiRoutePrefetchTasks(currentPath),
|
|
14_000,
|
|
);
|
|
return;
|
|
}
|
|
|
|
delayedPrefetch('core:home', corePrefetchTasks, 22_000);
|
|
}
|
|
|
|
export { prefetchAiPlatformPages };
|