feat(coding): add core host api composition
This commit is contained in:
@@ -18,7 +18,6 @@ import {
|
||||
resolveBundledCourseSkillsDir,
|
||||
} from '../opencode/course-skills';
|
||||
import {
|
||||
createElectronProjectStorage,
|
||||
createProjectStore,
|
||||
type OpencodeProjectStore,
|
||||
} from '../opencode/project-store';
|
||||
@@ -95,10 +94,13 @@ import {
|
||||
} from '../image-workspace/local-workspace';
|
||||
import { WorksSquareDesignWorkspace } from '../image-workspace/works-square-workspace';
|
||||
import type { DesignWorkspaceModule } from '../image-workspace/module';
|
||||
import { CodingAttachmentStore } from '../coding-projects/attachment-store';
|
||||
import { PiProductTools } from '../coding-runtime/pi/product-tools';
|
||||
import { createElectronCodingProjectStorage } from '../coding-projects/project-store';
|
||||
import { resolveBundledCodingSkillsDir } from '../coding-runtime/pi/resource-loader';
|
||||
import { createCodingProductHost } from '../api/coding-product-services';
|
||||
import type { CodingProductComposition } from '../api/coding-product-services';
|
||||
import {
|
||||
createCodingComposition,
|
||||
resolveCodingPiRuntimePaths,
|
||||
} from '../api/coding-composition';
|
||||
|
||||
// Diagnostic package: force Chromium networking onto HTTP/1.1 for transport A/B testing.
|
||||
app.commandLine.appendSwitch('disable-http2');
|
||||
@@ -206,6 +208,7 @@ let applicationInitialization: Promise<void> | null = null;
|
||||
let imageWorkspaceModule: DesignWorkspaceModule | null = null;
|
||||
let backgroundLifecycle!: BackgroundLifecycleController;
|
||||
let releaseJobs: ReleaseJobManager | null = null;
|
||||
let codingProducts: CodingProductComposition | null = null;
|
||||
const mainWindowFocusState = createMainWindowFocusState();
|
||||
const quitLifecycleState = createQuitLifecycleState();
|
||||
const launchDeepLinkUrl = findNianCodeDeepLinkUrl(process.argv);
|
||||
@@ -496,7 +499,8 @@ async function initialize(): Promise<void> {
|
||||
// Only local storage and the lightweight workspace object are needed to
|
||||
// construct the first window. Authentication and remote setup are restored
|
||||
// after the renderer has had a chance to paint.
|
||||
opencodeProjectStore = createProjectStore(await createElectronProjectStorage());
|
||||
const codingProjectStorage = await createElectronCodingProjectStorage();
|
||||
opencodeProjectStore = createProjectStore(codingProjectStorage);
|
||||
worksSubmissionBinding = createWorksSubmissionBindingStore(opencodeProjectStore);
|
||||
|
||||
const localImageWorkspaceEnabled = isLocalImageWorkspaceDevelopmentEnabled({
|
||||
@@ -553,29 +557,25 @@ async function initialize(): Promise<void> {
|
||||
window.webContents.send('release-job:status', status);
|
||||
}
|
||||
});
|
||||
const codingAttachments = new CodingAttachmentStore(
|
||||
join(app.getPath('userData'), 'coding-runtime', 'attachments'),
|
||||
);
|
||||
const piProductTools = new PiProductTools({
|
||||
codingProducts = createCodingComposition({
|
||||
storage: codingProjectStorage,
|
||||
browser: agentBrowser,
|
||||
attachments: codingAttachments,
|
||||
bundledSkillsDir: resolveBundledCodingSkillsDir({
|
||||
isPackaged: app.isPackaged,
|
||||
resourcesPath: process.resourcesPath,
|
||||
appPath: app.getAppPath(),
|
||||
}),
|
||||
localProxyCredential: getHostApiToken() || undefined,
|
||||
paths: {
|
||||
...resolveCodingPiRuntimePaths({
|
||||
isPackaged: app.isPackaged,
|
||||
resourcesPath: process.resourcesPath,
|
||||
appPath: app.getAppPath(),
|
||||
executablePath: process.execPath,
|
||||
}),
|
||||
userDataDir: app.getPath('userData'),
|
||||
bundledSkillsDir: resolveBundledCodingSkillsDir({
|
||||
isPackaged: app.isPackaged,
|
||||
resourcesPath: process.resourcesPath,
|
||||
appPath: app.getAppPath(),
|
||||
}),
|
||||
},
|
||||
});
|
||||
const codingProducts = {
|
||||
attachments: codingAttachments,
|
||||
productTools: piProductTools,
|
||||
host: createCodingProductHost({
|
||||
productTools: piProductTools,
|
||||
getActiveProject: async () => {
|
||||
const project = await opencodeProjectStore.getActiveProject();
|
||||
return project ? { id: project.id, path: project.path } : null;
|
||||
},
|
||||
}),
|
||||
};
|
||||
const hostApiContext: HostApiContext = {
|
||||
opencodeManager,
|
||||
opencodeProjectStore,
|
||||
@@ -866,10 +866,14 @@ if (gotTheLock) {
|
||||
const closeImageWorkspacePromise = imageWorkspaceModule?.closeEventSessions?.().catch((err) => {
|
||||
logger.warn('imageWorkspace.closeEventSessions() error during quit:', err);
|
||||
}) ?? Promise.resolve();
|
||||
const stopCodingProductsPromise = codingProducts?.shutdown().catch((err) => {
|
||||
logger.warn('codingProducts.shutdown() error during quit:', err);
|
||||
}) ?? Promise.resolve();
|
||||
const stopPromise = Promise.allSettled([
|
||||
stopOpencodePromise,
|
||||
stopAgentBrowserPromise,
|
||||
closeImageWorkspacePromise,
|
||||
stopCodingProductsPromise,
|
||||
]);
|
||||
const timeoutPromise = new Promise<'timeout'>((resolve) => {
|
||||
setTimeout(() => resolve('timeout'), 5000);
|
||||
@@ -900,6 +904,11 @@ if (gotTheLock) {
|
||||
} catch {
|
||||
// ignore — stop() may not be callable if state is corrupted
|
||||
}
|
||||
try {
|
||||
void codingProducts?.shutdown().catch(() => { /* ignore */ });
|
||||
} catch {
|
||||
// ignore — shutdown() may not be callable if state is corrupted
|
||||
}
|
||||
// Give runtime stop a brief window, then force-exit.
|
||||
setTimeout(() => {
|
||||
process.exit(1);
|
||||
|
||||
Reference in New Issue
Block a user