fix: prevent partial tool leaks and non-blocking dispose

- syncTools: on paginated listTools failure, unregister any tools already
  registered in the current sync before rethrowing (prevents orphans)
- Effect disposer: call client.close() directly without awaiting startup
  completion — aborts a hanging connect promptly on HMR/dispose
This commit is contained in:
lintianle
2026-07-08 13:23:46 +08:00
parent 0c8f2f7daf
commit 418b259a11

View File

@@ -119,6 +119,18 @@ describe('syncTools', () => {
expect(secondDisposers.size).toBe(1)
})
it('cleans up already-registered tools when a later page fails', async () => {
const client = createMockClient([])
client.listTools
.mockResolvedValueOnce({ tools: [{ name: 'survives_not', inputSchema: { type: 'object' } }], nextCursor: 'cursor1' })
.mockRejectedValueOnce(new Error('page 2 network error'))
await expect(syncTools(client as never, ctx, defaultOpts, new Map())).rejects.toThrow('page 2 network error')
// The tool from page 1 was registered then cleaned up on failure.
expect(ctx.tools.get('survives_not')).toBeUndefined()
})
it('drains paginated listTools responses', async () => {
const client = createMockClient([])
client.listTools