Refactor UUID generation, remove unused logger and encryption utilities, and clean up request handling

- Updated `generateUUID` function for improved readability and performance.
- Deleted `logger.ts`, `other.ts`, `request.ts`, `storage.ts`, `tansParams.ts`, and `validate.ts` as they were no longer needed.
- Simplified TypeScript configuration by removing unnecessary paths and aliases.
- Enhanced Vite configuration for better project structure and maintainability.
This commit is contained in:
DEV_DSW
2026-04-17 15:38:08 +08:00
parent b1dea9a5c2
commit 79bea4f107
360 changed files with 14495 additions and 30856 deletions

View File

@@ -0,0 +1,121 @@
export enum IPC_EVENTS {
EXTERNAL_OPEN = 'external-open',
APP_SET_FRAMELESS = 'app:set-frameless',
APP_LOAD_PAGE = 'app:load-page',
TAB_CREATE = 'tab:create',
TAB_LIST = 'tab:list',
TAB_NAVIGATE = 'tab:navigate',
TAB_RELOAD = 'tab:reload',
TAB_BACK = 'tab:back',
TAB_FORWARD = 'tab:forward',
TAB_SWITCH = 'tab:switch',
TAB_CLOSE = 'tab:close',
LOG_TO_MAIN = 'log-to-main',
READ_FILE = 'read-file',
INVOKE = 'ipc:invoke',
INVOKE_ASYNC = 'ipc:invokeAsync',
APP_MINIMIZE = 'app:minimize',
APP_MAXIMIZE = 'app:maximize',
APP_QUIT = 'app:quit',
FILE_READ = 'file:read',
FILE_WRITE = 'file:write',
GET_WINDOW_ID = 'get-window-id',
CUSTOM_EVENT = 'custom:event',
TIME_UPDATE = 'time:update',
RENDERER_IS_READY = 'renderer-ready',
SHOW_CONTEXT_MENU = 'show-context-menu',
START_A_DIALOGUE = 'start-a-dialogue',
OPEN_WINDOW = 'open-window',
LOG_DEBUG = 'log-debug',
LOG_INFO = 'log-info',
LOG_WARN = 'log-warn',
LOG_ERROR = 'log-error',
CONFIG_UPDATED = 'config-updated',
SET_CONFIG = 'set-config',
GET_CONFIG = 'get-config',
UPDATE_CONFIG = 'update-config',
SET_THEME_MODE = 'set-theme-mode',
GET_THEME_MODE = 'get-theme-mode',
IS_DARK_THEME = 'is-dark-theme',
THEME_MODE_UPDATED = 'theme-mode-updated',
EXECUTE_SCRIPT = 'execute-script',
TASK_PROGRESS = 'task:progress',
TASK_STARTED = 'task:started',
TASK_COMPLETED = 'task:completed',
OPEN_CHANNEL = 'open-channel',
SCRIPT_LIST = 'script:list',
SCRIPT_GET = 'script:get',
SCRIPT_SAVE = 'script:save',
SCRIPT_DELETE = 'script:delete',
SCRIPT_TOGGLE = 'script:toggle',
SCRIPT_RUN = 'script:run',
SCRIPT_RECORD_START = 'script:record-start',
SCRIPT_RECORD_STOP = 'script:record-stop',
SCRIPT_CODEGEN = 'script:codegen',
GATEWAY_RPC = 'gateway:rpc',
GATEWAY_EVENT = 'gateway:event',
UPDATE_CHECK = 'update:check',
UPDATE_DOWNLOAD = 'update:download',
UPDATE_INSTALL = 'update:install',
UPDATE_VERSION = 'update:version',
UPDATE_STATUS_CHANGED = 'update:status-changed',
}
export const MAIN_WIN_SIZE = {
width: 1440,
height: 900,
minWidth: 1440,
minHeight: 900,
} as const;
export enum WINDOW_NAMES {
MAIN = 'main',
SETTING = 'setting',
DIALOG = 'dialog',
LOADING = 'loading',
}
export enum CONFIG_KEYS {
THEME_MODE = 'themeMode',
PRIMARY_COLOR = 'primaryColor',
LANGUAGE = 'language',
FONT_SIZE = 'fontSize',
MINIMIZE_TO_TRAY = 'minimizeToTray',
PROVIDER = 'provider',
DEFAULT_MODEL = 'defaultModel',
AUTO_CHECK_UPDATE = 'autoCheckUpdate',
AUTO_DOWNLOAD_UPDATE = 'autoDownloadUpdate',
SELECTED_CHANNELS = 'selectedChannels',
IMAGE_CACHE = 'imageCache',
TASK_LIST = 'taskList',
}
export enum MENU_IDS {
CONVERSATION_ITEM = 'conversation-item',
CONVERSATION_LIST = 'conversation-list',
MESSAGE_ITEM = 'message-item',
}
export enum CONVERSATION_ITEM_MENU_IDS {
PIN = 'pin',
RENAME = 'rename',
DEL = 'del',
}
export enum CONVERSATION_LIST_MENU_IDS {
NEW_CONVERSATION = 'newConversation',
SORT_BY = 'sortBy',
SORT_BY_CREATE_TIME = 'sortByCreateTime',
SORT_BY_UPDATE_TIME = 'sortByUpdateTime',
SORT_BY_NAME = 'sortByName',
SORT_BY_MODEL = 'sortByModel',
SORT_ASCENDING = 'sortAscending',
SORT_DESCENDING = 'sortDescending',
BATCH_OPERATIONS = 'batchOperations',
}
export enum MESSAGE_ITEM_MENU_IDS {
COPY = 'copy',
DELETE = 'delete',
SELECT = 'select',
}

