mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-15 21:05:51 +00:00
Compare commits
4 Commits
v2.6.9
...
codex/code
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d3b16ae040 | ||
|
|
a90c16431b | ||
|
|
a5ede237f0 | ||
|
|
85dc1b9462 |
@@ -109,6 +109,10 @@ describe('startAgentSummarization', () => {
|
|||||||
lastTimerHandle = undefined
|
lastTimerHandle = undefined
|
||||||
})
|
})
|
||||||
|
|
||||||
|
function expectDebugLogContaining(fragment: string): void {
|
||||||
|
expect(debugLogs.some(message => message.includes(fragment))).toBe(true)
|
||||||
|
}
|
||||||
|
|
||||||
test('summarizes bounded transcript once and skips unchanged fingerprints', async () => {
|
test('summarizes bounded transcript once and skips unchanged fingerprints', async () => {
|
||||||
handle = startTestSummarization()
|
handle = startTestSummarization()
|
||||||
|
|
||||||
@@ -157,7 +161,7 @@ describe('startAgentSummarization', () => {
|
|||||||
|
|
||||||
expect(forkCalls).toEqual([])
|
expect(forkCalls).toEqual([])
|
||||||
expect(updateCalls).toEqual([])
|
expect(updateCalls).toEqual([])
|
||||||
expect(debugLogs).toContain(
|
expectDebugLogContaining(
|
||||||
'[AgentSummary] Skipping summary for task-1: no bounded context available',
|
'[AgentSummary] Skipping summary for task-1: no bounded context available',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -171,7 +175,7 @@ describe('startAgentSummarization', () => {
|
|||||||
|
|
||||||
expect(forkCalls).toEqual([])
|
expect(forkCalls).toEqual([])
|
||||||
expect(updateCalls).toEqual([])
|
expect(updateCalls).toEqual([])
|
||||||
expect(debugLogs).toContain(
|
expectDebugLogContaining(
|
||||||
'[AgentSummary] Skipping summary for task-1: not enough messages (2)',
|
'[AgentSummary] Skipping summary for task-1: not enough messages (2)',
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
@@ -188,9 +192,7 @@ describe('startAgentSummarization', () => {
|
|||||||
|
|
||||||
expect(forkCalls).toEqual([])
|
expect(forkCalls).toEqual([])
|
||||||
expect(updateCalls).toEqual([])
|
expect(updateCalls).toEqual([])
|
||||||
expect(debugLogs).toContain(
|
expectDebugLogContaining('[AgentSummary] Skipping summary — poor mode active')
|
||||||
'[AgentSummary] Skipping summary — poor mode active',
|
|
||||||
)
|
|
||||||
expect(scheduledCount).toBe(initialScheduledCount + 1)
|
expect(scheduledCount).toBe(initialScheduledCount + 1)
|
||||||
expect(lastTimerHandle).not.toBe(initialTimerHandle)
|
expect(lastTimerHandle).not.toBe(initialTimerHandle)
|
||||||
})
|
})
|
||||||
@@ -220,9 +222,7 @@ describe('startAgentSummarization', () => {
|
|||||||
|
|
||||||
handle.stop()
|
handle.stop()
|
||||||
|
|
||||||
expect(debugLogs).toContain(
|
expectDebugLogContaining('[AgentSummary] Stopping summarization for task-1')
|
||||||
'[AgentSummary] Stopping summarization for task-1',
|
|
||||||
)
|
|
||||||
expect(clearedHandles).toEqual([pendingHandle])
|
expect(clearedHandles).toEqual([pendingHandle])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -365,7 +365,11 @@ describe('teammate mailbox retention', () => {
|
|||||||
if (code === undefined) {
|
if (code === undefined) {
|
||||||
throw new Error('Expected filesystem errno code')
|
throw new Error('Expected filesystem errno code')
|
||||||
}
|
}
|
||||||
expect(['EISDIR', 'EPERM', 'EACCES']).toContain(code)
|
const expectedCodes =
|
||||||
|
process.platform === 'win32'
|
||||||
|
? ['EISDIR', 'EPERM', 'EACCES']
|
||||||
|
: ['EISDIR']
|
||||||
|
expect(expectedCodes).toContain(code)
|
||||||
expect((await stat(inboxPath)).isDirectory()).toBe(true)
|
expect((await stat(inboxPath)).isDirectory()).toBe(true)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -275,7 +275,7 @@ describe('UDS inbox retention', () => {
|
|||||||
'../udsClient.js'
|
'../udsClient.js'
|
||||||
)
|
)
|
||||||
|
|
||||||
const error = await sendToUdsSocket(path, 'hello', 50).then(
|
const error = await sendToUdsSocket(path, 'hello', 200).then(
|
||||||
() => undefined,
|
() => undefined,
|
||||||
err => err,
|
err => err,
|
||||||
)
|
)
|
||||||
@@ -301,6 +301,75 @@ describe('UDS inbox retention', () => {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test('connectToPeer reports connection failures as peer connection errors', async () => {
|
||||||
|
const path = socketPath('uds-connect-error')
|
||||||
|
const { connectToPeer, UdsPeerConnectionError } = await import(
|
||||||
|
'../udsClient.js'
|
||||||
|
)
|
||||||
|
|
||||||
|
const error = await connectToPeer(path, () => {
|
||||||
|
throw new Error('Unexpected post-connect socket error')
|
||||||
|
}).then(
|
||||||
|
() => undefined,
|
||||||
|
err => err,
|
||||||
|
)
|
||||||
|
|
||||||
|
expect(error).toBeInstanceOf(UdsPeerConnectionError)
|
||||||
|
if (!(error instanceof UdsPeerConnectionError)) {
|
||||||
|
throw new Error('Expected UDS peer connection error')
|
||||||
|
}
|
||||||
|
expect(error.socketPath).toBe(path)
|
||||||
|
})
|
||||||
|
|
||||||
|
test('connectToPeer leaves connected socket lifecycle to the caller', async () => {
|
||||||
|
const path = socketPath('uds-connect-lifecycle')
|
||||||
|
if (process.platform !== 'win32') {
|
||||||
|
await mkdir(dirname(path), { recursive: true })
|
||||||
|
}
|
||||||
|
|
||||||
|
const sockets = new Set<Socket>()
|
||||||
|
const receiver = createServer(socket => {
|
||||||
|
sockets.add(socket)
|
||||||
|
socket.on('close', () => {
|
||||||
|
sockets.delete(socket)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
await new Promise<void>((resolve, reject) => {
|
||||||
|
receiver.on('error', reject)
|
||||||
|
receiver.listen(path, () => resolve())
|
||||||
|
})
|
||||||
|
|
||||||
|
let client: Socket | undefined
|
||||||
|
const socketErrors: Error[] = []
|
||||||
|
try {
|
||||||
|
const { connectToPeer } = await import('../udsClient.js')
|
||||||
|
client = await connectToPeer(
|
||||||
|
path,
|
||||||
|
error => {
|
||||||
|
socketErrors.push(error)
|
||||||
|
},
|
||||||
|
1000,
|
||||||
|
)
|
||||||
|
await new Promise(resolve => setTimeout(resolve, 100))
|
||||||
|
|
||||||
|
expect(client.destroyed).toBe(false)
|
||||||
|
expect(client.listenerCount('error')).toBe(1)
|
||||||
|
|
||||||
|
const socketError = new Error('post-connect failure')
|
||||||
|
client.emit('error', socketError)
|
||||||
|
expect(socketErrors).toEqual([socketError])
|
||||||
|
} finally {
|
||||||
|
client?.destroy()
|
||||||
|
for (const socket of sockets) {
|
||||||
|
socket.destroy()
|
||||||
|
}
|
||||||
|
await closeServer(receiver)
|
||||||
|
if (process.platform !== 'win32') {
|
||||||
|
await unlink(path).catch(() => undefined)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
test('sendUdsMessage fails closed before connecting without an auth token', async () => {
|
test('sendUdsMessage fails closed before connecting without an auth token', async () => {
|
||||||
await expect(
|
await expect(
|
||||||
sendUdsMessage(socketPath('no-auth-token'), { type: 'text', data: 'x' }),
|
sendUdsMessage(socketPath('no-auth-token'), { type: 'text', data: 'x' }),
|
||||||
|
|||||||
@@ -266,17 +266,48 @@ export async function sendToUdsSocket(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Connect to a peer and return the raw socket for bidirectional communication.
|
* Connect to a peer and return the raw socket for bidirectional communication.
|
||||||
* The caller is responsible for managing the connection lifecycle.
|
* The caller owns the post-connect lifecycle through onSocketError, which is
|
||||||
|
* attached before the Promise resolves so peer socket errors cannot be
|
||||||
|
* swallowed or surface through a listener handoff window.
|
||||||
|
* Pre-connect failures reject with UdsPeerConnectionError.
|
||||||
|
* This only opens the transport; callers still own any capability handshake.
|
||||||
*/
|
*/
|
||||||
export function connectToPeer(socketPath: string): Promise<Socket> {
|
export function connectToPeer(
|
||||||
|
socketPath: string,
|
||||||
|
onSocketError: (error: Error) => void,
|
||||||
|
timeoutMs = 5000,
|
||||||
|
): Promise<Socket> {
|
||||||
return new Promise<Socket>((resolve, reject) => {
|
return new Promise<Socket>((resolve, reject) => {
|
||||||
const conn = createConnection(socketPath, () => {
|
const conn = createConnection(socketPath)
|
||||||
|
let settled = false
|
||||||
|
const timeout = setTimeout(
|
||||||
|
fail,
|
||||||
|
timeoutMs,
|
||||||
|
new Error('Connection timed out'),
|
||||||
|
)
|
||||||
|
function cleanupListeners(): void {
|
||||||
|
clearTimeout(timeout)
|
||||||
|
conn.off('error', fail)
|
||||||
|
}
|
||||||
|
function fail(cause: unknown): void {
|
||||||
|
if (settled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
settled = true
|
||||||
|
cleanupListeners()
|
||||||
|
conn.destroy()
|
||||||
|
reject(new UdsPeerConnectionError(socketPath, cause))
|
||||||
|
}
|
||||||
|
conn.once('connect', () => {
|
||||||
|
if (settled) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
settled = true
|
||||||
|
cleanupListeners()
|
||||||
|
conn.on('error', onSocketError)
|
||||||
resolve(conn)
|
resolve(conn)
|
||||||
})
|
})
|
||||||
conn.on('error', reject)
|
conn.on('error', fail)
|
||||||
conn.setTimeout(5000, () => {
|
|
||||||
conn.destroy(new Error('Connection timed out'))
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user