feat: 对接设计 Agent Gateway WebSocket
需求:服务端统一 Agent Gateway 将设计任务状态流切换为 WebSocket,客户端需要实时展示生成任务并支持断线恢复。 实现:Electron Main 管理 Session、一次性 Ticket、WebSocket 心跳与游标续传,按关闭码回收会话;Renderer 继续通过本机 Host API 的 SSE 投影接收任务事件,并保留 REST 降级同步。 验证:typecheck、变更文件 ESLint、37 个聚焦测试及 build:vite 通过。
This commit is contained in:
@@ -32,6 +32,10 @@ import { logger } from '../utils/logger';
|
||||
import { warmupNetworkOptimization } from '../utils/uv-env';
|
||||
import { resolvePythonRuntime } from '../utils/python-runtime';
|
||||
import { initTelemetry } from '../utils/telemetry';
|
||||
import {
|
||||
getOrCreateAgentGatewaySessionClientId,
|
||||
rotateAgentGatewaySessionClientId,
|
||||
} from '../utils/store';
|
||||
|
||||
import { isQuitting, setQuitting } from './app-state';
|
||||
import { applyProxySettings } from './proxy';
|
||||
@@ -73,6 +77,7 @@ import {
|
||||
LocalImageWorkspace,
|
||||
} from '../image-workspace/local-workspace';
|
||||
import { WorksSquareDesignWorkspace } from '../image-workspace/works-square-workspace';
|
||||
import type { DesignWorkspaceModule } from '../image-workspace/module';
|
||||
|
||||
const WINDOWS_APP_USER_MODEL_ID = 'app.niancode.desktop';
|
||||
const isE2EMode = process.env.NIANCODE_E2E === '1';
|
||||
@@ -152,6 +157,7 @@ let hostApiServer: Server | null = null;
|
||||
let projectProgressSync: ReturnType<typeof createProjectProgressSync> | null = null;
|
||||
let worksCloudDeployment: ReturnType<typeof createWorksCloudDeployment> | null = null;
|
||||
let agentBrowser: AgentBrowserModule | null = null;
|
||||
let imageWorkspaceModule: DesignWorkspaceModule | null = null;
|
||||
const mainWindowFocusState = createMainWindowFocusState();
|
||||
const quitLifecycleState = createQuitLifecycleState();
|
||||
const launchDeepLinkUrl = findNianCodeDeepLinkUrl(process.argv);
|
||||
@@ -419,7 +425,13 @@ async function initialize(): Promise<void> {
|
||||
});
|
||||
const imageWorkspace = localImageWorkspaceEnabled
|
||||
? new LocalImageWorkspace({ userDataDir: app.getPath('userData') })
|
||||
: new WorksSquareDesignWorkspace();
|
||||
: new WorksSquareDesignWorkspace({
|
||||
eventSessionClientIdStore: {
|
||||
getOrCreate: getOrCreateAgentGatewaySessionClientId,
|
||||
rotate: rotateAgentGatewaySessionClientId,
|
||||
},
|
||||
});
|
||||
imageWorkspaceModule = imageWorkspace;
|
||||
if (localImageWorkspaceEnabled) {
|
||||
logger.info('AI painting workspace is using local development storage');
|
||||
} else {
|
||||
@@ -647,9 +659,13 @@ if (gotTheLock) {
|
||||
const stopAgentBrowserPromise = agentBrowser?.dispose().catch((err) => {
|
||||
logger.warn('agentBrowser.dispose() error during quit:', err);
|
||||
}) ?? Promise.resolve();
|
||||
const closeImageWorkspacePromise = imageWorkspaceModule?.closeEventSessions?.().catch((err) => {
|
||||
logger.warn('imageWorkspace.closeEventSessions() error during quit:', err);
|
||||
}) ?? Promise.resolve();
|
||||
const stopPromise = Promise.allSettled([
|
||||
stopOpencodePromise,
|
||||
stopAgentBrowserPromise,
|
||||
closeImageWorkspacePromise,
|
||||
]);
|
||||
const timeoutPromise = new Promise<'timeout'>((resolve) => {
|
||||
setTimeout(() => resolve('timeout'), 5000);
|
||||
|
||||
Reference in New Issue
Block a user