feat: 支持 XCOpenCodeWeb.exe 配置和打包
- 添加 electron/config.ts 配置文件 - 支持 command(命令行) 和 exe 两种模式 - 更新 package.json 打包配置,添加 bin 目录 - 更新 .gitignore 忽略 bin/*.exe
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -32,6 +32,7 @@ dist-electron/
|
|||||||
# XCOpenCodeWeb (来自独立仓库 https://github.com/anomalyco/XCOpenCodeWeb)
|
# XCOpenCodeWeb (来自独立仓库 https://github.com/anomalyco/XCOpenCodeWeb)
|
||||||
remote/xcopencodeweb/XCOpenCodeWeb.exe
|
remote/xcopencodeweb/XCOpenCodeWeb.exe
|
||||||
service/xcopencodeweb/XCOpenCodeWeb.exe
|
service/xcopencodeweb/XCOpenCodeWeb.exe
|
||||||
|
bin/*.exe
|
||||||
|
|
||||||
# Tools output
|
# Tools output
|
||||||
tools/tongyi/ppt_output/
|
tools/tongyi/ppt_output/
|
||||||
|
|||||||
9
electron/config.ts
Normal file
9
electron/config.ts
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
export const appConfig = {
|
||||||
|
opencode: {
|
||||||
|
mode: 'command', // 'command' | 'exe'
|
||||||
|
exePath: 'bin/XCOpenCodeWeb.exe',
|
||||||
|
port: 4096,
|
||||||
|
healthCheckInterval: 10000,
|
||||||
|
maxRestartAttempts: 3,
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
import { spawn, ChildProcess } from 'child_process';
|
import { spawn, ChildProcess } from 'child_process';
|
||||||
|
import { app } from 'electron';
|
||||||
|
import path from 'path';
|
||||||
import log from 'electron-log';
|
import log from 'electron-log';
|
||||||
|
import { appConfig } from '../config';
|
||||||
|
|
||||||
const OPENCODE_PORT = 4096;
|
|
||||||
const HEALTH_CHECK_INTERVAL = 10000;
|
|
||||||
const MAX_RESTART_ATTEMPTS = 3;
|
|
||||||
const HEALTH_CHECK_TIMEOUT = 2000;
|
const HEALTH_CHECK_TIMEOUT = 2000;
|
||||||
|
|
||||||
class OpenCodeService {
|
class OpenCodeService {
|
||||||
@@ -13,7 +13,15 @@ class OpenCodeService {
|
|||||||
private _isRunning = false;
|
private _isRunning = false;
|
||||||
|
|
||||||
get port(): number {
|
get port(): number {
|
||||||
return OPENCODE_PORT;
|
return appConfig.opencode.port;
|
||||||
|
}
|
||||||
|
|
||||||
|
get healthCheckInterval(): number {
|
||||||
|
return appConfig.opencode.healthCheckInterval;
|
||||||
|
}
|
||||||
|
|
||||||
|
get maxRestartAttempts(): number {
|
||||||
|
return appConfig.opencode.maxRestartAttempts;
|
||||||
}
|
}
|
||||||
|
|
||||||
isRunning(): boolean {
|
isRunning(): boolean {
|
||||||
@@ -28,6 +36,23 @@ class OpenCodeService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getOpenCodePath(): string {
|
||||||
|
if (appConfig.opencode.mode === 'exe') {
|
||||||
|
const basePath = app.isPackaged
|
||||||
|
? path.dirname(app.getPath('exe'))
|
||||||
|
: path.join(process.cwd(), 'bin');
|
||||||
|
return path.join(basePath, appConfig.opencode.exePath);
|
||||||
|
}
|
||||||
|
return 'opencode';
|
||||||
|
}
|
||||||
|
|
||||||
|
private getOpenCodeArgs(): string[] {
|
||||||
|
if (appConfig.opencode.mode === 'exe') {
|
||||||
|
return ['serve'];
|
||||||
|
}
|
||||||
|
return ['serve'];
|
||||||
|
}
|
||||||
|
|
||||||
private getAuthHeaders(): Record<string, string> {
|
private getAuthHeaders(): Record<string, string> {
|
||||||
const password = 'xc_opencode_password';
|
const password = 'xc_opencode_password';
|
||||||
const encoded = Buffer.from(`:${password}`).toString('base64');
|
const encoded = Buffer.from(`:${password}`).toString('base64');
|
||||||
@@ -51,14 +76,14 @@ class OpenCodeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private async restart(): Promise<void> {
|
private async restart(): Promise<void> {
|
||||||
if (this.restartAttempts >= MAX_RESTART_ATTEMPTS) {
|
if (this.restartAttempts >= this.maxRestartAttempts) {
|
||||||
log.error('[OpenCodeService] Max restart attempts reached, giving up');
|
log.error('[OpenCodeService] Max restart attempts reached, giving up');
|
||||||
this._isRunning = false;
|
this._isRunning = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
this.restartAttempts++;
|
this.restartAttempts++;
|
||||||
log.info(`[OpenCodeService] Attempting restart (${this.restartAttempts}/${MAX_RESTART_ATTEMPTS})...`);
|
log.info(`[OpenCodeService] Attempting restart (${this.restartAttempts}/${this.maxRestartAttempts})...`);
|
||||||
|
|
||||||
await this.stop();
|
await this.stop();
|
||||||
await this.start();
|
await this.start();
|
||||||
@@ -75,7 +100,7 @@ class OpenCodeService {
|
|||||||
log.warn('[OpenCodeService] Health check failed, attempting restart...');
|
log.warn('[OpenCodeService] Health check failed, attempting restart...');
|
||||||
await this.restart();
|
await this.restart();
|
||||||
}
|
}
|
||||||
}, HEALTH_CHECK_INTERVAL);
|
}, this.healthCheckInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
async start(): Promise<{ success: boolean; error?: string }> {
|
async start(): Promise<{ success: boolean; error?: string }> {
|
||||||
@@ -85,9 +110,14 @@ class OpenCodeService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
log.info('[OpenCodeService] Starting OpenCode server...');
|
const opencodePath = this.getOpenCodePath();
|
||||||
|
const opencodeArgs = this.getOpenCodeArgs();
|
||||||
|
const mode = appConfig.opencode.mode;
|
||||||
|
|
||||||
this.process = spawn('opencode', ['serve'], {
|
log.info(`[OpenCodeService] Starting OpenCode server (mode: ${mode})...`);
|
||||||
|
log.info(`[OpenCodeService] Path: ${opencodePath}`);
|
||||||
|
|
||||||
|
this.process = spawn(opencodePath, opencodeArgs, {
|
||||||
stdio: 'pipe',
|
stdio: 'pipe',
|
||||||
shell: true,
|
shell: true,
|
||||||
detached: false,
|
detached: false,
|
||||||
|
|||||||
@@ -122,10 +122,12 @@
|
|||||||
"dist-api/**/*",
|
"dist-api/**/*",
|
||||||
"shared/**/*",
|
"shared/**/*",
|
||||||
"tools/**/*",
|
"tools/**/*",
|
||||||
|
"bin/**/*",
|
||||||
"package.json"
|
"package.json"
|
||||||
],
|
],
|
||||||
"asarUnpack": [
|
"asarUnpack": [
|
||||||
"tools/**/*"
|
"tools/**/*",
|
||||||
|
"bin/**/*"
|
||||||
],
|
],
|
||||||
"win": {
|
"win": {
|
||||||
"target": "nsis"
|
"target": "nsis"
|
||||||
|
|||||||
Reference in New Issue
Block a user