chore: establish YCode replication baseline and TODO

This commit is contained in:
xiaohan.yuan committed 2026-10-17 02:43:49 +08:00
commit 6dc59f89ba
1118 files changed
+196002

No files matched your search

+30
View File
@@ -0,0 +1,30 @@
// Isolated YCode host fixtures, not claims about WorkBuddy runtime screenshots.
const now = Date.now()
const tool = (id, name, args, result) => ({ id, name, args, argsRaw: JSON.stringify(args), status: 'ok', result, output: JSON.stringify(result) })
const manyLines = Array.from({ length: 300 }, (_, index) => `export const value${index} = ${index}`).join('\n')
const writes = [
tool('source-edit', 'edit_file', { path: 'src/example.ts', oldText: '1', newText: '2' }, { path: 'src/example.ts', oldContent: 'export const value = 1\n', newContent: 'export const value = 2\n' }),
tool('source-create', 'write_file', { path: 'new.txt', content: 'created\n' }, { path: 'new.txt', oldContent: null, newContent: 'created\n' }),
tool('source-empty', 'edit_file', { path: 'empty.txt', oldText: 'removed', newText: '' }, { path: 'empty.txt', oldContent: 'removed\n', newContent: '' }),
tool('source-many', 'write_file', { path: 'many.ts', content: manyLines }, { path: 'many.ts', oldContent: null, newContent: manyLines })
]
const artifact = (id, name, preview) => ({ type: 'artifact', artifact: { id, name, path: preview.uri || id, preview } })
export const artifactSourceFixture = {
sessions: [{ id: 'artifact-source', title: '产物源码分支验证', createdAt: now, updatedAt: now }],
messages: { 'artifact-source': [
{ id: 'user', role: 'user', content: '验证完整 Diff、异步 Markdown、HTML 和原生下载。', status: 'done', createdAt: now },
{ id: 'assistant', role: 'assistant', content: '', status: 'done', createdAt: now + 1, tools: writes, parts: [
...writes.flatMap(item => [{ type: 'text', text: `**${item.id}**` }, { type: 'tool', toolId: item.id }]),
artifact('custom', '异步 Markdown', { id: 'custom', type: 'custom-artifact', uri: 'notes/readme.md' }),
artifact('cached', '缓存 Markdown', { id: 'cached', type: 'custom-artifact', uri: 'missing.md', content: '# 缓存内容\n\n没有读取磁盘。' }),
artifact('slow', '慢速 Markdown', { id: 'slow', type: 'custom-artifact', uri: 'slow.md' }),
artifact('html', 'HTML 预览', { id: 'html', type: 'media-artifact', category: 'artifact', url: 'preview.html', contentType: 'code' }),
artifact('missing', '读取失败', { id: 'missing', type: 'custom-artifact', uri: 'missing.md' }),
artifact('timeout', 'Diff 超时', { id: 'timeout', type: 'file-changes', title: 'large.txt', fileChangeInfo: { uri: 'large.txt', diffStatus: 'timeout' } }),
{ type: 'plan', plan: { id: 'plan', title: '计划下载', steps: [{ id: '1', text: '验证 Markdown 保存', status: 'pending' }] } }
] }
] },
files: { 'src/example.ts': 'export const value = 2\n', 'new.txt': 'created\n', 'empty.txt': '', 'many.ts': manyLines,
'notes/readme.md': '# 异步加载成功\n\n真实调用文件读取桥。', 'slow.md': '# 过期读取不能覆盖新预览', 'preview.html': '<!doctype html><html><body><h1>HTML 预览成功</h1></body></html>' },
delays: { 'slow.md': 300 }
}
+49
View File
@@ -0,0 +1,49 @@
// 仅供离线 UI 验证;不进入产品数据,不请求模型。
const output = Array.from({ length: 90 }, (_, i) => `src/example-${i + 1}.ts`).join('\n') + '\nOUTPUT_END_完整输出'
const before = '我先检查工作目录中的文件,再给出结果。\n'
const after = [
'# 检查结果',
'',
'已读取 **90 个文件**。下面是正文、表格和代码块的渲染样本。',
'这一行用于检查普通换行。',
'',
'## 状态清单',
'',
'- [x] 列出工作目录',
'- [ ] 核对变更',
'- 保留嵌套列表',
' - 第二层内容',
'',
'| 模块 | 状态 | 说明 |',
'| :--- | :---: | ---: |',
'| 对话渲染 | 已完成 | 支持 Markdown |',
'| 工具过程 | 已完成 | 保留完整输出 |',
'',
'```typescript',
'',
'const message: string = "你好,YCode"',
'console.log(message)',
'',
'```',
'',
'> 工具发生在这段正文之前,重开会话后也应保持这个顺序。',
'',
'访问 https://example.com/docs;~~旧的内容~~,以及行内 `code`。',
'',
'<script>window.__unsafeExecuted = true</script>',
'',
'未标注语言的代码:',
'',
'```',
'plain text',
'```'
].join('\n')
const now = Date.now()
const tool = { id: 'fixture-read', name: 'read', args: { path: 'src' }, argsRaw: '{"path":"src"}', status: 'ok', summary: output.slice(0, 600), output, durationMs: 123 }
export const chatParityFixture = {
sessions: [{ id: 'parity', title: '对话渲染与工具过程验证', createdAt: now, updatedAt: now }],
messages: { parity: [
{ id: 'user-fixture', role: 'user', content: '检查文件并用表格、代码块汇报。', createdAt: now, status: 'done' },
{ id: 'assistant-fixture', role: 'assistant', content: before + after, tools: [tool], parts: [{ type: 'text', text: before }, { type: 'tool', toolId: tool.id }, { type: 'text', text: after }], createdAt: now, status: 'done' }
] }
}
@@ -0,0 +1,60 @@
// Deterministic UI data. Native/OMP execution is verified separately by the runtime regressions.
const now = Date.now()
const message = (id, role, content, extra = {}) => ({ id, role, content, createdAt: now, status: 'done', ...extra })
const tool = (id, name, args, result) => ({ id, name, args, argsRaw: JSON.stringify(args), status: 'ok', result, output: typeof result === 'string' ? result : JSON.stringify(result) })
const tools = [
tool('read', 'read_file', { path: 'src/example.ts', offset: 4, limit: 2 }, { content: 'export const value = 1', startLine: 4, endLine: 5, totalLines: 8 }),
tool('command', 'Bash', { command: 'npm run build' }, { stdout: 'Build complete', stderr: '', exitCode: 0 }),
tool('web', 'web_search', { query: 'documentation' }, { results: [{ title: 'Documentation', url: 'https://example.com', snippet: 'Example documentation result.' }] }),
tool('mcp', 'mcp_call_tool', { server_name: 'local', tool_name: 'inspect', arguments: {} }, { content: 'MCP result' }),
tool('unknown', 'custom_unknown', { input: 'x' }, 'Unknown-tool fallback output')
]
tools.push({ ...tool('plan-artifact', 'exit_plan_mode', {}, 'Plan ready'), metadata: { acp_request_permission: { planInfo: { planFilePath: 'plans/not-materialized.md', plan: '# 尚未落盘的计划\n\n- [ ] 验证内存内容预览\n- [ ] 保留原始 Markdown' } } } })
export const conversationCompleteFixture = {
sessions: [
{ id: 'conversation-complete', title: '八类对话组件验证', createdAt: now, updatedAt: now },
{ id: 'parallel-session', title: '并行会话验证', createdAt: now - 1, updatedAt: now - 1 }
],
messages: {
'conversation-complete': [
message('complete-user', 'user', '对齐问答、审批、工具、计划和消息操作。', { requestId: 'complete-request' }),
message('complete-assistant', 'assistant', '已完成组件恢复。', { requestId: 'complete-request', tools, parts: [
{ type: 'reasoning', id: 'thinking', text: '先读取实现,再检查状态和宿主回调。', finished: true },
...tools.map((item) => ({ type: 'tool', toolId: item.id })),
{ type: 'plan', plan: { id: 'plan', title: '对齐计划', steps: [{ id: '1', text: '恢复组件', status: 'completed' }, { id: '2', text: '接入宿主', status: 'in_progress' }] } },
{ type: 'task', task: { id: 'task', title: '检查工具状态', description: '验证成功、失败和取消状态。', status: 'success', summary: '**检查完成**,状态可恢复。' } },
{ type: 'text', text: '输入“问答验证”或“审批验证”检查完整交互。支持在运行时切换另一个会话并保留各自草稿。' }
] })
],
'parallel-session': [message('parallel-user', 'user', '第二个独立会话。'), message('parallel-assistant', 'assistant', '此处的草稿和运行状态独立保存。')]
},
files: { 'src/example.ts': 'line 1\nline 2\nline 3\nexport const value = 1\nline 5\nline 6\nline 7\nline 8' }
}
export const conversationCompleteBridge = `<script>
(()=>{
const fixture=window.__YCODE_FIXTURE__, listeners=new Set(), pending=new Map();let seq=0;
const emit=(event)=>listeners.forEach(listener=>listener(event));
const finish=(run,text)=>{pending.delete(run.runId);emit({sessionId:run.sessionId,runId:run.runId,type:'text',delta:text});emit({sessionId:run.sessionId,runId:run.runId,type:'done',content:text,tools:[]})};
window.ycode.chat.onEvent=(listener)=>{listeners.add(listener);return ()=>listeners.delete(listener)};
window.ycode.chat.send=async(payload)=>{
const run={sessionId:payload.sessionId,runId:'fixture-run-'+(++seq)}, assistantMessageId=run.runId+'-assistant';
const userMessage={id:run.runId+'-user',requestId:run.runId,planId:payload.planId,role:'user',content:payload.text,attachments:payload.attachments,createdAt:Date.now(),status:'done'};
const row=fixture.messages[run.sessionId]??(fixture.messages[run.sessionId]=[]);
let resultMessages;
if(payload.action){let index=row.findIndex(item=>item.id===payload.fromMessageId);if(payload.action==='regenerate')index=row.slice(0,index).findLastIndex(item=>item.role==='user');row.splice(index);resultMessages=[...row,userMessage,{id:assistantMessageId,requestId:run.runId,role:'assistant',content:'',status:'streaming',createdAt:Date.now()}]}
row.push(userMessage);
setTimeout(()=>{
if(/问答/.test(payload.text)){const interaction={id:run.runId+'-question',runId:run.runId,toolCallId:'fixture-question',kind:'question',title:'选择验证方式',status:'pending',questions:[{id:'choice',question:'选择哪种验证方式?',options:['源码和状态验证','浏览器交互验证']}]};pending.set(run.runId,{...run,interaction});emit({...run,type:'interaction',interaction})}
else if(/审批/.test(payload.text)){const interaction={id:run.runId+'-approval',requestId:run.runId+'-approval',runId:run.runId,toolCallId:'fixture-write',kind:'approval',title:'写入示例文件',status:'pending',options:[{optionId:'allow-once',name:'允许一次',kind:'allow_once'},{optionId:'reject-once',name:'拒绝',kind:'reject_once'}]};pending.set(run.runId,{...run,interaction});emit({...run,type:'interaction',interaction})}
else finish(run,'验证回复:'+payload.text);
},50);
return {...run,assistantMessageId,userMessage,...(resultMessages?{messages:resultMessages}:{})}
};
window.ycode.chat.respond=async(runId,id,response)=>{const run=pending.get(runId);if(!run||run.interaction.id!==id)return {accepted:false};const interaction={...run.interaction,status:response.kind==='approval'&&response.optionId==='reject-once'?'rejected':'answered',...(response.kind==='question'?{answer:response.answer,skipped:response.skipped}:{selectedOptionId:response.optionId})};emit({...run,type:'interaction',interaction});finish(run,response.kind==='question'?'已收到回答并继续。':'审批已回传并继续。');return {accepted:true}};
window.ycode.chat.cancel=async(runId)=>{const run=pending.get(runId);if(run){pending.delete(runId);emit({...run,type:'cancelled'})}return {cancelled:!!run}};
window.ycode.chat.feedback=async()=>{};
window.ycode.attachments={pick:async()=>[{id:'fixture-attachment',name:'example.txt',mimeType:'text/plain',size:15}],stage:async(input)=>({id:'fixture-staged-'+(++seq),name:input.name,mimeType:input.mimeType,size:input.dataBase64.length}),remove:async()=>{}};
window.ycode.speech={transcribe:async()=>{throw new Error('UI fixture does not call a speech service')}};
})();
</script>`
+65
View File
@@ -0,0 +1,65 @@
// Offline YCode state samples only; these do not establish original-app parity.
const now = Date.now()
const history = Array.from({ length: 14 }, (_, index) => {
const createdAt = now + index * 2
const text = Array.from({ length: 4 }, (__, paragraph) =>
`历史消息 ${index + 1},段落 ${paragraph + 1}。用于让会话时间线形成可滚动的真实内容。`.repeat(3)
).join('\n\n')
return [
{ id: `history-user-${index}`, role: 'user', content: `历史请求 ${index + 1}`, status: 'done', createdAt },
{ id: `history-assistant-${index}`, role: 'assistant', content: text, status: 'done', createdAt: createdAt + 1 }
]
}).flat()
export const conversationStatesFixture = {
sessions: [{ id: 'conversation-states', title: '对话状态回归', createdAt: now, updatedAt: now }],
messages: { 'conversation-states': history }
}
export const conversationStatesBridge = `<script>
(()=>{
const listeners=new Set(),runs=Object.create(null);let sequence=0;
const state={lastRunId:null,runs,responses:[],responsePlans:[],deferredResponses:[],earlyBatches:[],emit(event){
const runId=event.runId||state.lastRunId,run=runs[runId];
if(!run)throw new Error('No fixture run for event '+event.type);
const payload={...event,runId,sessionId:run.sessionId};
run.events.push(payload);listeners.forEach(listener=>listener(payload));
if(payload.type==='interaction')run.interactions[payload.interaction.id]=payload.interaction;
if(['done','cancelled','error'].includes(payload.type))run.finished=true;
return payload;
},queueResponse(mode){state.responsePlans.push(mode)},queueEarlyBatch(events){state.earlyBatches.push(events)},releaseDeferredResponse(){const release=state.deferredResponses.shift();if(!release)return false;release();return true}};
const completeResponse=(runId,id,response)=>{
const run=runs[runId],interaction=run?.interactions[id];
if(!interaction)return{accepted:false};
const option=interaction.options.find(item=>item.optionId===response.optionId);
if(!option)return{accepted:false};
const status=option.kind.startsWith('reject')?'rejected':'answered';
state.emit({runId,type:'interaction',interaction:{...interaction,selectedOptionId:option.optionId,status}});
return{accepted:true};
};
window.__YCODE_CONVERSATION_STATE_TEST__=state;
window.ycode.chat.onEvent=listener=>{listeners.add(listener);return()=>listeners.delete(listener)};
window.ycode.chat.send=async payload=>{
const runId='state-run-'+(++sequence),assistantMessageId=runId+'-assistant';
const run={runId,sessionId:payload.sessionId,assistantMessageId,events:[],interactions:Object.create(null),finished:false};
runs[runId]=run;state.lastRunId=runId;
const userMessage={id:runId+'-user',requestId:runId,role:'user',content:payload.text,attachments:payload.attachments,createdAt:Date.now(),status:'done'};
const earlyEvents=state.earlyBatches.shift()||[];
earlyEvents.forEach(event=>state.emit({...event,runId,...(event.type==='interaction'?{interaction:{...event.interaction,runId}}:{})}));
return{...run,userMessage};
};
window.ycode.chat.cancel=async runId=>{
const run=runs[runId];
if(!run||run.finished)return{cancelled:false};
state.emit({runId,type:'cancelled'});
return{cancelled:true};
};
window.ycode.chat.respond=async(runId,id,response)=>{
state.responses.push({runId,interactionId:id,response});
const mode=state.responsePlans.shift()||'success';
if(mode==='failure')throw new Error('fixture respond failure');
if(mode==='defer')return await new Promise(resolve=>state.deferredResponses.push(()=>resolve(completeResponse(runId,id,response))));
return completeResponse(runId,id,response);
};
})();
</script>`
+21
View File
@@ -0,0 +1,21 @@
// Offline verification data only; the resource bridge here never reads product files.
const now = Date.now()
const svgImage = (color, label) => `data:image/svg+xml;base64,${Buffer.from(`<svg xmlns="http://www.w3.org/2000/svg" width="320" height="160"><rect width="320" height="160" rx="12" fill="${color}"/><text x="160" y="88" text-anchor="middle" fill="white" font-size="28">${label}</text></svg>`).toString('base64')}`
const content = [
'## 图表、图片与文件交互', '',
'```mermaid', 'flowchart LR', ' A[输入] --> B[处理]', ' B --> C[输出]', '```', '',
'点击文件 `src/example.ts#L4-L7` 或目录 `src` 查看内容。', '',
'```ts:4:7:src/example.ts', 'export const result = input.map(transform)', '```', '',
'![蓝色示例](images/blue.svg)', '', '![绿色示例](images/green.svg)', '',
'以下验证错误图表仍可查看源码:', '',
'```mermaid', 'flowchart LR', ' A[unclosed', '```'
].join('\n')
export const dialogueMediaFixture = {
sessions: [{ id: 'dialogue-media', title: '图表、图片与文件交互', createdAt: now, updatedAt: now }],
messages: { 'dialogue-media': [
{ id: 'media-user', role: 'user', content: '验证图表缩放和下载、图片预览、文件行号跳转。', status: 'done', createdAt: now },
{ id: 'media-assistant', role: 'assistant', content, parts: [{ type: 'text', text: content }], tools: [], status: 'done', createdAt: now }
] },
images: { 'images/blue.svg': svgImage('#3567be', 'Image A'), 'images/green.svg': svgImage('#277c64', 'Image B') },
files: { 'src/example.ts': Array.from({ length: 32 }, (_, i) => `// example line ${i + 1}`).join('\n') }
}
+21
View File
@@ -0,0 +1,21 @@
// Offline YCode renderer cases. These are not original WorkBuddy runtime samples.
const now = Date.now()
const cases = [
['changed', '修改 Diff', 'sample.ts', 'modified', 'export const value = 2\n', '--- a/sample.ts\n+++ b/sample.ts\n@@ -1 +1 @@\n-export const value = 1\n+export const value = 2\n'],
['added', '新增 Diff', 'new.txt', 'added', 'created\n', '--- /dev/null\n+++ b/new.txt\n@@ -0,0 +1 @@\n+created\n'],
['deleted', '删除 Diff', 'empty.txt', 'deleted', '', '--- a/empty.txt\n+++ /dev/null\n@@ -1 +0,0 @@\n-removed\n'],
['unchanged', '相同 Diff', 'same.txt', 'modified', 'unchanged\n', '']
]
export const pierreDiffFixture = {
sessions: [{ id: 'pierre-diff', title: 'Pierre Diff 运行验证', createdAt: now, updatedAt: now }],
messages: { 'pierre-diff': [
{ id: 'user', role: 'user', content: '验证 Diff 渲染与视图切换。', status: 'done', createdAt: now },
{ id: 'assistant', role: 'assistant', content: '离线 Diff 样本。', status: 'done', createdAt: now + 1,
parts: [{ type: 'text', text: '离线 Diff 样本。' }, ...cases.map(([id, name, uri, changeType, cachedContent, diff]) => ({
type: 'artifact', artifact: { id, name, path: uri, preview: {
id, title: uri, type: 'file-changes', fileChangeInfo: { uri, changeType, cachedContent, diff }
} }
}))] }
] },
files: Object.fromEntries(cases.map(([, , uri, , content]) => [uri, content]))
}
+37
View File
@@ -0,0 +1,37 @@
// Offline verification only. No model request or product session is created.
const now = Date.now()
const content = [
'## 对话渲染源码还原验证',
'',
'行内公式:$E=mc^2$,集合宏:$\\RR$。',
'',
'$$',
'\\int_0^1 x^2\\,dx = \\frac{1}{3}',
'$$',
'',
'带文件和行号的代码:',
'',
'```ts:12:15:src/components/Message.tsx',
'export function Message({ text }: { text: string }) {',
' return <p>{text}</p>',
'}',
'```',
'',
'| 检查项 | 行为 |',
'| --- | --- |',
'| 公式 | KaTeX 渲染 |',
'| 代码 | 原文复制、文件行号 |',
'| 表格 | 引用原始 Markdown |',
'',
'- [x] 完成内容保持原顺序',
'- [ ] 继续补齐宿主能力',
'',
'<function_calls><invoke name="hidden">protocol payload</invoke></function_calls>'
].join('\n')
export const sourceRecoveryFixture = {
sessions: [{ id: 'source-recovery', title: '对话渲染源码还原', createdAt: now, updatedAt: now }],
messages: { 'source-recovery': [
{ id: 'recovery-user', role: 'user', content: '验证数学公式、代码文件行号和表格引用。', status: 'done', createdAt: now },
{ id: 'recovery-assistant', role: 'assistant', content, parts: [{ type: 'text', text: content }], tools: [], status: 'done', createdAt: now }
] }
}
+26
View File
@@ -0,0 +1,26 @@
// Verification fixture only. Does not create real sessions or contact a model.
const now = Date.now()
const content = [
'## 字体与间距', '',
'这是一段用于核对正文的文本,包含 **加粗文字** 和 `inline code`。', '',
'下一段文字保持相同的正文规则。字号改变时,段落间距使用公共间距变量。', '',
'- 一级列表', ' - 二级列表', '- 第二项', '',
'> 引用内容,用于检查继承的字号和行高。', '',
'| 项目 | 内容 |', '| --- | --- |', '| 字体 | 统一字号 |', '| 间距 | 公共变量 |', '',
'```ts', 'const greeting = "你好,WorkBuddy"', 'console.log(greeting)', '```'
].join('\n')
export const typographyFixture = {
sessions: [{ id: 'typography', title: '字体与间距核对', createdAt: now, updatedAt: now }],
messages: { typography: [
{ id: 'typography-user', role: 'user', content: '核对正文、代码和控件在六档字号下的表现。', status: 'done', createdAt: now },
{ id: 'typography-assistant', role: 'assistant', content, parts: [{ type: 'text', text: content }], tools: [], status: 'done', createdAt: now }
] }
}
// Off-canvas measurement probes for the unified handler, not product UI.
export const typographyProbes = `<style id="typography-fixture-style">
#typography-probes { position: fixed; left: -10000px; top: 0; }
.typography-probe-static { font-size: 13px; }
.typography-probe-semantic { font-size: var(--yc-text-body-size); line-height: var(--yc-text-body-line-height); }
.typography-probe-wb { font-size: var(--wb-font-body-size); }
</style><div id="typography-probes" aria-hidden="true"><span class="typography-probe-static">static</span><span class="typography-probe-semantic">semantic</span><span class="typography-probe-wb">wb</span><div class="cb-font-size-fixed"><span class="typography-probe-static">fixed static</span><span class="typography-probe-semantic">fixed semantic</span><span class="typography-probe-wb">fixed wb</span></div></div>`