feat: TypeScript + Electron v2 重构 - 纯桌面版

- 全面迁移到 TypeScript,严格类型定义
- 放弃 Web 版,专注 Electron 桌面应用
- 主进程模块化:main.ts, preload.ts, menu.ts, tray.ts, ipc.ts, utils.ts
- 渲染进程完整迁移所有功能组件
- 删除 PWA 相关文件 (sw.js, manifest.json)
- 删除 Web 版降级逻辑
- 保留所有核心功能:流式对话、多模型、Think推理、多模态、RAG知识库、Agent预设、历史管理
- 保留 Windows 11 Fluent Design 暗色主题样式
This commit is contained in:
thzxx
2026-04-06 03:04:20 +08:00
parent 0924497cd6
commit 7ca0e33d77
33 changed files with 7265 additions and 15 deletions
+250
View File
@@ -0,0 +1,250 @@
// ── Ollama API 类型 ──
export interface OllamaMessage {
role: 'user' | 'assistant' | 'system';
content: string;
images?: string[];
thinking?: string;
reasoning_content?: string;
}
export interface OllamaChatParams {
model: string;
messages: OllamaMessage[];
stream?: boolean;
think?: boolean;
system?: string;
keep_alive?: number | string;
options?: {
num_ctx?: number;
temperature?: number;
[key: string]: unknown;
};
}
export interface OllamaStreamChunk {
model?: string;
message?: {
role: string;
content?: string;
thinking?: string;
reasoning_content?: string;
};
done?: boolean;
eval_count?: number;
total_duration?: number;
}
export interface OllamaModelInfo {
name: string;
size?: number;
digest?: string;
modified_at?: string;
}
export interface OllamaModelDetail {
capabilities?: string[];
[key: string]: unknown;
}
export interface OllamaVersionResponse {
version: string;
}
export interface OllamaModelsResponse {
models: OllamaModelInfo[];
}
export interface OllamaPsResponse {
models?: Array<{
name: string;
size_vram?: number;
[key: string]: unknown;
}>;
}
export interface OllamaEmbedResponse {
embedding?: number[];
embeddings?: number[][];
}
// ── 会话类型 ──
export interface ChatFile {
name: string;
language?: string;
size?: number;
}
export interface FileContent {
language: string;
content: string;
}
export interface RagSource {
filename: string;
score: number;
text: string;
}
export interface ChatMessage {
role: 'user' | 'assistant';
content: string;
timestamp: number;
model?: string;
think?: string;
eval_count?: number;
total_duration?: number;
images?: string[];
files?: ChatFile[];
_fileContents?: FileContent[];
ragSources?: RagSource[];
stopped?: boolean;
}
export interface ChatSession {
id: string;
title: string;
model: string;
messages: ChatMessage[];
createdAt: number;
updatedAt: number;
}
// ── 预设类型 ──
export interface Preset {
id: string;
name: string;
icon: string;
systemPrompt: string;
temperature: number;
numCtx: number;
think: boolean;
builtIn?: boolean;
createdAt: number;
updatedAt: number;
}
// ── 知识库类型 ──
export interface VectorCollection {
id: string;
name: string;
embeddingModel: string;
docCount: number;
chunkCount: number;
createdAt: number;
updatedAt: number;
}
export interface VectorItem {
id: string;
collectionId: string;
docId: string;
filename: string;
chunkIndex: number;
text: string;
charCount: number;
embedding: number[];
}
export interface SearchResult extends VectorItem {
score: number;
}
export interface DocInfo {
docId: string;
filename: string;
chunkCount: number;
}
// ── 桌面 Bridge 类型 ──
export interface MetonaDesktopAPI {
isDesktop: boolean;
info: () => Promise<AppInfo>;
dialog: {
openFile: (options?: FileFilterOptions) => Promise<string[] | null>;
saveFile: (options?: SaveFileOptions) => Promise<string | null>;
};
fs: {
readFile: (filePath: string) => Promise<{ success: boolean; content?: string; name?: string; error?: string }>;
writeFile: (filePath: string, content: string) => Promise<{ success: boolean; error?: string }>;
};
notify: (title: string, body: string) => void;
window: {
minimize: () => void;
maximize: () => void;
close: () => void;
};
openExternal: (url: string) => void;
onMenuAction: (callback: (action: string) => void) => void;
onTrayAction: (callback: (action: string) => void) => void;
removeAllListeners: (channel: string) => void;
}
export interface AppInfo {
version: string;
platform: string;
arch: string;
electronVersion: string;
userDataPath: string;
}
export interface FileFilterOptions {
filters?: Array<{ name: string; extensions: string[] }>;
}
export interface SaveFileOptions {
defaultPath?: string;
filters?: Array<{ name: string; extensions: string[] }>;
}
// ── 桌面 Bridge 接口 ──
export interface DesktopBridge {
isDesktop: boolean;
getInfo: () => Promise<{ platform: string; version: string; arch?: string; electronVersion?: string; userDataPath?: string }>;
openFile: (filters?: Array<{ name: string; extensions: string[] }>) => Promise<string[] | null>;
saveFile: (options?: SaveFileOptions) => Promise<string | null>;
readFile: (filePath: string) => Promise<{ success: boolean; content?: string; name?: string; error?: string }>;
writeFile: (filePath: string, content: string) => Promise<{ success: boolean; error?: string }>;
notify: (title: string, body: string) => void;
minimize: () => void;
maximize: () => void;
close: () => void;
openExternal: (url: string) => void;
onMenuAction: (callback: (action: string) => void) => void;
onTrayAction: (callback: (action: string) => void) => void;
off: (channel: string) => void;
}
// ── State Keys ──
export type StateKey =
| 'db'
| 'api'
| 'currentSession'
| 'isStreaming'
| 'isHistoryView'
| 'pendingImages'
| 'abortController'
| 'systemPrompt'
| 'systemPromptEnabled'
| 'numCtx'
| 'historyPage'
| 'historySearchQuery'
| 'temperature'
| 'thinkEnabled'
| 'presets'
| 'activePresetId';
// ── Window global 声明 ──
declare global {
interface Window {
metonaDesktop?: MetonaDesktopAPI;
__metonaBridge?: DesktopBridge;
}
}