View File

@@ -0,0 +1,355 @@
export const PROVIDER_TYPES = [
'anthropic',
'openai',
'google',
'openrouter',
'ark',
'moonshot',
'siliconflow',
'deepseek',
'minimax-portal',
'minimax-portal-cn',
'modelstudio',
'ollama',
'custom',
] as const;
export type ProviderType = (typeof PROVIDER_TYPES)[number];
export const BUILTIN_PROVIDER_TYPES = [
'anthropic',
'openai',
'google',
'openrouter',
'ark',
'moonshot',
'siliconflow',
'deepseek',
'minimax-portal',
'minimax-portal-cn',
'modelstudio',
'ollama',
] as const;
export const OLLAMA_PLACEHOLDER_API_KEY = 'ollama-local';
export interface ProviderConfig {
id: string;
name: string;
type: ProviderType;
baseUrl?: string;
apiProtocol?: 'openai-completions' | 'openai-responses' | 'anthropic-messages';
headers?: Record<string, string>;
model?: string;
fallbackModels?: string[];
fallbackProviderIds?: string[];
enabled: boolean;
createdAt: string;
updatedAt: string;
}
export interface ProviderWithKeyInfo extends ProviderConfig {
hasKey: boolean;
keyMasked: string | null;
}
export interface ProviderTypeInfo {
id: ProviderType;
name: string;
icon: string;
placeholder: string;
model?: string;
requiresApiKey: boolean;
defaultBaseUrl?: string;
showBaseUrl?: boolean;
showModelId?: boolean;
showModelIdInDevModeOnly?: boolean;
modelIdPlaceholder?: string;
defaultModelId?: string;
isOAuth?: boolean;
supportsApiKey?: boolean;
apiKeyUrl?: string;
docsUrl?: string;
docsUrlZh?: string;
codePlanPresetBaseUrl?: string;
codePlanPresetModelId?: string;
codePlanDocsUrl?: string;
hidden?: boolean;
}
export type ProviderAuthMode =
| 'api_key'
| 'oauth_device'
| 'oauth_browser'
| 'local';
export type ProviderVendorCategory =
| 'official'
| 'compatible'
| 'local'
| 'custom';
export interface ProviderVendorInfo extends ProviderTypeInfo {
category: ProviderVendorCategory;
envVar?: string;
supportedAuthModes: ProviderAuthMode[];
defaultAuthMode: ProviderAuthMode;
supportsMultipleAccounts: boolean;
}
export interface ProviderAccount {
id: string;
vendorId: ProviderType;
label: string;
authMode: ProviderAuthMode;
baseUrl?: string;
apiProtocol?: 'openai-completions' | 'openai-responses' | 'anthropic-messages';
headers?: Record<string, string>;
model?: string;
fallbackModels?: string[];
fallbackAccountIds?: string[];
enabled: boolean;
isDefault: boolean;
metadata?: {
region?: string;
email?: string;
resourceUrl?: string;
customModels?: string[];
};
createdAt: string;
updatedAt: string;
}
export const PROVIDER_TYPE_INFO: ProviderTypeInfo[] = [
{
id: 'anthropic',
name: 'Anthropic',
icon: 'A',
placeholder: 'sk-ant-api03-...',
model: 'Claude',
requiresApiKey: true,
docsUrl: 'https://platform.claude.com/docs/en/api/overview',
},
{
id: 'openai',
name: 'OpenAI',
icon: 'O',
placeholder: 'sk-proj-...',
model: 'GPT',
requiresApiKey: true,
isOAuth: true,
supportsApiKey: true,
defaultModelId: 'gpt-5.4',
showModelId: true,
showModelIdInDevModeOnly: true,
modelIdPlaceholder: 'gpt-5.4',
apiKeyUrl: 'https://platform.openai.com/api-keys',
},
{
id: 'google',
name: 'Google',
icon: 'G',
placeholder: 'AIza...',
model: 'Gemini',
requiresApiKey: true,
isOAuth: true,
supportsApiKey: true,
defaultModelId: 'gemini-3-pro-preview',
showModelId: true,
showModelIdInDevModeOnly: true,
modelIdPlaceholder: 'gemini-3-pro-preview',
apiKeyUrl: 'https://aistudio.google.com/app/apikey',
},
{
id: 'openrouter',
name: 'OpenRouter',
icon: 'R',
placeholder: 'sk-or-v1-...',
model: 'Multi-Model',
requiresApiKey: true,
showModelId: true,
modelIdPlaceholder: 'openai/gpt-5.4',
defaultModelId: 'openai/gpt-5.4',
docsUrl: 'https://openrouter.ai/models',
},
{
id: 'minimax-portal-cn',
name: 'MiniMax (CN)',
icon: 'M',
placeholder: 'sk-...',
model: 'MiniMax',
requiresApiKey: false,
isOAuth: true,
supportsApiKey: true,
defaultModelId: 'MiniMax-M2.7',
showModelId: true,
showModelIdInDevModeOnly: true,
modelIdPlaceholder: 'MiniMax-M2.7',
apiKeyUrl: 'https://platform.minimaxi.com/',
},
{
id: 'moonshot',
name: 'Moonshot (CN)',
icon: 'K',
placeholder: 'sk-...',
model: 'Kimi',
requiresApiKey: true,
defaultBaseUrl: 'https://api.moonshot.cn/v1',
defaultModelId: 'kimi-k2.5',
docsUrl: 'https://platform.moonshot.cn/',
},
{
id: 'siliconflow',
name: 'SiliconFlow (CN)',
icon: 'S',
placeholder: 'sk-...',
model: 'Multi-Model',
requiresApiKey: true,
defaultBaseUrl: 'https://api.siliconflow.cn/v1',
showModelId: true,
showModelIdInDevModeOnly: true,
modelIdPlaceholder: 'deepseek-ai/DeepSeek-V3',
defaultModelId: 'deepseek-ai/DeepSeek-V3',
docsUrl: 'https://docs.siliconflow.cn/cn/userguide/introduction',
},
{
id: 'deepseek',
name: 'DeepSeek',
icon: 'D',
placeholder: 'sk-...',
model: 'DeepSeek',
requiresApiKey: true,
defaultBaseUrl: 'https://api.deepseek.com/v1',
showModelId: true,
modelIdPlaceholder: 'deepseek-chat',
defaultModelId: 'deepseek-chat',
apiKeyUrl: 'https://platform.deepseek.com/api_keys',
docsUrl: 'https://api-docs.deepseek.com/',
},
{
id: 'minimax-portal',
name: 'MiniMax (Global)',
icon: 'M',
placeholder: 'sk-...',
model: 'MiniMax',
requiresApiKey: false,
isOAuth: true,
supportsApiKey: true,
defaultModelId: 'MiniMax-M2.7',
showModelId: true,
showModelIdInDevModeOnly: true,
modelIdPlaceholder: 'MiniMax-M2.7',
apiKeyUrl: 'https://platform.minimax.io',
},
{
id: 'modelstudio',
name: 'Model Studio',
icon: 'Q',
placeholder: 'sk-...',
model: 'Qwen',
requiresApiKey: true,
defaultBaseUrl: 'https://coding.dashscope.aliyuncs.com/v1',
showBaseUrl: true,
defaultModelId: 'qwen3.5-plus',
showModelId: true,
showModelIdInDevModeOnly: true,
modelIdPlaceholder: 'qwen3.5-plus',
apiKeyUrl: 'https://bailian.console.aliyun.com/',
hidden: true,
},
{
id: 'ark',
name: 'ByteDance Ark',
icon: 'B',
placeholder: 'your-ark-api-key',
model: 'Doubao',
requiresApiKey: true,
defaultBaseUrl: 'https://ark.cn-beijing.volces.com/api/v3',
showBaseUrl: true,
showModelId: true,
modelIdPlaceholder: 'ep-20260228000000-xxxxx',
docsUrl: 'https://www.volcengine.com/',
codePlanPresetBaseUrl: 'https://ark.cn-beijing.volces.com/api/coding/v3',
codePlanPresetModelId: 'ark-code-latest',
codePlanDocsUrl: 'https://www.volcengine.com/docs/82379/1928261?lang=zh',
},
{
id: 'ollama',
name: 'Ollama',
icon: 'L',
placeholder: 'Not required',
requiresApiKey: false,
defaultBaseUrl: 'http://localhost:11434/v1',
showBaseUrl: true,
showModelId: true,
modelIdPlaceholder: 'qwen3:latest',
},
{
id: 'custom',
name: 'Custom',
icon: 'C',
placeholder: 'API key...',
requiresApiKey: true,
showBaseUrl: true,
showModelId: true,
modelIdPlaceholder: 'your-provider/model-id',
docsUrl: 'https://icnnp7d0dymg.feishu.cn/wiki/BmiLwGBcEiloZDkdYnGc8RWnn6d#Ee1ldfvKJoVGvfxc32mcILwenth',
docsUrlZh: 'https://icnnp7d0dymg.feishu.cn/wiki/BmiLwGBcEiloZDkdYnGc8RWnn6d#IWQCdfe5fobGU3xf3UGcgbLynGh',
},
];
export function getProviderIconUrl(_type: ProviderType | string): string | undefined {
return undefined;
}
export function shouldInvertInDark(_type: ProviderType | string): boolean {
return true;
}
export const SETUP_PROVIDERS = PROVIDER_TYPE_INFO;
export function getProviderTypeInfo(type: ProviderType): ProviderTypeInfo | undefined {
return PROVIDER_TYPE_INFO.find((providerType) => providerType.id === type);
}
export function getProviderDocsUrl(
provider: Pick<ProviderTypeInfo, 'docsUrl' | 'docsUrlZh'> | undefined,
language: string,
): string | undefined {
if (!provider?.docsUrl) {
return undefined;
}
if (language.startsWith('zh') && provider.docsUrlZh) {
return provider.docsUrlZh;
}
return provider.docsUrl;
}
export function shouldShowProviderModelId(
provider: Pick<ProviderTypeInfo, 'showModelId' | 'showModelIdInDevModeOnly'> | undefined,
devModeUnlocked: boolean,
): boolean {
if (!provider?.showModelId) return false;
if (provider.showModelIdInDevModeOnly && !devModeUnlocked) return false;
return true;
}
export function resolveProviderModelForSave(
provider: Pick<ProviderTypeInfo, 'defaultModelId' | 'showModelId' | 'showModelIdInDevModeOnly'> | undefined,
modelId: string,
devModeUnlocked: boolean,
): string | undefined {
if (!shouldShowProviderModelId(provider, devModeUnlocked)) {
return undefined;
}
const trimmedModelId = modelId.trim();
return trimmedModelId || provider?.defaultModelId || undefined;
}
export function resolveProviderApiKeyForSave(type: ProviderType | string, apiKey: string): string | undefined {
const trimmed = apiKey.trim();
if (type === 'ollama') {
return trimmed || OLLAMA_PLACEHOLDER_API_KEY;
}
return trimmed || undefined;
}

