diff --git a/src/main/KopayaAppService.ts b/src/main/KopayaAppService.ts index 64bdc93..a7241b3 100644 --- a/src/main/KopayaAppService.ts +++ b/src/main/KopayaAppService.ts @@ -496,7 +496,12 @@ export class KopayaAppService extends EventEmitter { } private async loadSidecarCapabilities(forceRefresh = false): Promise { - if (forceRefresh || !this.sidecarCapabilities) { + if (forceRefresh) { + this.sidecarCapabilities = await this.sidecar.refreshCapabilities(); + return this.sidecarCapabilities; + } + + if (!this.sidecarCapabilities) { this.sidecarCapabilities = await this.sidecar.describeCapabilities(); } diff --git a/src/main/sidecar/sidecarProcess.ts b/src/main/sidecar/sidecarProcess.ts index cf075c0..bf0f745 100644 --- a/src/main/sidecar/sidecarProcess.ts +++ b/src/main/sidecar/sidecarProcess.ts @@ -12,6 +12,7 @@ import type { } from '@shared/contracts/sidecar'; import type { ChatMessageRecord } from '@shared/domain/session'; import { createSidecarEnvironment } from '@main/sidecar/sidecarEnvironment'; +import { shouldRestartSidecarOnCapabilityRefresh } from '@main/sidecar/sidecarRefresh'; import { markRunTurnPendingErrored, shouldHandleRunTurnEvent, @@ -46,6 +47,14 @@ export class SidecarClient { return command; } + async refreshCapabilities(): Promise { + if (shouldRestartSidecarOnCapabilityRefresh(this.hasActiveRunTurn())) { + await this.dispose(); + } + + return this.describeCapabilities(); + } + async validatePattern(pattern: ValidatePatternCommand['pattern']): Promise { return this.dispatch({ type: 'validate-pattern', @@ -71,6 +80,16 @@ export class SidecarClient { this.process = undefined; } + hasActiveRunTurn(): boolean { + for (const pending of this.pending.values()) { + if (pending.kind === 'run-turn') { + return true; + } + } + + return false; + } + private async ensureProcess(): Promise { if (this.process && !this.process.killed) { return this.process; diff --git a/src/main/sidecar/sidecarRefresh.ts b/src/main/sidecar/sidecarRefresh.ts new file mode 100644 index 0000000..0ddd9b2 --- /dev/null +++ b/src/main/sidecar/sidecarRefresh.ts @@ -0,0 +1,3 @@ +export function shouldRestartSidecarOnCapabilityRefresh(hasActiveRunTurn: boolean): boolean { + return !hasActiveRunTurn; +} diff --git a/tests/main/sidecarRefresh.test.ts b/tests/main/sidecarRefresh.test.ts new file mode 100644 index 0000000..15b0e68 --- /dev/null +++ b/tests/main/sidecarRefresh.test.ts @@ -0,0 +1,13 @@ +import { describe, expect, test } from 'bun:test'; + +import { shouldRestartSidecarOnCapabilityRefresh } from '@main/sidecar/sidecarRefresh'; + +describe('shouldRestartSidecarOnCapabilityRefresh', () => { + test('restarts the sidecar when no run-turn is active', () => { + expect(shouldRestartSidecarOnCapabilityRefresh(false)).toBe(true); + }); + + test('keeps the existing sidecar when a run-turn is active', () => { + expect(shouldRestartSidecarOnCapabilityRefresh(true)).toBe(false); + }); +});