refactor(agent): replace OMP with Claude Code kernel

This commit is contained in:
xiaohan.yuan committed 2026-10-20 14:47:56 +08:00
1 parent 0fb2226f8c
commit 9a1f182397
232 files changed
+2561 -25564

No files matched your search

+208
View File
@@ -0,0 +1,208 @@
import assert from 'node:assert/strict'
import { createServer } from 'node:http'
import { mkdtemp, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join, resolve } from 'node:path'
import { createSdkMcpServer, query, tool } from '@anthropic-ai/claude-agent-sdk'
import { z } from 'zod'
const executable = resolve(process.env.YCODE_CLAUDE_EXE ?? 'node_modules/@anthropic-ai/claude-agent-sdk-win32-x64/claude.exe')
const temp = await mkdtemp(join(tmpdir(), 'ycode-claude-smoke-'))
const requests = []
function sse(res, event, data) {
res.write(`event: ${event}\ndata: ${JSON.stringify(data)}\n\n`)
}
function textResponse(res, id, model, text) {
sse(res, 'message_start', {
type: 'message_start',
message: {
id, type: 'message', role: 'assistant', model,
content: [], stop_reason: null, stop_sequence: null,
usage: { input_tokens: 12, output_tokens: 1 }
}
})
sse(res, 'content_block_start', { type: 'content_block_start', index: 0, content_block: { type: 'text', text: '' } })
sse(res, 'content_block_delta', { type: 'content_block_delta', index: 0, delta: { type: 'text_delta', text } })
sse(res, 'content_block_stop', { type: 'content_block_stop', index: 0 })
sse(res, 'message_delta', {
type: 'message_delta',
delta: { stop_reason: 'end_turn', stop_sequence: null },
usage: { output_tokens: 5 }
})
sse(res, 'message_stop', { type: 'message_stop' })
res.end()
}
const server = createServer((req, res) => {
let raw = ''
req.on('data', chunk => { raw += chunk })
req.on('end', () => {
let body
try { body = JSON.parse(raw || '{}') } catch { body = { raw } }
requests.push({ url: req.url, method: req.method, body })
if (!req.url?.includes('/messages')) {
res.writeHead(200, { 'content-type': 'application/json' })
res.end(JSON.stringify({ data: [] }))
return
}
res.writeHead(200, {
'content-type': 'text/event-stream',
'cache-control': 'no-cache',
connection: 'keep-alive'
})
const id = `msg_smoke_${requests.length}`
const latestUser = [...(body.messages ?? [])].reverse().find(message => message.role === 'user')
const latestUserContent = JSON.stringify(latestUser?.content ?? [])
if (process.env.DEBUG_CLAUDE_SMOKE === '1') console.error('smoke request', requests.length, latestUserContent.slice(0, 500))
const hasToolResult = latestUserContent.includes('"tool_result"')
const wantsRead = latestUserContent.includes('Read the smoke file.')
if (hasToolResult) {
textResponse(res, id, body.model ?? 'claude-smoke', 'Tool read complete.')
return
}
if (wantsRead && !hasToolResult) {
sse(res, 'message_start', {
type: 'message_start',
message: {
id, type: 'message', role: 'assistant', model: body.model ?? 'claude-smoke',
content: [], stop_reason: null, stop_sequence: null,
usage: { input_tokens: 12, output_tokens: 1 }
}
})
sse(res, 'content_block_start', {
type: 'content_block_start', index: 0,
content_block: { type: 'tool_use', id: 'tool_smoke', name: 'Read', input: {} }
})
sse(res, 'content_block_delta', {
type: 'content_block_delta', index: 0,
delta: { type: 'input_json_delta', partial_json: JSON.stringify({ file_path: join(temp, 'smoke.txt') }) }
})
sse(res, 'content_block_stop', { type: 'content_block_stop', index: 0 })
sse(res, 'message_delta', {
type: 'message_delta',
delta: { stop_reason: 'tool_use', stop_sequence: null },
usage: { output_tokens: 5 }
})
sse(res, 'message_stop', { type: 'message_stop' })
res.end()
return
}
textResponse(res, id, body.model ?? 'claude-smoke', 'Claude mock reply.')
})
})
await new Promise(resolveListen => server.listen(0, '127.0.0.1', resolveListen))
const address = server.address()
if (!address || typeof address === 'string') throw new Error('mock server did not bind')
const sessionId = crypto.randomUUID()
let runtimeSessionId = sessionId
let releaseSecondTurn
const firstTurnComplete = new Promise(resolve => { releaseSecondTurn = resolve })
const input = (async function* () {
yield {
type: 'user',
message: { role: 'user', content: [{ type: 'text', text: 'Read the smoke file.' }] },
parent_tool_use_id: null,
uuid: crypto.randomUUID(),
session_id: runtimeSessionId
}
await firstTurnComplete
yield {
type: 'user',
message: { role: 'user', content: [{ type: 'text', text: 'Reply once more.' }] },
parent_tool_use_id: null,
uuid: crypto.randomUUID(),
session_id: runtimeSessionId
}
})()
await writeFile(join(temp, 'smoke.txt'), 'SMOKE_FILE_CONTENTS', 'utf8')
const messages = []
const results = []
let instance
try {
instance = query({
prompt: input,
options: {
cwd: temp,
model: 'claude-smoke',
pathToClaudeCodeExecutable: executable,
env: {
...process.env,
ANTHROPIC_BASE_URL: `http://127.0.0.1:${address.port}`,
ANTHROPIC_API_KEY: 'ycode-smoke-key',
CLAUDE_CONFIG_DIR: join(temp, 'claude-config'),
CLAUDE_CODE_ENABLE_TODO_TOOLS: '1',
CLAUDE_CODE_ENABLE_TASKS: '0',
...(process.platform === 'win32' ? { CLAUDE_CODE_USE_POWERSHELL_TOOL: '1' } : {})
},
includePartialMessages: true,
permissionMode: 'default',
permissionPrompts: 'host',
settingSources: [],
strictMcpConfig: true,
tools: ['Read', 'Write', 'Edit', 'Glob', 'Grep', 'Bash', 'PowerShell', 'WebFetch', 'WebSearch',
'TodoWrite', 'AskUserQuestion', 'EnterPlanMode', 'ExitPlanMode'],
allowedTools: [],
disallowedTools: ['Agent', 'Task', 'Skill', 'Workflow', 'CronCreate', 'CronDelete', 'CronList'],
plugins: [],
agents: {},
skills: [],
mcpServers: {
ycode: createSdkMcpServer({
name: 'ycode',
tools: [tool('ping', 'Test host tool', { value: z.string() }, async ({ value }) => ({
content: [{ type: 'text', text: value }]
}))]
})
},
canUseTool: async (toolName) => toolName === 'Read'
? { behavior: 'allow', updatedInput: { file_path: join(temp, 'smoke.txt') } }
: { behavior: 'deny', message: 'Only Read is enabled in this smoke test.' }
}
})
for await (const message of instance) {
messages.push(message)
if (message.type === 'system' && message.subtype === 'init' && message.session_id) {
runtimeSessionId = message.session_id
}
if (message.type === 'result') {
results.push(message)
if (results.length === 1) releaseSecondTurn()
else break
}
}
} finally {
instance?.close()
await new Promise(resolveClose => server.close(resolveClose))
await rm(temp, { recursive: true, force: true })
}
const result = results.at(-1)
const streamed = messages.filter(message => message.type === 'stream_event')
.map(message => message.event)
.filter(event => event?.type === 'content_block_delta' && event.delta?.type === 'text_delta')
.map(event => event.delta.text)
.join('')
const toolResult = messages.find(message => message.type === 'user' &&
Array.isArray(message.message?.content) &&
message.message.content.some(block => block.type === 'tool_result'))
assert.ok(requests.some(request => request.url?.includes('/messages')), 'Claude Code should call the Anthropic Messages endpoint')
assert.equal(results.length, 2, 'one process should serve two consecutive turns')
assert.equal(new Set(results.map(message => message.session_id)).size, 1,
'both turns should stay in the same Claude session')
assert.equal(streamed, 'Tool read complete.Claude mock reply.')
assert.ok(toolResult, 'the native Read tool result should return to Claude')
assert.equal(result?.subtype, 'success')
assert.equal(result?.result, 'Claude mock reply.')
const init = messages.find(message => message.type === 'system' && message.subtype === 'init')
assert.ok(init?.tools.includes('TodoWrite'), 'TodoWrite should be enabled')
if (process.platform === 'win32') assert.ok(init?.tools.includes('PowerShell'), 'PowerShell should be enabled on Windows')
assert.equal(init?.tools.some(tool => ['Agent', 'Task', 'Skill', 'Workflow', 'CronCreate'].includes(tool)), false)
console.log(JSON.stringify({ result: 'PASS', requests: requests.length, messages: messages.length, turns: results.length, text: result.result }))