feat(coding): add plugin capability policy registry
This commit is contained in:
1 parent
d9c9a2b0dd
commit
a0361a3cda
14 files changed
+2169
-245
No files matched your search
@@ -18,6 +18,7 @@ import {
|
||||
} from '../../electron/coding-projects/skill-registry';
|
||||
import { PiProductTools } from '../../electron/coding-runtime/pi/product-tools';
|
||||
import { productToolDetails } from '../../electron/coding-runtime/product-tool-protocol';
|
||||
import type { CodingCapabilityRegistry } from '../../electron/coding-plugins/registry';
|
||||
import type { DataServiceOperations } from '../../electron/services/data-service-client';
|
||||
|
||||
const exec = promisify(execFile);
|
||||
@@ -233,35 +234,38 @@ describe('PI-090 product tools', () => {
|
||||
})).toBeNull();
|
||||
expect(productToolDetails({ schema: 'task-state.v1', tasks: [] })).toBeNull();
|
||||
expect(productToolDetails({
|
||||
schema: 'data-service.v1',
|
||||
operation: 'data_service_inspect',
|
||||
schema: 'makelore-capability.v1',
|
||||
plugin_id: 'makelore.data-service',
|
||||
plugin_version: '1.0.0',
|
||||
capability_id: 'data-service.control',
|
||||
operation: 'inspect',
|
||||
request_id: 'pi:run-a:resource-a',
|
||||
success: true,
|
||||
status: 200,
|
||||
code: null,
|
||||
error: null,
|
||||
retryable: false,
|
||||
billing: { mode: 'included', status: 'included' },
|
||||
payload_schema: 'data-service.v1',
|
||||
data: { instance_id: 'instance-a' },
|
||||
owner: 'must-be-dropped',
|
||||
})).toEqual({
|
||||
schema: 'data-service.v1',
|
||||
operation: 'data_service_inspect',
|
||||
success: true,
|
||||
status: 200,
|
||||
code: null,
|
||||
error: null,
|
||||
retryable: false,
|
||||
data: { instance_id: 'instance-a' },
|
||||
});
|
||||
expect(productToolDetails({
|
||||
schema: 'data-service.v1',
|
||||
operation: 'data_service_unknown',
|
||||
success: true,
|
||||
status: 200,
|
||||
code: null,
|
||||
error: null,
|
||||
retryable: false,
|
||||
data: null,
|
||||
})).toBeNull();
|
||||
expect(productToolDetails({
|
||||
schema: 'makelore-capability.v1',
|
||||
plugin_id: 'makelore.data-service',
|
||||
plugin_version: '1.0.0',
|
||||
capability_id: 'data-service.control',
|
||||
operation: 'inspect',
|
||||
request_id: 'pi:run-a:resource-a',
|
||||
success: true,
|
||||
status: 200,
|
||||
code: null,
|
||||
error: null,
|
||||
retryable: false,
|
||||
billing: { mode: 'included', status: 'included' },
|
||||
payload_schema: 'data-service.v1',
|
||||
data: null,
|
||||
})).toMatchObject({ schema: 'makelore-capability.v1', operation: 'inspect' });
|
||||
});
|
||||
|
||||
it('stores browser screenshots as attachment ids and never returns base64', async () => {
|
||||
@@ -413,12 +417,42 @@ describe('PI-090 product tools', () => {
|
||||
expect(dataService.reset).toHaveBeenCalledWith({ confirmed: true }, root);
|
||||
expect(dataService.removeProject).toHaveBeenCalledWith({ confirmed: true }, root);
|
||||
expect(removed.details).toMatchObject({
|
||||
schema: 'data-service.v1', operation: 'data_service_remove_project',
|
||||
schema: 'makelore-capability.v1', operation: 'remove_project',
|
||||
plugin_id: 'makelore.data-service', request_id: 'pi:run-a:resource-a',
|
||||
billing: { mode: 'included', status: 'included' }, payload_schema: 'data-service.v1',
|
||||
success: true, status: 200, data: { removed: true },
|
||||
});
|
||||
expect(JSON.stringify(removed)).not.toContain(root);
|
||||
});
|
||||
|
||||
it('delegates any non-core product tool to the capability registry', async () => {
|
||||
const root = await temporaryRoot('makelore-pi-generic-plugin-');
|
||||
const invoke = vi.fn().mockResolvedValue({
|
||||
content: [{ type: 'text', text: 'plugin-result' }],
|
||||
details: {
|
||||
schema: 'makelore-capability.v1', plugin_id: 'makelore.example', plugin_version: '1.0.0',
|
||||
capability_id: 'example.capability', operation: 'run', request_id: 'pi:run-a:resource-a',
|
||||
success: true, status: 200, code: null, error: null, retryable: false,
|
||||
billing: { mode: 'included', status: 'included' }, payload_schema: 'example.v1', data: {},
|
||||
},
|
||||
});
|
||||
const registry = { invoke } as unknown as CodingCapabilityRegistry;
|
||||
const tools = new PiProductTools({
|
||||
browser: {} as AgentBrowserModule,
|
||||
attachments: new CodingAttachmentStore(path.join(root, 'attachments')),
|
||||
bundledSkillsDir: path.resolve('resources/coding-skills'),
|
||||
capabilityRegistry: registry,
|
||||
});
|
||||
const context = {
|
||||
conversationId: 'conversation-a', runId: 'run-a', resourceId: 'resource-a',
|
||||
projectId: 'local-project-a', projectPath: root, skillIds: [],
|
||||
};
|
||||
await tools.execute('example_tool', context, { value: 1 });
|
||||
expect(invoke).toHaveBeenCalledWith({
|
||||
toolName: 'example_tool', context, workerRole: 'parent', effectiveSkillIds: [], value: { value: 1 },
|
||||
});
|
||||
});
|
||||
|
||||
it('rejects forbidden tool fields and destructive calls without literal confirmation', async () => {
|
||||
const root = await temporaryRoot('makelore-pi-data-input-');
|
||||
const dataService = {
|
||||
@@ -438,15 +472,17 @@ describe('PI-090 product tools', () => {
|
||||
projectId: 'local-project-a', projectPath: root, skillIds: [],
|
||||
};
|
||||
|
||||
await expect(tools.execute('data_service_inspect', context, { owner: 'owner-a' })).rejects.toThrow(
|
||||
'Data Service tool input is invalid',
|
||||
);
|
||||
await expect(tools.execute('data_service_inspect', context, { owner: 'owner-a' })).resolves.toMatchObject({
|
||||
details: { schema: 'makelore-capability.v1', code: 'plugin_input_invalid', status: 422 },
|
||||
});
|
||||
await expect(tools.execute('data_service_put_document', context, {
|
||||
collection: 'todos', document_id: 'one', data: {}, path: root,
|
||||
})).rejects.toThrow('Data Service tool input is invalid');
|
||||
await expect(tools.execute('data_service_remove_project', context, { confirmed: false })).rejects.toThrow(
|
||||
'Data Service tool input is invalid',
|
||||
);
|
||||
})).resolves.toMatchObject({
|
||||
details: { schema: 'makelore-capability.v1', code: 'plugin_input_invalid', status: 422 },
|
||||
});
|
||||
await expect(tools.execute('data_service_remove_project', context, { confirmed: false })).resolves.toMatchObject({
|
||||
details: { schema: 'makelore-capability.v1', code: 'plugin_input_invalid', status: 422 },
|
||||
});
|
||||
expect(dataService.inspect).not.toHaveBeenCalled();
|
||||
expect(dataService.removeProject).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user