- beautifului.dev 组件直连:Sidebar Nav、Tool Chips、Approval Card(抽屉化)、Streaming/Thinking、Code Block、Selection Actions、Prompt Bar、Search
104 lines
3.4 KiB
JavaScript
104 lines
3.4 KiB
JavaScript
// 复现渲染层"输出一闪而过":用与 agent-service.ts 相同的 SDK 调用链,
|
||
// 订阅全部事件并打印事件序列与消息对象结构。
|
||
import os from 'node:os'
|
||
import {
|
||
createAgentSessionRuntime,
|
||
createAgentSessionServices,
|
||
createAgentSessionFromServices,
|
||
getAgentDir,
|
||
SessionManager
|
||
} from '@earendil-works/pi-coding-agent'
|
||
|
||
const cwd = os.homedir()
|
||
const agentDir = getAgentDir()
|
||
|
||
const services = await createAgentSessionServices({ cwd, agentDir })
|
||
const factory = async (opts) => {
|
||
const result = await createAgentSessionFromServices({
|
||
services,
|
||
sessionManager: opts.sessionManager,
|
||
sessionStartEvent: opts.sessionStartEvent
|
||
})
|
||
return { ...result, services, diagnostics: services.diagnostics }
|
||
}
|
||
|
||
const sessionManager = SessionManager.continueRecent(cwd)
|
||
const runtime = await createAgentSessionRuntime(factory, { cwd, agentDir, sessionManager })
|
||
const session = runtime.session
|
||
|
||
let rebindCount = 0
|
||
runtime.setRebindSession(async (s) => {
|
||
rebindCount++
|
||
console.log(`\n>>> REBIND fired (#${rebindCount}) — 渲染层会收到 session_switched,messages.length=${s.messages.length}`)
|
||
})
|
||
|
||
session.subscribe((event) => {
|
||
switch (event.type) {
|
||
case 'message_start':
|
||
console.log('EVT message_start role=', JSON.stringify(event.message?.role))
|
||
break
|
||
case 'message_update': {
|
||
const inner = event.assistantMessageEvent
|
||
if (inner) {
|
||
if (inner.type.endsWith('_delta')) {
|
||
process.stdout.write(`.`)
|
||
} else {
|
||
console.log(`EVT message_update ${inner.type}`)
|
||
}
|
||
}
|
||
break
|
||
}
|
||
case 'message_end': {
|
||
const m = event.message
|
||
console.log('\nEVT message_end role=', m?.role)
|
||
console.log(' message keys:', Object.keys(m ?? {}))
|
||
try {
|
||
JSON.stringify(m)
|
||
console.log(' JSON.stringify: OK, length=', JSON.stringify(m).length)
|
||
} catch (err) {
|
||
console.log(' JSON.stringify FAILED ->', err.message, '(toCloneable 会变成 null → 渲染层消息变空!)')
|
||
}
|
||
if (m?.role === 'assistant') {
|
||
console.log(' stopReason=', m.stopReason, ' errorMessage=', m.errorMessage)
|
||
console.log(' content types=', (m.content ?? []).map((b) => b.type).join(','))
|
||
for (const b of m.content ?? []) {
|
||
if (b.type === 'text') console.log(' text block:', JSON.stringify(b.text).slice(0, 200))
|
||
}
|
||
}
|
||
break
|
||
}
|
||
case 'agent_end':
|
||
console.log(`\nEVT agent_end willRetry=${event.willRetry} messages=${event.messages?.length}`)
|
||
break
|
||
default:
|
||
console.log('EVT', event.type)
|
||
}
|
||
})
|
||
|
||
console.log('--- session:', session.sessionId, 'messages:', session.messages.length)
|
||
console.log('--- model:', session.model?.provider + '/' + session.model?.id)
|
||
console.log('--- sending "hi" ...')
|
||
|
||
try {
|
||
await session.prompt('hi')
|
||
console.log('\n--- prompt resolved')
|
||
} catch (err) {
|
||
console.log('\n--- prompt THREW:', err?.message)
|
||
}
|
||
|
||
// 等待 agent_settled 之后的异步收尾
|
||
await new Promise((r) => setTimeout(r, 1500))
|
||
|
||
console.log('\n=== final session.messages ===')
|
||
for (const [i, m] of session.messages.entries()) {
|
||
const blocks = Array.isArray(m.content)
|
||
? m.content.map((b) => b.type).join(',')
|
||
: typeof m.content === 'string'
|
||
? 'str:' + m.content.slice(0, 30)
|
||
: '??'
|
||
console.log(`#${i} ${m.role} [${blocks}]`)
|
||
}
|
||
|
||
console.log('\nrebindCount=', rebindCount)
|
||
process.exit(0)
|