fix(api): restore migrated remote coverage

This commit is contained in:
imccyu
2026-08-27 21:57:57 +08:00
parent 88f2f0aaec
commit 812556040d
5 changed files with 73 additions and 4 deletions
+1 -1
View File
@@ -58,7 +58,7 @@ interface CatalogFetch {
}
/** Required services: reference source faces plus the tool-row and locale registries. */
export const inject = ['inputTriggers', 'connection', 'sessions', 'slots', 'locale', 'remote']
export const inject = ['inputTriggers', 'connection', 'sessions', 'slots', 'locale', 'remote', 'remote.skills']
/**
* Client plugin body: register the '/' source, dictionaries, and keyed tool row.
@@ -102,7 +102,7 @@ const req = (query: string, signal?: AbortSignal) =>
describe('apply', () => {
it('declares the services it binds', () => {
expect(inject).toEqual(['inputTriggers', 'connection', 'sessions', 'slots', 'locale', 'remote'])
expect(inject).toEqual(['inputTriggers', 'connection', 'sessions', 'slots', 'locale', 'remote', 'remote.skills'])
})
it('registers the dedicated skill row and its locale dictionaries', async () => {
@@ -81,6 +81,16 @@ describe('handler carrier-layer statuses', () => {
expect(parsed.result.error?.details.issues.length).toBeGreaterThan(0)
})
it('rejects a request whose envelope method does not match its path', async () => {
const body = JSON.stringify({ type: 'client-request', rpcId: 'r-mismatch', method: 'other.method', payload: {} })
const response = await handler.fetch(new Request('http://x/api/host.describe', { method: 'POST', headers: { 'content-type': 'application/json' }, body }))
const parsed = await response.json() as { result: { error?: { code: string; message: string } } }
expect(parsed.result.error).toMatchObject({
code: 'bad-request',
message: 'method "other.method" does not match path "host.describe"',
})
})
it('500s when the impl itself throws', async () => {
const crashing = toFetchHandler(fakeApi({ crashOn: 'host.describe' }))
const body = JSON.stringify({ type: 'client-request', rpcId: 'r-11', method: 'host.describe', payload: {} })
+9 -2
View File
@@ -525,13 +525,20 @@ describe('LlmRuntime', () => {
const ctx = new Context()
await ctx.plugin(LlmRuntime)
const provider = { id: 'catalog', name: 'Catalog Provider' }
const model = { provider: 'catalog', id: 'fast', name: 'Fast', description: 'Low latency' }
const model = {
provider: 'catalog',
id: 'fast',
name: 'Fast',
description: 'Low latency',
inputModalities: ['text'] as const,
}
ctx.llm.registerAdapter(['catalog'], new CatalogAdapter(provider, [model]))
const providers = ctx.llm.listProviders()
const models = await ctx.llm.listModels('catalog')
expect(providers).toEqual([provider])
expect(models).toEqual([model])
expect(models[0]!.inputModalities).not.toBe(model.inputModalities)
providers[0]!.name = 'mutated'
models[0]!.name = 'mutated'
@@ -539,7 +546,7 @@ describe('LlmRuntime', () => {
model.name = 'source mutated'
expect(ctx.llm.listProviders()).toEqual([{ id: 'catalog', name: 'Catalog Provider' }])
await expect(ctx.llm.listModels('catalog')).resolves.toEqual([{
provider: 'catalog', id: 'fast', name: 'source mutated', description: 'Low latency',
provider: 'catalog', id: 'fast', name: 'source mutated', description: 'Low latency', inputModalities: ['text'],
}])
})
+52
View File
@@ -250,6 +250,58 @@ describe('model discovery registry', () => {
])
})
it('carries cancellation into Remote discovery and maps provider failures', async () => {
const ctx = await setup()
const discover = vi.fn()
.mockResolvedValueOnce([
{ id: 'keep', name: 'Keep', contextWindow: 1024, maxTokens: 256 },
{ id: '' },
{ id: 'keep' },
{ id: 'bare' },
])
.mockRejectedValueOnce(new Error('endpoint offline'))
.mockRejectedValueOnce('provider refused')
ctx.llm.registerModelDiscovery('llm-example', discover)
const signal = new AbortController().signal
await expect(ctx.llm.remoteDiscoverModels(
'llm-example',
{ baseURL: 'https://gateway.example/v1' },
signal,
)).resolves.toEqual([
{ id: 'keep', name: 'Keep', contextWindow: 1024, maxTokens: 256 },
{ id: 'bare' },
])
expect(discover).toHaveBeenNthCalledWith(
1,
{ baseURL: 'https://gateway.example/v1' },
signal,
)
await expect(ctx.llm.remoteDiscoverModels(
'llm-example',
{ baseURL: 'https://gateway.example/v1' },
signal,
)).rejects.toMatchObject({
failure: {
code: 'model-discovery-failed',
message: 'endpoint offline',
details: { settingsNs: 'llm-example', baseURL: 'https://gateway.example/v1' },
},
})
await expect(ctx.llm.remoteDiscoverModels(
'llm-example',
{ provider: 'known-route' },
signal,
)).rejects.toMatchObject({
failure: {
code: 'model-discovery-failed',
message: 'provider refused',
details: { settingsNs: 'llm-example' },
},
})
})
it('refuses a namespace nothing serves and a draft with no endpoint', async () => {
const ctx = await setup()
ctx.llm.registerModelDiscovery('llm-example', () => Promise.resolve([]))