Merge commit 'a9cc0fddb40be295c43cb2badb4cbcb2b032556c' into codex/product-providers-pr2-claude-code
# Conflicts: # .agents/notes/proposed/feature/2026-08-04-claude-code-and-codex-subagent-backends.i18n.yaml # .agents/notes/proposed/feature/2026-08-04-claude-code-and-codex-subagent-backends.md # .agents/notes/proposed/feature/2026-08-04-claude-code-and-codex-subagent-backends.zh.md # docs/core-data-structures/subprocess.i18n.yaml # packages/subprocess/subprocess/README.i18n.yaml
This commit is contained in:
@@ -83,18 +83,17 @@ function complete(
|
||||
|
||||
/**
|
||||
* Start a loopback-only Anthropic Messages SSE fixture.
|
||||
* @param script - one behavior per Messages request.
|
||||
* @param behavior - the single response behavior for this fixture.
|
||||
* @returns the bound server and its recorded requests.
|
||||
*/
|
||||
export async function startMessagesFixture(
|
||||
script: readonly MessagesBehavior[],
|
||||
behavior: MessagesBehavior,
|
||||
): Promise<MessagesFixture> {
|
||||
const requests: RecordedMessagesRequest[] = []
|
||||
let requestStartedResolve!: () => void
|
||||
const requestStarted = new Promise<void>((resolve) => {
|
||||
requestStartedResolve = resolve
|
||||
})
|
||||
let behaviorIndex = 0
|
||||
const server = createServer((request, response) => {
|
||||
const chunks: Buffer[] = []
|
||||
request.on('data', (chunk: Buffer) => { chunks.push(chunk) })
|
||||
@@ -117,18 +116,6 @@ export async function startMessagesFixture(
|
||||
body,
|
||||
})
|
||||
requestStartedResolve()
|
||||
const behavior = script[behaviorIndex++]
|
||||
if (behavior === undefined) {
|
||||
response.writeHead(500, { 'content-type': 'application/json' })
|
||||
response.end(JSON.stringify({
|
||||
type: 'error',
|
||||
error: {
|
||||
type: 'api_error',
|
||||
message: 'Messages fixture script was exhausted',
|
||||
},
|
||||
}))
|
||||
return
|
||||
}
|
||||
if (behavior.kind === 'complete') {
|
||||
complete(response, body, behavior.text)
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ interface RealHarness {
|
||||
readonly env: Record<string, string>
|
||||
}
|
||||
|
||||
async function realHarness(script: readonly MessagesBehavior[]): Promise<{
|
||||
async function realHarness(behavior: MessagesBehavior): Promise<{
|
||||
readonly harness: RealHarness
|
||||
readonly fixture: MessagesFixture
|
||||
}> {
|
||||
@@ -80,7 +80,7 @@ async function realHarness(script: readonly MessagesBehavior[]): Promise<{
|
||||
join(claudeConfig, 'settings.json'),
|
||||
`${JSON.stringify({ model: settingsModel }, null, 2)}\n`,
|
||||
)
|
||||
const fixture = await startMessagesFixture(script)
|
||||
const fixture = await startMessagesFixture(behavior)
|
||||
fixtures.push(fixture)
|
||||
const env = {
|
||||
ANTHROPIC_API_KEY: fakeKey,
|
||||
@@ -149,9 +149,10 @@ describe('real Claude Agent SDK 0.3.220 and Claude Code 2.1.220', {
|
||||
it('inherits host settings and sends the exact task and fake key to local Messages', async () => {
|
||||
const sentinel = 'REAL_CLAUDE_CODE_SENTINEL_2_1_220'
|
||||
const task = 'Return the fixture sentinel exactly.'
|
||||
const { harness, fixture } = await realHarness([
|
||||
{ kind: 'complete', text: sentinel },
|
||||
])
|
||||
const { harness, fixture } = await realHarness({
|
||||
kind: 'complete',
|
||||
text: sentinel,
|
||||
})
|
||||
expect(sdkPackage.version).toBe('0.3.220')
|
||||
expect(sdkPackage.claudeCodeVersion).toBe('2.1.220')
|
||||
expect(sdkPackage.optionalDependencies[platformPackage]).toBe('0.3.220')
|
||||
@@ -191,7 +192,7 @@ describe('real Claude Agent SDK 0.3.220 and Claude Code 2.1.220', {
|
||||
})
|
||||
|
||||
it('maps a real CLI process failure to error', async () => {
|
||||
const { harness, fixture } = await realHarness([{ kind: 'hold' }])
|
||||
const { harness, fixture } = await realHarness({ kind: 'hold' })
|
||||
const run = await startRequest(harness, 'Exercise the failure path.')
|
||||
await fixture.requestStarted
|
||||
expect(harness.handles).toHaveLength(1)
|
||||
@@ -207,7 +208,7 @@ describe('real Claude Agent SDK 0.3.220 and Claude Code 2.1.220', {
|
||||
})
|
||||
|
||||
it('settles cancellation and leaves the real SDK-spawned CLI tree quiescent', async () => {
|
||||
const { harness, fixture } = await realHarness([{ kind: 'hold' }])
|
||||
const { harness, fixture } = await realHarness({ kind: 'hold' })
|
||||
const controller = new AbortController()
|
||||
const run = await startRequest(
|
||||
harness,
|
||||
|
||||
@@ -27,6 +27,7 @@ import type {
|
||||
SubprocessSpawnSpec,
|
||||
} from '@deepseek-ai/dsh-subprocess'
|
||||
import LocalSubprocessService from '@deepseek-ai/dsh-subprocess-local'
|
||||
import { MAX_TIMER_DELAY_MS } from '@deepseek-ai/dsh-timeout'
|
||||
import * as claudeCode from '../src/index.ts'
|
||||
import * as invariant from '../src/invariant.ts'
|
||||
import {
|
||||
@@ -74,8 +75,6 @@ async function nextTask(): Promise<void> {
|
||||
|
||||
interface FakeChildOptions {
|
||||
readonly pid?: number
|
||||
readonly stdin?: PassThrough | undefined
|
||||
readonly stdout?: PassThrough | undefined
|
||||
readonly exitOnTerminate?: boolean
|
||||
readonly waitForExitError?: Error
|
||||
readonly doneError?: Error
|
||||
@@ -145,8 +144,8 @@ function fakeChild(options: FakeChildOptions = {}): FakeChild {
|
||||
})
|
||||
const handle: SubprocessHandle = {
|
||||
pid: options.pid ?? 1234,
|
||||
stdin: options.stdin === undefined ? stdin : options.stdin,
|
||||
stdout: options.stdout === undefined ? stdout : options.stdout,
|
||||
stdin,
|
||||
stdout,
|
||||
stderr: undefined,
|
||||
collected: {},
|
||||
done,
|
||||
@@ -232,7 +231,6 @@ function sdkSpawnOptions(
|
||||
|
||||
interface FakeRun {
|
||||
readonly child: FakeChild
|
||||
readonly query: Query
|
||||
readonly close: ReturnType<typeof vi.fn>
|
||||
readonly spawnSpecs: SubprocessSpawnSpec[]
|
||||
readonly options: Options[]
|
||||
@@ -262,7 +260,7 @@ function fakeRun(
|
||||
params.options.spawnClaudeCodeProcess!(sdkSpawnOptions())
|
||||
return query
|
||||
})
|
||||
return { child, query, close, spawnSpecs, options, spec }
|
||||
return { child, close, spawnSpecs, options, spec }
|
||||
}
|
||||
|
||||
beforeEach(() => {
|
||||
@@ -318,6 +316,11 @@ describe('task admission and package contracts', () => {
|
||||
await expect(ctx.plugin(claudeCode, { disposeGraceMs }))
|
||||
.rejects.toThrow('disposeGraceMs must be a positive finite number')
|
||||
}
|
||||
await expect(ctx.plugin(claudeCode, {
|
||||
disposeGraceMs: MAX_TIMER_DELAY_MS + 1,
|
||||
})).rejects.toThrow(
|
||||
`disposeGraceMs must be no greater than ${MAX_TIMER_DELAY_MS}`,
|
||||
)
|
||||
await ctx.fiber.dispose()
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user