import { Context } from '@deepseek-ai/cordis' import { describe, expect, it } from 'vitest' import { CordisInspectRegistryService, type HostCordisInspectProviderRegistration } from '../src/inspect-registry.ts' function makeProvider(id: string, desc: string): HostCordisInspectProviderRegistration { return { manifest: { id, description: desc, methods: [{ name: 'list', description: 'List things.', inputSchema: { type: 'object', properties: {}, additionalProperties: false }, outputSchema: { description: 'anything' }, }], }, async query() { return {} }, } } describe('CordisInspectRegistryService', () => { it('accepts the first registration of a provider id', () => { const ctx = new Context() const svc = new CordisInspectRegistryService(ctx) const p = makeProvider('Service', 'desc') const dispose = svc.register(p) expect(svc.list()).toContainEqual(expect.objectContaining({ id: 'Service', platform: 'host' })) dispose() expect(svc.list()).not.toContainEqual(expect.objectContaining({ id: 'Service' })) }) it('replaces on identical re-registration without throwing', () => { const ctx = new Context() const svc = new CordisInspectRegistryService(ctx) const p = makeProvider('Service', 'desc') const disposeA = svc.register(p) const disposeB = svc.register(p) // same object — identical manifest // Still in the directory (replaced, not removed) expect(svc.list()).toContainEqual(expect.objectContaining({ id: 'Service', platform: 'host' })) // disposeA should be a no-op because the map entry was replaced disposeA() expect(svc.list()).toContainEqual(expect.objectContaining({ id: 'Service', platform: 'host' })) // disposeB removes the current registration disposeB() expect(svc.list()).not.toContainEqual(expect.objectContaining({ id: 'Service' })) }) it('rejects a different manifest claiming the same id', () => { const ctx = new Context() const svc = new CordisInspectRegistryService(ctx) svc.register(makeProvider('Service', 'original')) expect(() => svc.register(makeProvider('Service', 'different'))) .toThrow('Host Cordis inspect provider "Service" is already registered') }) it('rejects empty provider id', () => { const ctx = new Context() const svc = new CordisInspectRegistryService(ctx) expect(() => svc.register(makeProvider('', 'empty'))) .toThrow('Cordis inspect provider id must not be empty') }) it('detects method-array length mismatch as unequal', () => { const ctx = new Context() const svc = new CordisInspectRegistryService(ctx) const a: HostCordisInspectProviderRegistration = { manifest: { id: 'X', description: 'd', methods: [{ name: 'a', description: 'a', inputSchema: {}, outputSchema: {} }], }, async query() { return {} }, } const b: HostCordisInspectProviderRegistration = { manifest: { id: 'X', description: 'd', methods: [ { name: 'a', description: 'a', inputSchema: {}, outputSchema: {} }, { name: 'b', description: 'b', inputSchema: {}, outputSchema: {} }, ], }, async query() { return {} }, } svc.register(a) expect(() => svc.register(b)).toThrow('already registered') }) })