feat(coding): add model tools and device packages

This commit is contained in:
2026-09-02 18:35:26 +08:00
parent 841273b433
commit 664b8823a0
60 changed files with 3847 additions and 2068 deletions

View File

@@ -7,7 +7,6 @@ import {
} from '../../electron/coding-plugins/registry';
import type { CodingPluginAdapter } from '../../electron/coding-plugins/registry';
import { createDataServicePluginAdapter } from '../../electron/coding-plugins/adapters/data-service';
import { createWebSearchPluginAdapter } from '../../electron/coding-plugins/adapters/web-search';
import {
createDataServiceOperations,
DataServiceCloudClient,
@@ -333,150 +332,6 @@ describe('CodingCapabilityRegistry', () => {
expect(invoke).toHaveBeenCalledTimes(1);
});
it('materializes Web Search only for the parent snapshot and rejects the old worker after disable', async () => {
const definition: CodingPluginDefinition = {
id: 'makelore.web-search', version: '1.0.0', contractVersion: 1,
displayName: 'Web Search', description: 'Hosted web search',
runtimeKind: 'platform_hosted', acquisitionMode: 'user_acquired',
releaseId: 'release-web-search-1',
provenance: { source: 'marketplace', packageRoot: 'C:/packages/web-search' },
scope: 'project', adapterId: 'makelore.web-search', requiresBackend: true,
skills: [{
id: 'web-search', entryPath: 'skills/web-search/SKILL.md', grants: ['web-search.search'],
}],
tools: [{
name: 'makelore_web_search', label: 'Web Search', description: 'Search the web',
capabilityId: 'web-search.search', operation: 'search', roles: ['parent'],
mutation: 'read', projectWriteLease: false,
permissions: ['hosted.web-search.search'], executionMode: 'synchronous',
inputSchema: {
type: 'object', additionalProperties: false, required: ['query', 'confirmed'],
properties: { query: { type: 'string' }, confirmed: { type: 'boolean' } },
},
}],
operations: [{
capabilityId: 'web-search.search', operation: 'search', toolName: 'makelore_web_search',
}],
surfaces: {},
};
const billing = {
mode: 'platform_metered' as const, entitlement_scope: 'plugin_usage', notice: 'Metered',
unit_name: 'search_request', unit_size: 1, rate_points: '1.00',
minimum_charge_points: '1.00', rounding_mode: 'ceil' as const,
};
const webSearchPolicy: PluginPolicyClientState = {
status: 'current', revision: 10, lastVerifiedAt: 1,
catalog: {
schema_version: 1, catalog_version: 'web-search-1', pricing_version: 'pricing-1',
plugins: [{
plugin_id: definition.id, supported_contract_versions: [1], status: 'active',
capabilities: [{
capability_id: 'web-search.search', operations: [{ operation: 'search', billing }],
}],
}],
},
};
const frozen: EffectivePluginSnapshot = {
accountSessionId: 'account-a\u00001', projectId: context.projectId,
pluginReleaseIds: ['release-web-search-1'], effectiveSkillIds: ['web-search'],
skillEntries: [{
id: 'web-search', entryPath: 'skills/web-search/SKILL.md', packageRoot: 'C:/packages/web-search',
}],
toolDefinitions: definition.tools,
runtimePolicies: [{
pluginId: definition.id, pluginVersion: definition.version,
releaseId: definition.releaseId, contractVersion: 1,
capabilityId: 'web-search.search', operation: 'search', billing,
}],
unavailableReasons: [],
};
const disabled: EffectivePluginSnapshot = {
...frozen, pluginReleaseIds: [], effectiveSkillIds: [], skillEntries: [],
toolDefinitions: [], runtimePolicies: [],
unavailableReasons: [{
pluginId: definition.id, code: 'project_disabled', message: 'Plugin is not enabled',
}],
};
let current = frozen;
const resolve = vi.fn(async ({ role }: { role: 'parent' | 'child' }) => (
role === 'child' ? { ...disabled, unavailableReasons: [] } : current
));
const resolveForInvocation = vi.fn(async () => current);
const effectiveResolver = {
resolve,
resolveForInvocation,
getSkillSources: vi.fn(async () => [{
id: 'web-search', pluginId: definition.id, packageRoot: 'C:/packages/web-search',
directory: 'C:/packages/web-search/skills/web-search', entryPath: 'SKILL.md',
}]),
getPolicyState: vi.fn(() => webSearchPolicy),
getInstalledDefinition: vi.fn(async () => definition),
} as unknown as EffectivePluginResolver;
const search = vi.fn().mockResolvedValue({
executionId: 'execution-web-1', releaseId: definition.releaseId,
logicalOperationId: 'pi:run-a:resource-a', status: 'succeeded',
answer: 'A bounded answer', sources: [{ title: 'Source', url: 'https://example.com' }],
searchQueries: ['Makelore'], errorCode: null,
billing: {
mode: 'platform_metered', status: 'settled', reserved_points: '1.00',
actual_points: '1.00', usage_amount: 1, unit: 'search_request',
},
});
const adapter = createWebSearchPluginAdapter({
client: { search } as never,
admissionResolver: {
resolve: vi.fn().mockResolvedValue({
releaseId: definition.releaseId, releaseAdmissionId: 'admission-web-1',
}),
} as never,
});
const capabilityRegistry = registry({
definitions: [], effectiveResolver, adapters: [adapter],
policyClient: { getState: () => webSearchPolicy, refresh: vi.fn() },
getEnabledPluginIds: async () => [definition.id],
});
const parent = await capabilityRegistry.resolveWorkerResources({
projectId: context.projectId, projectPath: context.projectPath,
assignedSkillIds: ['web-search'], role: 'parent',
});
const child = await capabilityRegistry.resolveWorkerResources({
projectId: context.projectId, projectPath: context.projectPath,
assignedSkillIds: ['web-search'], role: 'child',
});
expect(parent.tools.map(({ name }) => name)).toEqual(['makelore_web_search']);
expect(parent.effectiveSkillIds).toEqual(['web-search']);
expect(child.tools).toEqual([]);
expect(child.effectiveSkillIds).toEqual([]);
const result = await capabilityRegistry.invoke({
toolName: 'makelore_web_search',
context: { ...context, skillIds: ['web-search'], effectiveSnapshot: frozen },
workerRole: 'parent', effectiveSkillIds: ['web-search'],
value: { query: ' Makelore ', confirmed: true },
});
expect(search).toHaveBeenCalledWith(expect.objectContaining({
releaseId: 'release-web-search-1', releaseAdmissionId: 'admission-web-1',
logicalOperationId: 'pi:run-a:resource-a', query: 'Makelore', confirmed: true,
}));
expect(result.details).toMatchObject({
schema: 'makelore-capability.v1', plugin_id: 'makelore.web-search',
capability_id: 'web-search.search', operation: 'search',
payload_schema: 'web-search.v1', billing: { status: 'settled', actual_points: '1.00' },
});
expect(resolveForInvocation).toHaveBeenCalledOnce();
current = disabled;
const stale = await capabilityRegistry.invoke({
toolName: 'makelore_web_search',
context: { ...context, skillIds: ['web-search'], effectiveSnapshot: frozen },
workerRole: 'parent', effectiveSkillIds: ['web-search'],
value: { query: 'Makelore', confirmed: true },
});
expect(stale.details).toMatchObject({ success: false, code: 'plugin_not_enabled' });
expect(search).toHaveBeenCalledOnce();
});
it('refuses a new plugin action from an old worker after lifecycle invalidation', async () => {
const frozenSnapshot: EffectivePluginSnapshot = {
accountSessionId: 'account-a\u00001',