diff --git a/apps/desktop/src/main/__tests__/skills.test.ts b/apps/desktop/src/main/__tests__/skills.test.ts index 9cb94764cda..3987f9da7fd 100644 --- a/apps/desktop/src/main/__tests__/skills.test.ts +++ b/apps/desktop/src/main/__tests__/skills.test.ts @@ -108,11 +108,11 @@ Use the Office tools.`); assert.match(mainProcess, /hostCapabilities: desktopHostCapabilities/); assert.match(mainProcess, /buildSkillsPromptFragment\(\s*skillSource,\s*options\?\.host \?\? deps\.host \?\? deps\.hostCapabilities,\s*options\?\.skillBudget,\s*\)/); assert.match(mainProcess, /buildSkillAgentTool\([\s\S]*resolveDesktopSkillHost(?:,\s*)?\)/); - assert.match(mainProcess, /const backendSkillHost: HostCapabilities =/); + assert.match(mainProcess, /const backendSkillHost = buildHostCapabilitiesFromBinding\(backendToolNames\)/); + assert.doesNotMatch(mainProcess, /const backendCapabilities = new Set\(\)/); assert.match(mainProcess, /\[\.\.\.builtinTools, \.\.\.buildMcpTools\(mcpManager\)\]/); assert.match(mainProcess, /const backendTools = computerUseToolsForModel\(/); assert.match(mainProcess, /const backendToolNames = new Set\(/); - assert.match(mainProcess, /if \(tools\.some\(\(tool\) => backendToolNames\.has\(tool\.name\)\)\) backendCapabilities\.add\(capability\)/); assert.match(mainProcess, /backendTools\.map\(\(tool\) => tool\.name\)/); assert.match(mainProcess, /if \(!ctx\.tools\) desktopSessionSkillHosts\.set\(ctx\.sessionId, backendSkillHost\)/); assert.match(mainProcess, /host: backendSkillHost/); diff --git a/apps/desktop/src/main/main.ts b/apps/desktop/src/main/main.ts index 86a2586213c..49259413a56 100644 --- a/apps/desktop/src/main/main.ts +++ b/apps/desktop/src/main/main.ts @@ -679,9 +679,6 @@ backends.register('ai-sdk', createAiSdkBackendFactory({ telemetryRepo, artifactStore, desktopSessionSkillHosts, - riveTools, - officeTools, - browserTools, computerUseTools, agentTeamLeadTools, builtinTools, diff --git a/apps/desktop/src/main/session-stream.ts b/apps/desktop/src/main/session-stream.ts index b11adad514a..e64c6ac0d9a 100644 --- a/apps/desktop/src/main/session-stream.ts +++ b/apps/desktop/src/main/session-stream.ts @@ -7,6 +7,7 @@ import { AiSdkBackend, buildDefaultContextBudgetPolicy, buildExpertDispatchToolForTeamId, + buildHostCapabilitiesFromBinding, buildLlmHistorySummarizer, buildMcpTools, buildProviderOptions, @@ -85,9 +86,6 @@ export interface AiSdkBackendFactoryDeps { telemetryRepo: TelemetryRepo; artifactStore: ArtifactStore; desktopSessionSkillHosts: Map; - riveTools: AssembledTools['riveTools']; - officeTools: AssembledTools['officeTools']; - browserTools: AssembledTools['browserTools']; computerUseTools: AssembledTools['computerUseTools']; agentTeamLeadTools: AssembledTools['agentTeamLeadTools']; builtinTools: AssembledTools['builtinTools']; @@ -123,9 +121,6 @@ export function createAiSdkBackendFactory(deps: AiSdkBackendFactoryDeps): Backen telemetryRepo, artifactStore, desktopSessionSkillHosts, - riveTools, - officeTools, - browserTools, computerUseTools, agentTeamLeadTools, builtinTools, @@ -179,19 +174,7 @@ export function createAiSdkBackendFactory(deps: AiSdkBackendFactoryDeps): Backen ...backendTools.map((tool) => tool.name), ...(expertDispatchTool ? [expertDispatchTool.name, ...agentTeamLeadTools.map((tool) => tool.name)] : []), ]); - const backendCapabilities = new Set(); - for (const [capability, tools] of [ - ['rive', riveTools], - ['office', officeTools], - ['browser', browserTools], - ['computer_use', computerUseTools], - ] as const) { - if (tools.some((tool) => backendToolNames.has(tool.name))) backendCapabilities.add(capability); - } - const backendSkillHost: HostCapabilities = { - toolNames: backendToolNames, - capabilities: backendCapabilities, - }; + const backendSkillHost = buildHostCapabilitiesFromBinding(backendToolNames); // Child backends share the parent sessionId but intentionally have a // narrower tool surface. They do not receive the Desktop Skill tool, so // they must not overwrite the parent session's resolver entry. diff --git a/packages/runtime/src/skills.ts b/packages/runtime/src/skills.ts index a405a67962a..2620a732c50 100644 --- a/packages/runtime/src/skills.ts +++ b/packages/runtime/src/skills.ts @@ -504,7 +504,7 @@ export async function buildSkillsPromptFragment( let skills = (await scanSkills(source)).filter((skill) => skill.enabled); // Gate before prompt-budget truncation so a host lacking a required tool // never advertises the skill. `host === undefined` keeps the legacy - // no-gating behavior (desktop call sites stay unchanged). + // no-gating behavior. if (host) skills = gateSkillsByHostCapabilities(skills, host).filter((gated) => gated.eligible); if (skills.length === 0) return undefined; @@ -575,8 +575,7 @@ export function loadSkillInstructionsFromScan( const raw = typeof name === 'string' ? name.trim() : ''; const enabledSkills = skills.filter((skill) => skill.enabled); // Gate eligible skills before exposing them as available or loading them. - // `host === undefined` keeps the legacy no-gating behavior (desktop call - // sites stay unchanged). + // `host === undefined` keeps the legacy no-gating behavior. const gated = host ? gateSkillsByHostCapabilities(enabledSkills, host) : enabledSkills.map((skill) => ({