markpdfdown 0.1.8 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/main/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import sharp from "sharp";
|
|
|
12
12
|
import fs$1 from "fs/promises";
|
|
13
13
|
import { v4 } from "uuid";
|
|
14
14
|
import { createRequire } from "module";
|
|
15
|
+
import pkg$1 from "electron-updater";
|
|
15
16
|
import __cjs_mod__ from "node:module";
|
|
16
17
|
const __filename = import.meta.filename;
|
|
17
18
|
const __dirname = import.meta.dirname;
|
|
@@ -248,6 +249,16 @@ var PageStatus = /* @__PURE__ */ ((PageStatus2) => {
|
|
|
248
249
|
PageStatus2[PageStatus2["RETRYING"] = 3] = "RETRYING";
|
|
249
250
|
return PageStatus2;
|
|
250
251
|
})(PageStatus || {});
|
|
252
|
+
var UpdateStatus = /* @__PURE__ */ ((UpdateStatus2) => {
|
|
253
|
+
UpdateStatus2["IDLE"] = "idle";
|
|
254
|
+
UpdateStatus2["CHECKING"] = "checking";
|
|
255
|
+
UpdateStatus2["AVAILABLE"] = "available";
|
|
256
|
+
UpdateStatus2["NOT_AVAILABLE"] = "not_available";
|
|
257
|
+
UpdateStatus2["DOWNLOADING"] = "downloading";
|
|
258
|
+
UpdateStatus2["DOWNLOADED"] = "downloaded";
|
|
259
|
+
UpdateStatus2["ERROR"] = "error";
|
|
260
|
+
return UpdateStatus2;
|
|
261
|
+
})(UpdateStatus || {});
|
|
251
262
|
var TaskEventType = /* @__PURE__ */ ((TaskEventType2) => {
|
|
252
263
|
TaskEventType2["TASK_UPDATED"] = "task:updated";
|
|
253
264
|
TaskEventType2["TASK_STATUS_CHANGED"] = "task:status_changed";
|
|
@@ -2439,6 +2450,151 @@ class WorkerOrchestrator {
|
|
|
2439
2450
|
}
|
|
2440
2451
|
}
|
|
2441
2452
|
const workerOrchestrator = new WorkerOrchestrator();
|
|
2453
|
+
const providerPresets = [
|
|
2454
|
+
{
|
|
2455
|
+
name: "OpenAI",
|
|
2456
|
+
type: "openai-responses",
|
|
2457
|
+
apiBase: "https://api.openai.com/v1",
|
|
2458
|
+
modelListApi: "/models",
|
|
2459
|
+
modelNameField: "id",
|
|
2460
|
+
modelIdField: "id",
|
|
2461
|
+
defaultModels: []
|
|
2462
|
+
},
|
|
2463
|
+
{
|
|
2464
|
+
name: "Anthropic",
|
|
2465
|
+
type: "anthropic",
|
|
2466
|
+
apiBase: "https://api.anthropic.com/v1",
|
|
2467
|
+
modelListApi: "/models",
|
|
2468
|
+
modelNameField: "display_name",
|
|
2469
|
+
modelIdField: "id",
|
|
2470
|
+
capabilityField: "input_modalities",
|
|
2471
|
+
capabilityFilter: "image",
|
|
2472
|
+
defaultModels: []
|
|
2473
|
+
},
|
|
2474
|
+
{
|
|
2475
|
+
name: "Gemini",
|
|
2476
|
+
type: "gemini",
|
|
2477
|
+
apiBase: "https://generativelanguage.googleapis.com/v1beta",
|
|
2478
|
+
modelListApi: "/models",
|
|
2479
|
+
modelNameField: "displayName",
|
|
2480
|
+
modelIdField: "name",
|
|
2481
|
+
defaultModels: []
|
|
2482
|
+
},
|
|
2483
|
+
{
|
|
2484
|
+
name: "ZenMux",
|
|
2485
|
+
type: "anthropic",
|
|
2486
|
+
apiBase: "https://zenmux.ai/api/anthropic/v1",
|
|
2487
|
+
modelListApi: "/models",
|
|
2488
|
+
modelNameField: "display_name",
|
|
2489
|
+
modelIdField: "id",
|
|
2490
|
+
capabilityField: "input_modalities",
|
|
2491
|
+
capabilityFilter: "image",
|
|
2492
|
+
defaultModels: []
|
|
2493
|
+
},
|
|
2494
|
+
{
|
|
2495
|
+
name: "OpenRouter",
|
|
2496
|
+
type: "openai",
|
|
2497
|
+
apiBase: "https://openrouter.ai/api/v1",
|
|
2498
|
+
modelListApi: "/models",
|
|
2499
|
+
modelNameField: "name",
|
|
2500
|
+
modelIdField: "id",
|
|
2501
|
+
capabilityField: "architecture.input_modalities",
|
|
2502
|
+
capabilityFilter: "image",
|
|
2503
|
+
defaultModels: []
|
|
2504
|
+
},
|
|
2505
|
+
{
|
|
2506
|
+
name: "SiliconFlow",
|
|
2507
|
+
type: "openai",
|
|
2508
|
+
apiBase: "https://api.siliconflow.cn/v1",
|
|
2509
|
+
modelListApi: "/models",
|
|
2510
|
+
modelNameField: "id",
|
|
2511
|
+
modelIdField: "id",
|
|
2512
|
+
defaultModels: []
|
|
2513
|
+
},
|
|
2514
|
+
{
|
|
2515
|
+
name: "Ollama",
|
|
2516
|
+
type: "ollama",
|
|
2517
|
+
apiBase: "http://localhost:11434/api",
|
|
2518
|
+
modelListApi: "/tags",
|
|
2519
|
+
modelNameField: "name",
|
|
2520
|
+
modelIdField: "name",
|
|
2521
|
+
defaultModels: []
|
|
2522
|
+
}
|
|
2523
|
+
];
|
|
2524
|
+
function findProviderPreset(type, name) {
|
|
2525
|
+
return providerPresets.find(
|
|
2526
|
+
(preset) => preset.type === type && preset.name === name
|
|
2527
|
+
);
|
|
2528
|
+
}
|
|
2529
|
+
function getProviderPresetKey(type, name) {
|
|
2530
|
+
return `${type}:${name}`;
|
|
2531
|
+
}
|
|
2532
|
+
class PresetProviderService {
|
|
2533
|
+
static instance;
|
|
2534
|
+
initialized = false;
|
|
2535
|
+
constructor() {
|
|
2536
|
+
}
|
|
2537
|
+
static getInstance() {
|
|
2538
|
+
if (!PresetProviderService.instance) {
|
|
2539
|
+
PresetProviderService.instance = new PresetProviderService();
|
|
2540
|
+
}
|
|
2541
|
+
return PresetProviderService.instance;
|
|
2542
|
+
}
|
|
2543
|
+
/**
|
|
2544
|
+
* 初始化预设供应商
|
|
2545
|
+
* 使用 type + name 去重,若不存在则插入,status = -1(禁用)
|
|
2546
|
+
*/
|
|
2547
|
+
async initialize() {
|
|
2548
|
+
if (this.initialized) {
|
|
2549
|
+
console.log("[PresetProviderService] Already initialized, skipping...");
|
|
2550
|
+
return;
|
|
2551
|
+
}
|
|
2552
|
+
try {
|
|
2553
|
+
console.log("[PresetProviderService] Starting preset provider injection...");
|
|
2554
|
+
const existingProviders = await providerRepository.findAllIncludeDisabled();
|
|
2555
|
+
const existingKeys = new Set(
|
|
2556
|
+
existingProviders.map((p) => getProviderPresetKey(p.type, p.name))
|
|
2557
|
+
);
|
|
2558
|
+
let insertedCount = 0;
|
|
2559
|
+
for (const preset of providerPresets) {
|
|
2560
|
+
const key = getProviderPresetKey(preset.type, preset.name);
|
|
2561
|
+
if (!existingKeys.has(key)) {
|
|
2562
|
+
await providerRepository.create({
|
|
2563
|
+
name: preset.name,
|
|
2564
|
+
type: preset.type,
|
|
2565
|
+
api_key: "",
|
|
2566
|
+
base_url: preset.apiBase,
|
|
2567
|
+
suffix: "",
|
|
2568
|
+
status: -1
|
|
2569
|
+
// 默认禁用
|
|
2570
|
+
});
|
|
2571
|
+
console.log(
|
|
2572
|
+
`[PresetProviderService] Inserted preset provider: ${preset.name} (${preset.type})`
|
|
2573
|
+
);
|
|
2574
|
+
insertedCount++;
|
|
2575
|
+
} else {
|
|
2576
|
+
console.log(
|
|
2577
|
+
`[PresetProviderService] Preset provider already exists: ${preset.name} (${preset.type})`
|
|
2578
|
+
);
|
|
2579
|
+
}
|
|
2580
|
+
}
|
|
2581
|
+
console.log(
|
|
2582
|
+
`[PresetProviderService] Preset provider injection completed. Inserted: ${insertedCount}`
|
|
2583
|
+
);
|
|
2584
|
+
this.initialized = true;
|
|
2585
|
+
} catch (error) {
|
|
2586
|
+
console.error("[PresetProviderService] Failed to initialize preset providers:", error);
|
|
2587
|
+
throw error;
|
|
2588
|
+
}
|
|
2589
|
+
}
|
|
2590
|
+
/**
|
|
2591
|
+
* 重置初始化状态(主要用于测试)
|
|
2592
|
+
*/
|
|
2593
|
+
reset() {
|
|
2594
|
+
this.initialized = false;
|
|
2595
|
+
}
|
|
2596
|
+
}
|
|
2597
|
+
const presetProviderService = PresetProviderService.getInstance();
|
|
2442
2598
|
const IPC_CHANNELS = {
|
|
2443
2599
|
// Provider channels
|
|
2444
2600
|
PROVIDER: {
|
|
@@ -2447,7 +2603,9 @@ const IPC_CHANNELS = {
|
|
|
2447
2603
|
CREATE: "provider:create",
|
|
2448
2604
|
UPDATE: "provider:update",
|
|
2449
2605
|
DELETE: "provider:delete",
|
|
2450
|
-
UPDATE_STATUS: "provider:updateStatus"
|
|
2606
|
+
UPDATE_STATUS: "provider:updateStatus",
|
|
2607
|
+
GET_PRESETS: "provider:getPresets",
|
|
2608
|
+
FETCH_MODEL_LIST: "provider:fetchModelList"
|
|
2451
2609
|
},
|
|
2452
2610
|
// Model channels
|
|
2453
2611
|
MODEL: {
|
|
@@ -2485,6 +2643,15 @@ const IPC_CHANNELS = {
|
|
|
2485
2643
|
COMPLETION: {
|
|
2486
2644
|
MARK_IMAGEDOWN: "completion:markImagedown",
|
|
2487
2645
|
TEST_CONNECTION: "completion:testConnection"
|
|
2646
|
+
},
|
|
2647
|
+
// Event channels (for event bridge)
|
|
2648
|
+
EVENTS: {
|
|
2649
|
+
UPDATER_STATUS: "updater:status"
|
|
2650
|
+
},
|
|
2651
|
+
// Updater channels
|
|
2652
|
+
UPDATER: {
|
|
2653
|
+
CHECK_FOR_UPDATES: "updater:checkForUpdates",
|
|
2654
|
+
QUIT_AND_INSTALL: "updater:quitAndInstall"
|
|
2488
2655
|
}
|
|
2489
2656
|
};
|
|
2490
2657
|
function registerProviderHandlers() {
|
|
@@ -2590,8 +2757,135 @@ function registerProviderHandlers() {
|
|
|
2590
2757
|
}
|
|
2591
2758
|
}
|
|
2592
2759
|
);
|
|
2760
|
+
ipcMain.handle(
|
|
2761
|
+
IPC_CHANNELS.PROVIDER.GET_PRESETS,
|
|
2762
|
+
async () => {
|
|
2763
|
+
try {
|
|
2764
|
+
return { success: true, data: providerPresets };
|
|
2765
|
+
} catch (error) {
|
|
2766
|
+
console.error("[IPC] provider:getPresets error:", error);
|
|
2767
|
+
return { success: false, error: error.message };
|
|
2768
|
+
}
|
|
2769
|
+
}
|
|
2770
|
+
);
|
|
2771
|
+
ipcMain.handle(
|
|
2772
|
+
IPC_CHANNELS.PROVIDER.FETCH_MODEL_LIST,
|
|
2773
|
+
async (_, providerId) => {
|
|
2774
|
+
try {
|
|
2775
|
+
const provider = await providerRepository.findById(providerId);
|
|
2776
|
+
if (!provider) {
|
|
2777
|
+
return { success: false, error: "Provider not found" };
|
|
2778
|
+
}
|
|
2779
|
+
const preset = findProviderPreset(provider.type, provider.name);
|
|
2780
|
+
const baseUrl = provider.base_url || preset?.apiBase;
|
|
2781
|
+
if (!baseUrl) {
|
|
2782
|
+
return {
|
|
2783
|
+
success: false,
|
|
2784
|
+
error: "No API base URL configured for this provider"
|
|
2785
|
+
};
|
|
2786
|
+
}
|
|
2787
|
+
const modelListApi = preset?.modelListApi ?? "/models";
|
|
2788
|
+
const modelListUrl = `${baseUrl}${modelListApi}`;
|
|
2789
|
+
const headers = {
|
|
2790
|
+
"Content-Type": "application/json"
|
|
2791
|
+
};
|
|
2792
|
+
if (provider.api_key) {
|
|
2793
|
+
switch (provider.type) {
|
|
2794
|
+
case "anthropic":
|
|
2795
|
+
headers["x-api-key"] = provider.api_key;
|
|
2796
|
+
headers["anthropic-version"] = "2023-06-01";
|
|
2797
|
+
break;
|
|
2798
|
+
case "gemini":
|
|
2799
|
+
headers["x-goog-api-key"] = provider.api_key;
|
|
2800
|
+
break;
|
|
2801
|
+
default:
|
|
2802
|
+
headers["Authorization"] = `Bearer ${provider.api_key}`;
|
|
2803
|
+
break;
|
|
2804
|
+
}
|
|
2805
|
+
}
|
|
2806
|
+
const response = await fetch(modelListUrl, {
|
|
2807
|
+
method: "GET",
|
|
2808
|
+
headers
|
|
2809
|
+
});
|
|
2810
|
+
if (!response.ok) {
|
|
2811
|
+
const errorText = await response.text();
|
|
2812
|
+
console.error(
|
|
2813
|
+
`[IPC] provider:fetchModelList HTTP error: ${response.status}`,
|
|
2814
|
+
errorText
|
|
2815
|
+
);
|
|
2816
|
+
return {
|
|
2817
|
+
success: false,
|
|
2818
|
+
error: `Failed to fetch models: HTTP ${response.status}`
|
|
2819
|
+
};
|
|
2820
|
+
}
|
|
2821
|
+
const data = await response.json();
|
|
2822
|
+
const filterByCapability = (items) => {
|
|
2823
|
+
if (!preset?.capabilityField || !preset?.capabilityFilter) return items;
|
|
2824
|
+
return items.filter((item) => {
|
|
2825
|
+
const value = getNestedValue(item, preset.capabilityField);
|
|
2826
|
+
if (!Array.isArray(value)) return true;
|
|
2827
|
+
return value.includes(preset.capabilityFilter);
|
|
2828
|
+
});
|
|
2829
|
+
};
|
|
2830
|
+
let models = [];
|
|
2831
|
+
const modelIdField = preset?.modelIdField ?? "id";
|
|
2832
|
+
const modelNameField = preset?.modelNameField ?? "id";
|
|
2833
|
+
switch (provider.type) {
|
|
2834
|
+
case "openai":
|
|
2835
|
+
case "openai-responses":
|
|
2836
|
+
if (data.data && Array.isArray(data.data)) {
|
|
2837
|
+
models = filterByCapability(data.data).map((item) => ({
|
|
2838
|
+
id: item[modelIdField] || item.id,
|
|
2839
|
+
name: item[modelNameField] || item.id
|
|
2840
|
+
}));
|
|
2841
|
+
}
|
|
2842
|
+
break;
|
|
2843
|
+
case "anthropic":
|
|
2844
|
+
if (data.data && Array.isArray(data.data)) {
|
|
2845
|
+
models = filterByCapability(data.data).map((item) => ({
|
|
2846
|
+
id: item[modelIdField] || item.id,
|
|
2847
|
+
name: item[modelNameField] || item.id
|
|
2848
|
+
}));
|
|
2849
|
+
}
|
|
2850
|
+
break;
|
|
2851
|
+
case "gemini":
|
|
2852
|
+
if (data.models && Array.isArray(data.models)) {
|
|
2853
|
+
models = filterByCapability(data.models).map((item) => ({
|
|
2854
|
+
id: item[modelIdField]?.replace("models/", "") || item.name,
|
|
2855
|
+
name: item[modelNameField] || item.name
|
|
2856
|
+
}));
|
|
2857
|
+
}
|
|
2858
|
+
break;
|
|
2859
|
+
case "ollama":
|
|
2860
|
+
if (data.models && Array.isArray(data.models)) {
|
|
2861
|
+
models = filterByCapability(data.models).map((item) => ({
|
|
2862
|
+
id: item[modelIdField] || item.name,
|
|
2863
|
+
name: item[modelNameField] || item.name
|
|
2864
|
+
}));
|
|
2865
|
+
}
|
|
2866
|
+
break;
|
|
2867
|
+
default: {
|
|
2868
|
+
const modelArray = data.data || data.models || [];
|
|
2869
|
+
if (Array.isArray(modelArray)) {
|
|
2870
|
+
models = filterByCapability(modelArray).map((item) => ({
|
|
2871
|
+
id: getNestedValue(item, modelIdField) || item.id || item.name,
|
|
2872
|
+
name: getNestedValue(item, modelNameField) || item.id || item.name
|
|
2873
|
+
}));
|
|
2874
|
+
}
|
|
2875
|
+
}
|
|
2876
|
+
}
|
|
2877
|
+
return { success: true, data: models };
|
|
2878
|
+
} catch (error) {
|
|
2879
|
+
console.error("[IPC] provider:fetchModelList error:", error);
|
|
2880
|
+
return { success: false, error: error.message };
|
|
2881
|
+
}
|
|
2882
|
+
}
|
|
2883
|
+
);
|
|
2593
2884
|
console.log("[IPC] Provider handlers registered");
|
|
2594
2885
|
}
|
|
2886
|
+
function getNestedValue(obj, path2) {
|
|
2887
|
+
return path2.split(".").reduce((acc, part) => acc?.[part], obj);
|
|
2888
|
+
}
|
|
2595
2889
|
const findAll$1 = async () => {
|
|
2596
2890
|
return await prisma.model.findMany({
|
|
2597
2891
|
orderBy: [{ createdAt: "desc" }]
|
|
@@ -3429,19 +3723,6 @@ function registerAppHandlers() {
|
|
|
3429
3723
|
return getAppVersion();
|
|
3430
3724
|
});
|
|
3431
3725
|
}
|
|
3432
|
-
function registerAllHandlers() {
|
|
3433
|
-
registerProviderHandlers();
|
|
3434
|
-
registerModelHandlers();
|
|
3435
|
-
registerTaskHandlers();
|
|
3436
|
-
registerTaskDetailHandlers();
|
|
3437
|
-
registerFileHandlers();
|
|
3438
|
-
registerCompletionHandlers();
|
|
3439
|
-
registerAppHandlers();
|
|
3440
|
-
console.log("[IPC] All handlers registered successfully");
|
|
3441
|
-
}
|
|
3442
|
-
function registerIpcHandlers() {
|
|
3443
|
-
registerAllHandlers();
|
|
3444
|
-
}
|
|
3445
3726
|
class WindowManager {
|
|
3446
3727
|
static instance;
|
|
3447
3728
|
mainWindow = null;
|
|
@@ -3476,6 +3757,112 @@ class WindowManager {
|
|
|
3476
3757
|
}
|
|
3477
3758
|
}
|
|
3478
3759
|
const windowManager = WindowManager.getInstance();
|
|
3760
|
+
const { autoUpdater } = pkg$1;
|
|
3761
|
+
class UpdateService {
|
|
3762
|
+
static instance;
|
|
3763
|
+
initialized = false;
|
|
3764
|
+
isChecking = false;
|
|
3765
|
+
constructor() {
|
|
3766
|
+
}
|
|
3767
|
+
static getInstance() {
|
|
3768
|
+
if (!UpdateService.instance) {
|
|
3769
|
+
UpdateService.instance = new UpdateService();
|
|
3770
|
+
}
|
|
3771
|
+
return UpdateService.instance;
|
|
3772
|
+
}
|
|
3773
|
+
ensureInitialized() {
|
|
3774
|
+
if (this.initialized) return;
|
|
3775
|
+
if (!app.isPackaged) return;
|
|
3776
|
+
this.initialized = true;
|
|
3777
|
+
autoUpdater.autoDownload = true;
|
|
3778
|
+
autoUpdater.allowPrerelease = false;
|
|
3779
|
+
autoUpdater.autoInstallOnAppQuit = true;
|
|
3780
|
+
this.registerListeners();
|
|
3781
|
+
}
|
|
3782
|
+
registerListeners() {
|
|
3783
|
+
autoUpdater.on("checking-for-update", () => {
|
|
3784
|
+
console.log("[UpdateService] Checking for updates...");
|
|
3785
|
+
this.sendStatus({ status: UpdateStatus.CHECKING });
|
|
3786
|
+
});
|
|
3787
|
+
autoUpdater.on("update-available", (info) => {
|
|
3788
|
+
console.log("[UpdateService] Update available:", info.version);
|
|
3789
|
+
this.sendStatus({ status: UpdateStatus.AVAILABLE, version: info.version });
|
|
3790
|
+
});
|
|
3791
|
+
autoUpdater.on("update-not-available", (info) => {
|
|
3792
|
+
console.log("[UpdateService] No update available. Current version:", info.version);
|
|
3793
|
+
this.sendStatus({ status: UpdateStatus.NOT_AVAILABLE, version: info.version });
|
|
3794
|
+
});
|
|
3795
|
+
autoUpdater.on("download-progress", (progress) => {
|
|
3796
|
+
console.log(`[UpdateService] Download progress: ${progress.percent.toFixed(1)}%`);
|
|
3797
|
+
this.sendStatus({ status: UpdateStatus.DOWNLOADING, progress: progress.percent });
|
|
3798
|
+
});
|
|
3799
|
+
autoUpdater.on("update-downloaded", (info) => {
|
|
3800
|
+
console.log("[UpdateService] Update downloaded:", info.version);
|
|
3801
|
+
this.sendStatus({ status: UpdateStatus.DOWNLOADED, version: info.version });
|
|
3802
|
+
});
|
|
3803
|
+
autoUpdater.on("error", (error) => {
|
|
3804
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
3805
|
+
const safeMessage = errorMessage.length > 200 ? `${errorMessage.slice(0, 200)}...` : errorMessage;
|
|
3806
|
+
const errorDetails = {
|
|
3807
|
+
message: safeMessage,
|
|
3808
|
+
name: error instanceof Error ? error.name : void 0,
|
|
3809
|
+
stack: error instanceof Error ? error.stack : void 0,
|
|
3810
|
+
code: error.code,
|
|
3811
|
+
statusCode: error.statusCode
|
|
3812
|
+
};
|
|
3813
|
+
console.error("[UpdateService] Error:", errorDetails);
|
|
3814
|
+
this.sendStatus({ status: UpdateStatus.ERROR, error: safeMessage });
|
|
3815
|
+
});
|
|
3816
|
+
}
|
|
3817
|
+
sendStatus(data) {
|
|
3818
|
+
windowManager.sendToRenderer(IPC_CHANNELS.EVENTS.UPDATER_STATUS, data);
|
|
3819
|
+
}
|
|
3820
|
+
async checkForUpdates() {
|
|
3821
|
+
this.ensureInitialized();
|
|
3822
|
+
if (!this.initialized) return;
|
|
3823
|
+
if (this.isChecking) return;
|
|
3824
|
+
this.isChecking = true;
|
|
3825
|
+
try {
|
|
3826
|
+
await autoUpdater.checkForUpdates();
|
|
3827
|
+
} finally {
|
|
3828
|
+
this.isChecking = false;
|
|
3829
|
+
}
|
|
3830
|
+
}
|
|
3831
|
+
quitAndInstall() {
|
|
3832
|
+
this.ensureInitialized();
|
|
3833
|
+
autoUpdater.quitAndInstall();
|
|
3834
|
+
}
|
|
3835
|
+
}
|
|
3836
|
+
const updateService = UpdateService.getInstance();
|
|
3837
|
+
function registerUpdaterHandlers() {
|
|
3838
|
+
ipcMain.handle(IPC_CHANNELS.UPDATER.CHECK_FOR_UPDATES, async () => {
|
|
3839
|
+
if (!app.isPackaged) {
|
|
3840
|
+
console.log("[Updater] Skipping update check in development mode");
|
|
3841
|
+
windowManager.sendToRenderer(IPC_CHANNELS.EVENTS.UPDATER_STATUS, {
|
|
3842
|
+
status: UpdateStatus.NOT_AVAILABLE
|
|
3843
|
+
});
|
|
3844
|
+
return;
|
|
3845
|
+
}
|
|
3846
|
+
await updateService.checkForUpdates();
|
|
3847
|
+
});
|
|
3848
|
+
ipcMain.handle(IPC_CHANNELS.UPDATER.QUIT_AND_INSTALL, () => {
|
|
3849
|
+
updateService.quitAndInstall();
|
|
3850
|
+
});
|
|
3851
|
+
}
|
|
3852
|
+
function registerAllHandlers() {
|
|
3853
|
+
registerProviderHandlers();
|
|
3854
|
+
registerModelHandlers();
|
|
3855
|
+
registerTaskHandlers();
|
|
3856
|
+
registerTaskDetailHandlers();
|
|
3857
|
+
registerFileHandlers();
|
|
3858
|
+
registerCompletionHandlers();
|
|
3859
|
+
registerAppHandlers();
|
|
3860
|
+
registerUpdaterHandlers();
|
|
3861
|
+
console.log("[IPC] All handlers registered successfully");
|
|
3862
|
+
}
|
|
3863
|
+
function registerIpcHandlers() {
|
|
3864
|
+
registerAllHandlers();
|
|
3865
|
+
}
|
|
3479
3866
|
class EventBridge {
|
|
3480
3867
|
isInitialized = false;
|
|
3481
3868
|
initialize() {
|
|
@@ -3709,6 +4096,10 @@ async function initializeBackgroundServices() {
|
|
|
3709
4096
|
console.log("[Main] Initializing database in background...");
|
|
3710
4097
|
await initDatabase();
|
|
3711
4098
|
console.log(`[Main] Database initialized in ${Date.now() - startTime}ms`);
|
|
4099
|
+
console.log("[Main] Injecting preset providers...");
|
|
4100
|
+
const presetStartTime = Date.now();
|
|
4101
|
+
await presetProviderService.initialize();
|
|
4102
|
+
console.log(`[Main] Preset providers injected in ${Date.now() - presetStartTime}ms`);
|
|
3712
4103
|
console.log("[Main] Starting task logic in background...");
|
|
3713
4104
|
const taskStartTime = Date.now();
|
|
3714
4105
|
await startTask();
|
|
@@ -3719,6 +4110,11 @@ async function initializeBackgroundServices() {
|
|
|
3719
4110
|
if (mainWindow) {
|
|
3720
4111
|
mainWindow.webContents.send("app:ready");
|
|
3721
4112
|
}
|
|
4113
|
+
if (app.isPackaged) {
|
|
4114
|
+
updateService.checkForUpdates().catch(
|
|
4115
|
+
(err) => console.error("[Main] Auto-update check failed:", err)
|
|
4116
|
+
);
|
|
4117
|
+
}
|
|
3722
4118
|
} catch (error) {
|
|
3723
4119
|
console.error("[Main] Background services initialization error:", error);
|
|
3724
4120
|
throw error;
|
package/dist/preload/index.js
CHANGED
|
@@ -8,7 +8,9 @@ electron.contextBridge.exposeInMainWorld("api", {
|
|
|
8
8
|
create: (data) => electron.ipcRenderer.invoke("provider:create", data),
|
|
9
9
|
update: (id, data) => electron.ipcRenderer.invoke("provider:update", id, data),
|
|
10
10
|
delete: (id) => electron.ipcRenderer.invoke("provider:delete", id),
|
|
11
|
-
updateStatus: (id, status) => electron.ipcRenderer.invoke("provider:updateStatus", id, status)
|
|
11
|
+
updateStatus: (id, status) => electron.ipcRenderer.invoke("provider:updateStatus", id, status),
|
|
12
|
+
getPresets: () => electron.ipcRenderer.invoke("provider:getPresets"),
|
|
13
|
+
fetchModelList: (providerId) => electron.ipcRenderer.invoke("provider:fetchModelList", providerId)
|
|
12
14
|
},
|
|
13
15
|
// ==================== Model APIs ====================
|
|
14
16
|
model: {
|
|
@@ -56,6 +58,11 @@ electron.contextBridge.exposeInMainWorld("api", {
|
|
|
56
58
|
maximize: () => electron.ipcRenderer.send("window:maximize"),
|
|
57
59
|
close: () => electron.ipcRenderer.send("window:close")
|
|
58
60
|
},
|
|
61
|
+
// ==================== Updater APIs ====================
|
|
62
|
+
updater: {
|
|
63
|
+
checkForUpdates: () => electron.ipcRenderer.invoke("updater:checkForUpdates"),
|
|
64
|
+
quitAndInstall: () => electron.ipcRenderer.invoke("updater:quitAndInstall")
|
|
65
|
+
},
|
|
59
66
|
// ==================== Event APIs ====================
|
|
60
67
|
events: {
|
|
61
68
|
/**
|
|
@@ -81,6 +88,18 @@ electron.contextBridge.exposeInMainWorld("api", {
|
|
|
81
88
|
return () => {
|
|
82
89
|
electron.ipcRenderer.removeListener("taskDetail:event", handler);
|
|
83
90
|
};
|
|
91
|
+
},
|
|
92
|
+
/**
|
|
93
|
+
* 监听更新状态事件
|
|
94
|
+
* @param callback 事件回调函数
|
|
95
|
+
* @returns 清理函数
|
|
96
|
+
*/
|
|
97
|
+
onUpdaterStatus: (callback) => {
|
|
98
|
+
const handler = (_event, data) => callback(data);
|
|
99
|
+
electron.ipcRenderer.on("updater:status", handler);
|
|
100
|
+
return () => {
|
|
101
|
+
electron.ipcRenderer.removeListener("updater:status", handler);
|
|
102
|
+
};
|
|
84
103
|
}
|
|
85
104
|
},
|
|
86
105
|
// ==================== Platform APIs ====================
|
|
@@ -95,6 +95,60 @@ body {
|
|
|
95
95
|
overflow: hidden !important;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
/* Model Service Tabs 内容区域滚动 - 仅滚动时显示滚动条 */
|
|
99
|
+
.model-service-tabs .ant-tabs-content-holder {
|
|
100
|
+
overflow-y: auto;
|
|
101
|
+
scrollbar-gutter: stable;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.model-service-tabs .ant-tabs-content-holder::-webkit-scrollbar {
|
|
105
|
+
width: 6px;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
.model-service-tabs .ant-tabs-content-holder::-webkit-scrollbar-thumb {
|
|
109
|
+
background-color: transparent;
|
|
110
|
+
border-radius: 3px;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
.model-service-tabs .ant-tabs-content-holder:hover::-webkit-scrollbar-thumb,
|
|
114
|
+
.model-service-tabs .ant-tabs-content-holder:active::-webkit-scrollbar-thumb {
|
|
115
|
+
background-color: rgba(0, 0, 0, 0.2);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
.model-service-tabs .ant-tabs-content-holder::-webkit-scrollbar-track {
|
|
119
|
+
background: transparent;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* Provider 状态呼吸灯 */
|
|
123
|
+
.provider-status-light {
|
|
124
|
+
display: inline-block;
|
|
125
|
+
width: 8px;
|
|
126
|
+
height: 8px;
|
|
127
|
+
border-radius: 50%;
|
|
128
|
+
flex-shrink: 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
.provider-status-light--enabled {
|
|
132
|
+
background-color: #52c41a;
|
|
133
|
+
box-shadow: 0 0 6px rgba(82, 196, 26, 0.6);
|
|
134
|
+
animation: breathing-green 2s ease-in-out infinite;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.provider-status-light--disabled {
|
|
138
|
+
background-color: #bfbfbf;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
@keyframes breathing-green {
|
|
142
|
+
0%, 100% {
|
|
143
|
+
box-shadow: 0 0 4px rgba(82, 196, 26, 0.4);
|
|
144
|
+
opacity: 1;
|
|
145
|
+
}
|
|
146
|
+
50% {
|
|
147
|
+
box-shadow: 0 0 10px rgba(82, 196, 26, 0.8);
|
|
148
|
+
opacity: 0.8;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
98
152
|
/* Markdown 预览面板滚动 */
|
|
99
153
|
.ant-splitter-panel:last-child {
|
|
100
154
|
overflow: auto !important;
|