feat(coding): add plugin capability policy registry
This commit is contained in:
98
tests/unit/data-service-plugin-adapter.test.ts
Normal file
98
tests/unit/data-service-plugin-adapter.test.ts
Normal file
@@ -0,0 +1,98 @@
|
||||
// @vitest-environment node
|
||||
|
||||
import { describe, expect, it, vi } from 'vitest';
|
||||
import { DATA_SERVICE_TOOL_DEFINITIONS } from '../../shared/coding-plugins';
|
||||
import type { DataServiceOperations } from '../../electron/services/data-service-client';
|
||||
import {
|
||||
createDataServicePluginAdapter,
|
||||
} from '../../electron/coding-plugins/adapters/data-service';
|
||||
|
||||
const context = {
|
||||
conversationId: 'conversation-a',
|
||||
runId: 'run-a',
|
||||
resourceId: 'resource-a',
|
||||
requestId: 'pi:run-a:resource-a',
|
||||
localProjectId: 'local-project-a',
|
||||
projectPath: 'C:\\projects\\demo',
|
||||
durableProjectId: 'durable-project-a',
|
||||
workerRole: 'parent' as const,
|
||||
effectiveSkillIds: ['data-service'],
|
||||
};
|
||||
|
||||
function success<T>(data: T) {
|
||||
return {
|
||||
success: true as const,
|
||||
status: 200,
|
||||
code: null,
|
||||
error: null,
|
||||
retryable: false as const,
|
||||
data,
|
||||
};
|
||||
}
|
||||
|
||||
function operations(): DataServiceOperations {
|
||||
return {
|
||||
configure: vi.fn().mockResolvedValue(success({ configured: true })),
|
||||
inspect: vi.fn().mockResolvedValue(success({ instance_id: 'instance-a' })),
|
||||
listProjects: vi.fn().mockResolvedValue(success({ items: [], total: 0, instance_limit: 20 })),
|
||||
getDocument: vi.fn().mockResolvedValue(success({ id: 'one', data: {}, revision: 1 })),
|
||||
listDocuments: vi.fn().mockResolvedValue(success({ items: [], next_cursor: null, limit: 50 })),
|
||||
putDocument: vi.fn().mockResolvedValue(success({ id: 'one', data: {}, revision: 1 })),
|
||||
deleteDocument: vi.fn().mockResolvedValue(success(null)),
|
||||
removeCollection: vi.fn().mockResolvedValue(success({ removed: true, usage: { document_count: 0, total_bytes: 0 } })),
|
||||
reset: vi.fn().mockResolvedValue(success({ instance_id: 'instance-a' })),
|
||||
removeProject: vi.fn().mockResolvedValue(success({ removed: true })),
|
||||
};
|
||||
}
|
||||
|
||||
describe('Data Service plugin adapter', () => {
|
||||
it('maps all ten package operations through DataServiceOperations', async () => {
|
||||
const dataService = operations();
|
||||
const adapter = createDataServicePluginAdapter(dataService);
|
||||
const inputs: Record<string, unknown> = {
|
||||
data_service_configure: { collections: ['todos'] },
|
||||
data_service_inspect: {},
|
||||
data_service_list_projects: {},
|
||||
data_service_get_document: { collection: 'todos', document_id: 'one' },
|
||||
data_service_list_documents: { collection: 'todos', limit: 50, cursor: 'cursor-a' },
|
||||
data_service_put_document: { collection: 'todos', document_id: 'one', data: { done: false }, if_revision: 1 },
|
||||
data_service_delete_document: { collection: 'todos', document_id: 'one', if_revision: 1, confirmed: true },
|
||||
data_service_remove_collection: { collection: 'todos', confirmed: true },
|
||||
data_service_reset: { confirmed: true },
|
||||
data_service_remove_project: { confirmed: true },
|
||||
};
|
||||
for (const tool of DATA_SERVICE_TOOL_DEFINITIONS) {
|
||||
const result = await adapter.invoke(context, tool, inputs[tool.name]);
|
||||
expect(result).toMatchObject({ success: true, payload_schema: 'data-service.v1' });
|
||||
expect(result).not.toHaveProperty('plugin_id');
|
||||
expect(result).not.toHaveProperty('request_id');
|
||||
}
|
||||
expect(dataService.configure).toHaveBeenCalledWith({ collections: ['todos'] }, context.projectPath);
|
||||
expect(dataService.inspect).toHaveBeenCalledWith(context.projectPath);
|
||||
expect(dataService.listProjects).toHaveBeenCalledWith();
|
||||
expect(dataService.getDocument).toHaveBeenCalledWith({ collection: 'todos', document_id: 'one' }, context.projectPath);
|
||||
expect(dataService.listDocuments).toHaveBeenCalledWith({ collection: 'todos', limit: 50, cursor: 'cursor-a' }, context.projectPath);
|
||||
expect(dataService.putDocument).toHaveBeenCalledWith({
|
||||
collection: 'todos', document_id: 'one', data: { done: false }, if_revision: 1,
|
||||
}, context.projectPath);
|
||||
expect(dataService.deleteDocument).toHaveBeenCalledWith({
|
||||
collection: 'todos', document_id: 'one', if_revision: 1, confirmed: true,
|
||||
}, context.projectPath);
|
||||
});
|
||||
|
||||
it('returns bounded domain context and rejects forbidden or malformed input', async () => {
|
||||
const dataService = operations();
|
||||
const adapter = createDataServicePluginAdapter(dataService);
|
||||
const put = DATA_SERVICE_TOOL_DEFINITIONS.find(({ name }) => name === 'data_service_put_document');
|
||||
if (!put) throw new Error('put definition missing');
|
||||
const invalid = await adapter.invoke(context, put, {
|
||||
collection: 'todos', document_id: 'one', data: {}, projectPath: context.projectPath,
|
||||
});
|
||||
expect(invalid).toMatchObject({
|
||||
success: false, status: 422, code: 'plugin_input_invalid', data: null,
|
||||
});
|
||||
const result = await adapter.invoke(context, put, { collection: 'todos', document_id: 'one', data: {} });
|
||||
expect(result).toMatchObject({ success: true, payload_schema: 'data-service.v1' });
|
||||
expect(dataService.putDocument).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user