Browse Source

修复 OpenViking user key 响应解析

Samien 1 month ago
parent
commit
a103d9e19f
2 changed files with 16 additions and 4 deletions
  1. 2 2
      src/server/openVikingService.ts
  2. 14 2
      tests/server/openViking.test.ts

+ 2 - 2
src/server/openVikingService.ts

@@ -26,7 +26,7 @@ function mapError(error: unknown, operation: string): never {
 
 function apiKeyFromResult(value: Record<string, unknown>): string {
   const user = value.user && typeof value.user === 'object' ? value.user as Record<string, unknown> : undefined
-  const key = value.apiKey ?? value.api_key ?? value.key ?? value.token ?? user?.apiKey ?? user?.api_key
+  const key = value.user_key ?? value.userKey ?? value.apiKey ?? value.api_key ?? value.key ?? value.token ?? user?.user_key ?? user?.userKey ?? user?.apiKey ?? user?.api_key
   if (typeof key !== 'string' || !key) throw new Error('server did not return a user API key')
   return key
 }
@@ -89,7 +89,7 @@ export class OpenVikingService {
       try {
         result = await this.adminClient().adminRegisterUser(this.#configuration.accountId, userId, 'user', { seed: `yaoyao:${agent.id}` }) as Record<string, unknown>
       } catch (error) {
-        if (!(error instanceof OpenVikingError) || !['EXISTS', 'CONFLICT', 'ALREADY_EXISTS'].includes(error.code)) throw error
+        if (!(error instanceof OpenVikingError) || !['EXISTS', 'USER_EXISTS', 'CONFLICT', 'ALREADY_EXISTS'].includes(error.code)) throw error
         result = await this.adminClient().adminRegenerateKey(this.#configuration.accountId, userId, `yaoyao:${agent.id}`) as Record<string, unknown>
       }
       const binding: OpenVikingUserBinding = {

+ 14 - 2
tests/server/openViking.test.ts

@@ -16,8 +16,8 @@ let home: string, store: WorkspaceStore, manager: OpenVikingConfigurationManager
 const files = new Map<string, string>()
 const removed = new Set<string>()
 const admin = {
-  adminRegisterUser: vi.fn(async () => ({ apiKey: `user-key-${admin.adminRegisterUser.mock.calls.length}` })),
-  adminRegenerateKey: vi.fn(async () => ({ apiKey: 'regenerated-key' })),
+  adminRegisterUser: vi.fn(async () => ({ user_key: `user-key-${admin.adminRegisterUser.mock.calls.length}` })),
+  adminRegenerateKey: vi.fn(async () => ({ user_key: 'regenerated-key' })),
   adminRemoveUser: vi.fn(async () => ({ ok: true })),
 }
 const clients = new Map<string, { apiKey: string; client: unknown }>()
@@ -93,6 +93,18 @@ describe('OpenViking memory provider', () => {
     expect(admin.adminRemoveUser).toHaveBeenCalledWith('account', binding.userId)
     expect(store.require(owner, 'openviking-binding', a.id).status).toBe('removed')
   })
+  it('recovers an existing remote user without a local key binding', async () => {
+    admin.adminRegisterUser.mockResolvedValueOnce({})
+    await expect(service.ensureUser(owner, a)).rejects.toThrowError(expect.objectContaining({ code: 'openviking_unavailable' }))
+
+    admin.adminRegisterUser.mockRejectedValueOnce(new OpenVikingError('user exists', { code: 'USER_EXISTS', statusCode: 409 }))
+    const binding = await service.ensureUser(owner, a)
+    expect(binding.userId).toBe(openVikingUserId(a.id))
+    expect(JSON.stringify(binding)).not.toContain('regenerated-key')
+    expect(admin.adminRegenerateKey).toHaveBeenCalledWith('account', binding.userId, `yaoyao:${a.id}`)
+    expect(service.userClient(owner, a.id)).toBeTruthy()
+    expect(clients.get(binding.userId)?.apiKey).toBe('regenerated-key')
+  })
   it('keeps user memory isolated per contributing Bot', async () => {
     await knowledge.writeMemory(owner, { requestId: randomUUID(), scope: 'user', agentId: a.id, topic: '接口', content: '甲认为使用版本一', tier: 'profile' })
     await knowledge.writeMemory(owner, { requestId: randomUUID(), scope: 'user', agentId: b.id, topic: '接口', content: '乙认为使用版本二', tier: 'profile' })