v0.6.0: beautifului 整合 + 会话/工作区/队列/权限/命令/附件全链路
- beautifului.dev 组件直连:Sidebar Nav、Tool Chips、Approval Card(抽屉化)、Streaming/Thinking、Code Block、Selection Actions、Prompt Bar、Search
This commit is contained in:
@@ -0,0 +1,81 @@
|
||||
// 验证渲染层对 session_switched 历史消息的渲染逻辑:
|
||||
// 用与主进程一致的 session.messages 源,跑 MessageItem 的 readBlocks + AssistantBody 判断。
|
||||
import os from 'node:os'
|
||||
import { createAgentSessionServices, getAgentDir } from '@earendil-works/pi-coding-agent'
|
||||
|
||||
const cwd = os.homedir()
|
||||
const services = await createAgentSessionServices({ cwd, agentDir: getAgentDir() })
|
||||
|
||||
// SessionManager.list + 加载最近会话的等价做法:直接用 services 里加载当前会话
|
||||
const session = services.sessionManager
|
||||
? null
|
||||
: null
|
||||
|
||||
// 走 SessionManager 拿最近会话并加载
|
||||
const { SessionManager } = await import('@earendil-works/pi-coding-agent')
|
||||
const sm = SessionManager.continueRecent(cwd)
|
||||
const smAny = sm
|
||||
// SessionManager.continueRecent 返回的 manager 需要挂到 session 上才有 messages;
|
||||
// 更直接:读它指向的会话文件并解析 message 条目
|
||||
const entries = []
|
||||
if (typeof smAny.loadEntries === 'function') {
|
||||
entries.push(...(await smAny.loadEntries()))
|
||||
}
|
||||
console.log('loadEntries available:', typeof smAny.loadEntries === 'function', 'entries:', entries.length)
|
||||
|
||||
// 退路:直接解析磁盘上的最近 jsonl(与主进程 toCloneable 后的消息同构)
|
||||
import { readdirSync, readFileSync, statSync } from 'node:fs'
|
||||
import { join } from 'node:path'
|
||||
const dir = join(cwd, '.pi', 'agent', 'sessions', '--C--Users-21976--')
|
||||
const files = readdirSync(dir).filter((f) => f.endsWith('.jsonl'))
|
||||
files.sort((a, b) => statSync(join(dir, b)).mtimeMs - statSync(join(dir, a)).mtimeMs)
|
||||
const latest = files[0]
|
||||
console.log('latest session file:', latest)
|
||||
|
||||
const lines = readFileSync(join(dir, latest), 'utf8').trim().split('\n')
|
||||
const messages = []
|
||||
for (const line of lines) {
|
||||
let entry
|
||||
try {
|
||||
entry = JSON.parse(line)
|
||||
} catch {
|
||||
continue
|
||||
}
|
||||
if (entry.type === 'message' && entry.message) messages.push(entry.message)
|
||||
}
|
||||
|
||||
// ==== 渲染层逻辑复刻(与 MessageItem.tsx 一致)====
|
||||
function readBlocks(raw) {
|
||||
if (!raw || typeof raw !== 'object') return []
|
||||
const content = raw.content
|
||||
if (typeof content === 'string') return [{ type: 'text', text: content }]
|
||||
if (Array.isArray(content)) {
|
||||
return content.filter((c) => typeof c === 'object' && c !== null)
|
||||
}
|
||||
return []
|
||||
}
|
||||
|
||||
for (const [i, m] of messages.entries()) {
|
||||
console.log(`\n=== history msg #${i} role=${m.role} ===`)
|
||||
const blocks = readBlocks(m)
|
||||
let rendered = 0
|
||||
for (const block of blocks) {
|
||||
if (block.type === 'thinking' && typeof block.text === 'string') {
|
||||
console.log(' -> ThinkingBlock (text field)')
|
||||
rendered++
|
||||
continue
|
||||
}
|
||||
if (block.type === 'text' && block.text) {
|
||||
console.log(` -> Markdown("${String(block.text).slice(0, 60)}…")`)
|
||||
rendered++
|
||||
continue
|
||||
}
|
||||
if (block.type === 'toolCall' && block.id) {
|
||||
console.log(' -> ToolCard', block.name)
|
||||
rendered++
|
||||
continue
|
||||
}
|
||||
console.log(' -> **被丢弃** block type =', block.type, 'keys =', Object.keys(block).join(','))
|
||||
}
|
||||
console.log(` rendered ${rendered}/${blocks.length} blocks`)
|
||||
}
|
||||
Reference in New Issue
Block a user