View File

@@ -0,0 +1,53 @@
export interface ScriptLastRun {
time: string;
success: boolean;
error?: string;
}
export interface AutomationScript {
id: string;
name: string;
description: string;
filename: string;
enabled: boolean;
channel: string;
createdAt: string;
updatedAt: string;
code?: string;
lastRun?: ScriptLastRun;
}
export interface ScriptSaveInput {
id?: string;
name: string;
description: string;
code: string;
channel: string;
enabled: boolean;
}
export interface ScriptExecutionResult {
success: boolean;
exitCode: number | null;
stdoutTail: string;
stderrTail: string;
error?: string;
}
export type ScriptRecordingStatus = 'idle' | 'recording' | 'stopped';
export interface ScriptMetaItem {
id: string;
name: string;
description: string;
filename: string;
enabled: boolean;
channel: string;
createdAt: string;
updatedAt: string;
lastRun?: ScriptLastRun;
}
export interface ScriptsMeta {
scripts: ScriptMetaItem[];
}

View File

@@ -0,0 +1,40 @@
export type SubTaskStatus = 'pending' | 'running' | 'success' | 'failed';
export interface SubTask {
id: string;
taskId: string;
scriptId: string;
name: string;
status: SubTaskStatus;
progress: number;
message: string;
stdoutTail: string;
stderrTail: string;
error?: string;
startedAt: string;
completedAt?: string;
}
export type TaskStatus = 'pending' | 'running' | 'success' | 'partial_failed' | 'failed';
export interface Task {
id: string;
title: string;
operation: 'open' | 'close';
roomType: string;
dateRange: [string, string];
status: TaskStatus;
subTasks: SubTask[];
roomList: any[];
createdAt: string;
updatedAt: string;
}
export interface TaskProgressPayload {
taskId: string;
subTaskId: string;
progress?: number;
message?: string;
stdoutTail?: string;
stderrTail?: string;
}

