Просмотр исходного кода

fix(api): restore migrated remote coverage

imccyu 1 месяц назад
Родитель
Сommit
812556040d

+ 1 - 1
packages/client/ui-skill/src/client/index.ts

@@ -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.

+ 1 - 1
packages/client/ui-skill/tests/browser-plugin.client.spec.ts

@@ -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 () => {

+ 10 - 0
packages/host/apiproxy/tests/fetch-carrier.spec.ts

@@ -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
packages/llm/llm/tests/service.spec.ts

@@ -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 - 0
packages/llm/llm/tests/topology.spec.ts

@@ -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([]))