diff --git a/scripts/product-package-policy.ts b/scripts/product-package-policy.ts index 8606ff62c9..08171b05b8 100644 --- a/scripts/product-package-policy.ts +++ b/scripts/product-package-policy.ts @@ -16,6 +16,7 @@ export interface ProductPackagePolicy { * Optional integrations may be reached by an optional bundle without becoming default capabilities. */ export const PRODUCT_PACKAGE_POLICY: Readonly> = { + 'packages/core/agent-tool-presentation': { category: 'optional', reason: 'Deprecated selector retained for existing executor configurations.' }, 'packages/browser-use/browser-use': { category: 'optional', reason: 'Service definition used by explicitly selected browser providers.' }, 'packages/computer-use/computer-use': { category: 'optional', reason: 'Service definition used by explicitly selected computer providers.' }, 'packages/lsp/lsp': { category: 'optional', reason: 'Service definition for deployment-configured language servers.' }, diff --git a/scripts/verify-cordis-config.spec.ts b/scripts/verify-cordis-config.spec.ts index ec0385af10..497729b2ac 100644 --- a/scripts/verify-cordis-config.spec.ts +++ b/scripts/verify-cordis-config.spec.ts @@ -11,6 +11,7 @@ import { describe, expect, it } from 'vitest' import { bundleManifestPaths, bundlePluginDependencyErrors, + exclusivePlaneRowIds, metadataExpressionErrors, packageTestFixtureDependencyErrors, packageTestPluginDependencyErrors, @@ -48,6 +49,17 @@ describe('verify-cordis-config metadata expressions', () => { }) describe('workspace Bundle discovery and product dependency closures', () => { + it('allows scoped executors on both planes while retaining other plugin rows', () => { + expect([...exclusivePlaneRowIds([{ insert: [ + { id: 'native', name: '@deepseek-ai/dsh-tool-executor-native' }, + { id: 'ptc', name: '@deepseek-ai/dsh-tool-executor-ptc' }, + { id: 'tools', name: '@deepseek-ai/dsh-tools' }, + { id: 'group', name: 'cordis:group', group: true, config: [ + { id: 'tool-executor-ptc', name: '@deepseek-ai/dsh-tool-fs' }, + ] }, + ] }])]).toEqual(['tools', 'group', 'tool-executor-ptc']) + }) + it('discovers a Bundle outside packages/bundle from its manifest declaration', () => { const fixture = mkdtempSync(join(tmpdir(), 'dsh-bundle-discovery-')) try { diff --git a/scripts/verify-cordis-config.ts b/scripts/verify-cordis-config.ts index 76e9bdba87..1017c7e8e1 100644 --- a/scripts/verify-cordis-config.ts +++ b/scripts/verify-cordis-config.ts @@ -119,7 +119,8 @@ function validateClientHalvesDeclared(): string[] { } /** - * No shipped agent preset may repeat a row the host composition still runs. + * No shipped agent preset may repeat an unscoped row the host composition still runs. + * Tool executors select through the mounting scope and may appear on both planes. * * A preset contributes what ONE session adds to the host's registries. A row * active on both planes is therefore mounted twice — once per process and once @@ -157,7 +158,7 @@ function validatePresetPlaneSeparation(): string[] { const active = new Set([...rowIds(hostFile), ...overlayRows].filter(id => !disabled.has(id))) for (const file of overlayFiles) { for (const definition of presetDefinitions(loadEntries(file))) { - for (const id of collectRowIds(definition.plugins)) { + for (const id of exclusivePlaneRowIds(definition.plugins)) { if (active.has(id)) problems.push(`${file}#${definition.id}: row "${id}" is also active in the host composition; a row belongs to exactly one plane`) } } @@ -178,10 +179,15 @@ function loadEntries(file: string): unknown[] { * @returns the declared ids. */ function rowIds(file: string): Set { - return collectRowIds(loadEntries(file)) + return exclusivePlaneRowIds(loadEntries(file)) } -function collectRowIds(rows: unknown): Set { +/** + * Collect rows that cannot be shared between the host and a preset. + * @param rows - parsed Loader entries, including inserts and groups. + * @returns ids excluding the executor plugins whose registrations are scope-owned. + */ +export function exclusivePlaneRowIds(rows: unknown): Set { const ids = new Set() const walk = (value: unknown): void => { if (isUnknownArray(value)) { @@ -189,7 +195,9 @@ function collectRowIds(rows: unknown): Set { return } if (!isRecord(value)) return - if (typeof value.id === 'string' && typeof value.name === 'string') ids.add(value.id) + if (typeof value.id === 'string' && typeof value.name === 'string' + && value.name !== '@deepseek-ai/dsh-tool-executor-native' + && value.name !== '@deepseek-ai/dsh-tool-executor-ptc') ids.add(value.id) walk(value.insert) if (isCordisGroupEntry(value)) walk(value.config) }