View File

@@ -0,0 +1,38 @@
import type { Task } from './task-types';
import { CONFIG_KEYS, WINDOW_NAMES } from './constants';
export type ThemeMode = 'dark' | 'light' | 'system';
export type WindowNames = `${WINDOW_NAMES}`;
export type ConfigKeys = `${CONFIG_KEYS}`;
export interface IConfig {
[CONFIG_KEYS.THEME_MODE]: ThemeMode;
[CONFIG_KEYS.PRIMARY_COLOR]: string;
[CONFIG_KEYS.LANGUAGE]: 'zh' | 'en';
[CONFIG_KEYS.FONT_SIZE]: number;
[CONFIG_KEYS.MINIMIZE_TO_TRAY]: boolean;
[CONFIG_KEYS.PROVIDER]?: string;
[CONFIG_KEYS.DEFAULT_MODEL]?: string | null;
[CONFIG_KEYS.AUTO_CHECK_UPDATE]?: boolean;
[CONFIG_KEYS.AUTO_DOWNLOAD_UPDATE]?: boolean;
[CONFIG_KEYS.SELECTED_CHANNELS]: Array<{ id: string; channelName: string; channelUrl: string }>;
[CONFIG_KEYS.IMAGE_CACHE]: Array<[string, any]>;
[CONFIG_KEYS.TASK_LIST]?: Task[];
}
export interface Provider {
id: number;
name: string;
visible?: boolean;
title?: string;
type?: 'OpenAI';
openAISetting?: string;
createdAt: number;
updatedAt: number;
models: string[];
}
export interface OpenAISetting {
baseURL?: string;
apiKey?: string;
}

View File

@@ -0,0 +1,33 @@
export function debounce<T extends (...args: any[]) => any>(
fn: T,
delay: number,
): (...args: Parameters<T>) => void {
let timer: NodeJS.Timeout | null = null;
return function debounced(this: unknown, ...args: Parameters<T>) {
if (timer) {
clearTimeout(timer);
}
timer = setTimeout(() => {
fn.apply(this, args);
}, delay);
};
}
export function cloneDeep<T>(obj: T): T {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (Array.isArray(obj)) {
return obj.map((item) => cloneDeep(item)) as T;
}
const clone = Object.assign({}, obj);
for (const key in clone) {
if (Object.prototype.hasOwnProperty.call(clone, key)) {
clone[key] = cloneDeep(clone[key]);
}
}
return clone;
}