mirror of
https://github.com/davidkaya/aryx.git
synced 2026-08-28 13:47:12 +02:00
fix: use live copilot model availability
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -3,8 +3,17 @@ import { basename } from 'node:path';
|
||||
|
||||
import { dialog } from 'electron';
|
||||
|
||||
import type { AgentActivityEvent, TurnDeltaEvent } from '@shared/contracts/sidecar';
|
||||
import { findModel } from '@shared/domain/models';
|
||||
import type {
|
||||
AgentActivityEvent,
|
||||
SidecarCapabilities,
|
||||
TurnDeltaEvent,
|
||||
} from '@shared/contracts/sidecar';
|
||||
import {
|
||||
buildAvailableModelCatalog,
|
||||
findModel,
|
||||
normalizePatternModels,
|
||||
resolveReasoningEffort,
|
||||
} from '@shared/domain/models';
|
||||
import {
|
||||
buildSessionTitle,
|
||||
isReasoningEffort,
|
||||
@@ -42,6 +51,15 @@ export class KopayaAppService extends EventEmitter<AppServiceEvents> {
|
||||
private readonly sidecar = new SidecarClient();
|
||||
private readonly secretStore = new SecretStore();
|
||||
private workspace?: WorkspaceState;
|
||||
private sidecarCapabilities?: SidecarCapabilities;
|
||||
|
||||
async describeSidecarCapabilities(): Promise<SidecarCapabilities> {
|
||||
if (!this.sidecarCapabilities) {
|
||||
this.sidecarCapabilities = await this.sidecar.describeCapabilities();
|
||||
}
|
||||
|
||||
return this.sidecarCapabilities;
|
||||
}
|
||||
|
||||
async loadWorkspace(): Promise<WorkspaceState> {
|
||||
if (!this.workspace) {
|
||||
@@ -152,6 +170,8 @@ export class KopayaAppService extends EventEmitter<AppServiceEvents> {
|
||||
const workspace = await this.loadWorkspace();
|
||||
const project = this.requireProject(workspace, projectId);
|
||||
const pattern = this.requirePattern(workspace, patternId);
|
||||
const modelCatalog = await this.loadAvailableModelCatalog();
|
||||
const normalizedPattern = normalizePatternModels(pattern, modelCatalog);
|
||||
|
||||
const session: SessionRecord = {
|
||||
id: createId('session'),
|
||||
@@ -162,7 +182,9 @@ export class KopayaAppService extends EventEmitter<AppServiceEvents> {
|
||||
updatedAt: nowIso(),
|
||||
status: 'idle',
|
||||
messages: [],
|
||||
scratchpadConfig: isScratchpadProject(project) ? createScratchpadSessionConfig(pattern) : undefined,
|
||||
scratchpadConfig: isScratchpadProject(project)
|
||||
? createScratchpadSessionConfig(normalizedPattern)
|
||||
: undefined,
|
||||
};
|
||||
|
||||
workspace.sessions.unshift(session);
|
||||
@@ -177,9 +199,7 @@ export class KopayaAppService extends EventEmitter<AppServiceEvents> {
|
||||
const session = this.requireSession(workspace, sessionId);
|
||||
const project = this.requireProject(workspace, session.projectId);
|
||||
const pattern = this.requirePattern(workspace, session.patternId);
|
||||
const effectivePattern = isScratchpadProject(project)
|
||||
? applyScratchpadSessionConfig(pattern, session)
|
||||
: pattern;
|
||||
const effectivePattern = await this.buildEffectivePattern(project, pattern, session);
|
||||
|
||||
const trimmed = content.trim();
|
||||
if (!trimmed) {
|
||||
@@ -248,12 +268,12 @@ export class KopayaAppService extends EventEmitter<AppServiceEvents> {
|
||||
async updateScratchpadSessionConfig(
|
||||
sessionId: string,
|
||||
model: string,
|
||||
reasoningEffort: ReasoningEffort,
|
||||
reasoningEffort?: ReasoningEffort,
|
||||
): Promise<WorkspaceState> {
|
||||
const workspace = await this.loadWorkspace();
|
||||
const session = this.requireSession(workspace, sessionId);
|
||||
const project = this.requireProject(workspace, session.projectId);
|
||||
const pattern = this.requirePattern(workspace, session.patternId);
|
||||
const modelCatalog = await this.loadAvailableModelCatalog();
|
||||
|
||||
if (!isScratchpadProject(project)) {
|
||||
throw new Error('Only scratchpad sessions can change model settings in chat.');
|
||||
@@ -264,17 +284,17 @@ export class KopayaAppService extends EventEmitter<AppServiceEvents> {
|
||||
}
|
||||
|
||||
const normalizedModel = model.trim();
|
||||
if (!normalizedModel || !findModel(normalizedModel)) {
|
||||
const selectedModel = normalizedModel ? findModel(normalizedModel, modelCatalog) : undefined;
|
||||
if (!selectedModel) {
|
||||
throw new Error(`Model "${model}" is not available.`);
|
||||
}
|
||||
if (!isReasoningEffort(reasoningEffort)) {
|
||||
if (reasoningEffort && !isReasoningEffort(reasoningEffort)) {
|
||||
throw new Error(`Reasoning effort "${reasoningEffort}" is not supported.`);
|
||||
}
|
||||
|
||||
session.scratchpadConfig = {
|
||||
...(createScratchpadSessionConfig(pattern) ?? {}),
|
||||
model: normalizedModel,
|
||||
reasoningEffort,
|
||||
reasoningEffort: resolveReasoningEffort(selectedModel, reasoningEffort),
|
||||
};
|
||||
session.updatedAt = nowIso();
|
||||
|
||||
@@ -449,6 +469,28 @@ export class KopayaAppService extends EventEmitter<AppServiceEvents> {
|
||||
return workspace;
|
||||
}
|
||||
|
||||
private async loadAvailableModelCatalog() {
|
||||
try {
|
||||
const capabilities = await this.describeSidecarCapabilities();
|
||||
return buildAvailableModelCatalog(capabilities.models);
|
||||
} catch {
|
||||
return buildAvailableModelCatalog();
|
||||
}
|
||||
}
|
||||
|
||||
private async buildEffectivePattern(
|
||||
project: ProjectRecord,
|
||||
pattern: PatternDefinition,
|
||||
session: SessionRecord,
|
||||
): Promise<PatternDefinition> {
|
||||
const patternWithSessionConfig = isScratchpadProject(project)
|
||||
? applyScratchpadSessionConfig(pattern, session)
|
||||
: pattern;
|
||||
|
||||
const modelCatalog = await this.loadAvailableModelCatalog();
|
||||
return normalizePatternModels(patternWithSessionConfig, modelCatalog);
|
||||
}
|
||||
|
||||
private emitSessionEvent(event: SessionEventRecord): void {
|
||||
this.emit('session-event', event);
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ import type {
|
||||
import { KopayaAppService } from '@main/KopayaAppService';
|
||||
|
||||
export function registerIpcHandlers(window: BrowserWindow, service: KopayaAppService): void {
|
||||
ipcMain.handle(ipcChannels.describeSidecarCapabilities, () => service.describeSidecarCapabilities());
|
||||
ipcMain.handle(ipcChannels.loadWorkspace, () => service.loadWorkspace());
|
||||
ipcMain.handle(ipcChannels.addProject, () => service.addProject());
|
||||
ipcMain.handle(ipcChannels.removeProject, (_event, projectId: string) => service.removeProject(projectId));
|
||||
|
||||
Reference in New Issue
Block a user