Skip to content
This repository was archived by the owner on Jun 8, 2026. It is now read-only.

Commit 1fcbb4d

Browse files
Andrew EyeAndrew Eye
authored andcommitted
FEA-1469: add Symphony web POC surface
1 parent de3b6cc commit 1fcbb4d

10 files changed

Lines changed: 1864 additions & 15 deletions

apps/desktop/src/main/app.ts

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ import { SettingsStore, shouldShowManagedKeyHint, type SavedConfigManagedPatch }
6767
import { DesktopTray } from "./tray.js";
6868
import { DesktopWindow } from "./window.js";
6969
import { AgentMonitorSidecar } from "./agent-monitor-sidecar.js";
70+
import { SymphonyWebPocRuntime } from "./symphony-web-poc-runtime.js";
7071
import { AgentSessionSyncService } from "./agent-session-sync-service.js";
7172
import {
7273
isAgentMonitorHooksEnabled,
@@ -204,6 +205,7 @@ export class DesktopApplication {
204205
private readonly cloudSocket: CloudSocketService;
205206
private readonly commandExecutor: CloudCommandExecutor;
206207
private readonly agentMonitor: AgentMonitorSidecar;
208+
private readonly symphonyWebPoc: SymphonyWebPocRuntime;
207209
private readonly agentSessionSync: AgentSessionSyncService;
208210
private readonly activityLog: ActivityLogStore;
209211
private readonly approvalStore: ApprovalStore;
@@ -317,6 +319,9 @@ export class DesktopApplication {
317319
this.agentMonitor.setSandboxBaseDirectory(
318320
this.settingsStore.getSandboxBaseDirectory(),
319321
);
322+
this.symphonyWebPoc = new SymphonyWebPocRuntime({
323+
dataDir: path.join(app.getPath("userData"), "symphony-web-poc"),
324+
});
320325
this.activityLog = new ActivityLogStore();
321326
this.jobStore = new JobStore();
322327
this.approvalStore = new ApprovalStore({
@@ -670,6 +675,9 @@ export class DesktopApplication {
670675
syncAgentMonitorHooksOnBoot();
671676
this.agentSessionSync.start();
672677
}
678+
if (this.settingsStore.getSymphonyWebPocEnabled()) {
679+
void this.symphonyWebPoc.start();
680+
}
673681

674682
try {
675683
await this.server.start();
@@ -1266,6 +1274,10 @@ export class DesktopApplication {
12661274
return this.settingsStore.getPlanExtractionEnabled();
12671275
}
12681276

1277+
private isSymphonyWebPocEnabled(): boolean {
1278+
return this.settingsStore.getSymphonyWebPocEnabled();
1279+
}
1280+
12691281
private async applyAgentMonitorSetting(enabled: boolean): Promise<void> {
12701282
this.tray.setAgentMonitorEnabled(enabled);
12711283

@@ -1299,6 +1311,20 @@ export class DesktopApplication {
12991311
?.webContents.send("desktop:navigate-settings-tab", "relay-gateway");
13001312
}
13011313

1314+
private async applySymphonyWebPocSetting(enabled: boolean): Promise<void> {
1315+
if (enabled) {
1316+
void this.symphonyWebPoc.start();
1317+
return;
1318+
}
1319+
await this.symphonyWebPoc.stop();
1320+
this.desktopWindow
1321+
.getWindow()
1322+
?.webContents.send("desktop:navigate-tab", "settings");
1323+
this.desktopWindow
1324+
.getWindow()
1325+
?.webContents.send("desktop:navigate-settings-tab", "feature-flags");
1326+
}
1327+
13021328
openClaudeDashboard(): void {
13031329
this.desktopWindow.show();
13041330
if (!this.isAgentMonitorEnabled()) {
@@ -1745,7 +1771,12 @@ export class DesktopApplication {
17451771
},
17461772
cloudSocket: this.cloudSocket,
17471773
commandExecutor: this.commandExecutor,
1748-
agentMonitor: this.agentMonitor,
1774+
agentMonitor: {
1775+
stop: async () => {
1776+
await this.symphonyWebPoc.stop();
1777+
await this.agentMonitor.stop();
1778+
},
1779+
},
17491780
server: this.server,
17501781
desktopWindow: this.desktopWindow,
17511782
tray: this.tray,
@@ -2462,6 +2493,20 @@ export class DesktopApplication {
24622493
enabled: this.isAgentMonitorEnabled(),
24632494
planExtractionEnabled: this.isPlanExtractionEnabled(),
24642495
}));
2496+
ipcMain.handle("desktop:get-symphony-web-poc-status", () =>
2497+
this.symphonyWebPoc.getStatus(this.isSymphonyWebPocEnabled()),
2498+
);
2499+
ipcMain.handle("desktop:restart-symphony-web-poc", async () => {
2500+
if (!this.isSymphonyWebPocEnabled()) {
2501+
return {
2502+
ok: false,
2503+
error: "Symphony Web POC is disabled in Settings.",
2504+
};
2505+
}
2506+
await this.symphonyWebPoc.stop();
2507+
void this.symphonyWebPoc.start();
2508+
return { ok: true };
2509+
});
24652510
// FEA-1334: proxy the Agent Monitor cold-start ingest progress so the renderer
24662511
// can drive the floating progress card without a cross-origin fetch.
24672512
// Returns null whenever the Agent Monitor runtime is not reachable — the renderer treats
@@ -2554,8 +2599,15 @@ export class DesktopApplication {
25542599
if (activeAlwaysAllowRules.length !== settings.alwaysAllowRules.length) {
25552600
this.settingsStore.setAlwaysAllowRules(activeAlwaysAllowRules);
25562601
}
2602+
const effectiveFlags = Object.fromEntries(
2603+
FEATURE_FLAGS.map((flag) => [
2604+
flag.key,
2605+
this.settingsStore.getFlag(flag.key as FlagKey),
2606+
]),
2607+
);
25572608
return {
25582609
...settings,
2610+
...effectiveFlags,
25592611
alwaysAllowRules: activeAlwaysAllowRules,
25602612
};
25612613
});
@@ -2663,6 +2715,12 @@ export class DesktopApplication {
26632715
) {
26642716
await this.applyAgentMonitorSetting(nextPartial.agentMonitorEnabled);
26652717
}
2718+
if (
2719+
typeof nextPartial.symphonyWebPocEnabled === "boolean" &&
2720+
nextPartial.symphonyWebPocEnabled !== currentSettings.symphonyWebPocEnabled
2721+
) {
2722+
await this.applySymphonyWebPocSetting(nextPartial.symphonyWebPocEnabled);
2723+
}
26662724
if (
26672725
typeof nextPartial.cloudCommandsPaused === "boolean" &&
26682726
nextPartial.cloudCommandsPaused !== this.cloudCommandsPaused
@@ -2714,6 +2772,9 @@ export class DesktopApplication {
27142772
sandboxBaseDirectory: this.settingsStore.getSandboxBaseDirectory(),
27152773
commandsPaused: this.cloudCommandsPaused,
27162774
connectionEnabled: this.cloudConnectionEnabled,
2775+
symphonyWebPoc: this.symphonyWebPoc.getStatus(
2776+
this.isSymphonyWebPocEnabled(),
2777+
),
27172778
connectionSecurity: this.getConnectionSecurityStatus(),
27182779
commandSigning: {
27192780
serverSupported: this.serverCommandSigningSupported,

apps/desktop/src/main/preload.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,28 @@ const desktopApi = {
125125
enabled: boolean;
126126
planExtractionEnabled: boolean;
127127
}>,
128+
getSymphonyWebPocStatus: () =>
129+
ipcRenderer.invoke("desktop:get-symphony-web-poc-status") as Promise<{
130+
enabled: boolean;
131+
ready: boolean;
132+
mode: string | null;
133+
url: string | null;
134+
apiUrl: string | null;
135+
apiToken: string | null;
136+
dbPath: string | null;
137+
error: string | null;
138+
source: string | null;
139+
counts: {
140+
projects: number;
141+
workstreams: number;
142+
documents: number;
143+
};
144+
}>,
145+
restartSymphonyWebPoc: () =>
146+
ipcRenderer.invoke("desktop:restart-symphony-web-poc") as Promise<{
147+
ok: boolean;
148+
error?: string;
149+
}>,
128150
openAgentMonitor: () =>
129151
ipcRenderer.invoke("desktop:open-agent-monitor") as Promise<unknown>,
130152
getAgentMonitorHooksEnabled: () =>

apps/desktop/src/main/settings-store.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,10 @@ export class SettingsStore {
269269
return this.getFlag("planExtractionEnabled");
270270
}
271271

272+
getSymphonyWebPocEnabled(): boolean {
273+
return this.getFlag("symphonyWebPocEnabled");
274+
}
275+
272276
getCommandSigningEnforcementEnabled(): boolean {
273277
return this.getFlag("commandSigningEnforcementEnabled");
274278
}
@@ -313,6 +317,10 @@ export class SettingsStore {
313317
this.setFlag("planExtractionEnabled", planExtractionEnabled);
314318
}
315319

320+
setSymphonyWebPocEnabled(symphonyWebPocEnabled: boolean): void {
321+
this.setFlag("symphonyWebPocEnabled", symphonyWebPocEnabled);
322+
}
323+
316324
setCommandSigningEnforcementEnabled(commandSigningEnforcementEnabled: boolean): void {
317325
this.setFlag("commandSigningEnforcementEnabled", commandSigningEnforcementEnabled);
318326
}

0 commit comments

Comments
 (0)