chore: establish YCode replication baseline and TODO
This commit is contained in:
commit
6dc59f89ba
1118 files changed
+196002
No files matched your search
@@ -0,0 +1,264 @@
|
||||
// Recover source tool-result view styles from already-exported REA Evidence.
|
||||
import { createHash } from 'node:crypto'
|
||||
import { readFile, writeFile } from 'node:fs/promises'
|
||||
import { dirname, resolve } from 'node:path'
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import { parse } from '@babel/parser'
|
||||
import postcss from 'postcss'
|
||||
|
||||
const rootDir = resolve(dirname(fileURLToPath(import.meta.url)), '../..')
|
||||
const runtimeEvidencePath = resolve(rootDir, '.tmp/rea-runtime-scripts.json')
|
||||
const cssDirectory = resolve(rootDir, '.tmp/rea-css-recovered')
|
||||
const outputPath = resolve(rootDir, 'src/renderer/src/workbuddy/conversation/tool-result-source.css')
|
||||
|
||||
const runtimeEvidenceId = 'ev_717fa5e846e64d67ac19c8925d121bff632c0d3aefb3603b10858559cabb2dcb'
|
||||
const runtimeScriptPath = 'renderer/assets/src-DbE1_mgM.js'
|
||||
const runtimeScriptSha256 = '6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4'
|
||||
const cssEvidenceId = 'ev_377c8790468b3c67dad8577aabb327f98d3140659f0fffdbabfcff5a40cc9e94'
|
||||
const cssFile = 'src-CyXHA0IC.css'
|
||||
const cssSha256 = 'a5e26b537bb50323aefbf25abddad52e288dd3868598be8d255d70886fe77cfe'
|
||||
|
||||
const commandAliases = ['execute_command', 'ExecuteCommand', 'run_command', 'run_terminal_cmd', 'Bash', 'PowerShell', 'BashOutput']
|
||||
const commandRoot = `.cr-captured-tool:is(${commandAliases.map((name) => `[data-tool-name="${name}"]`).join(',')})`
|
||||
const publicClassFamilies = [
|
||||
'.cr-tool-btn',
|
||||
'.cr-tool-head',
|
||||
'.cr-tool-exp',
|
||||
'.cr-tool-list-files__',
|
||||
'.cr-tool-search-ref__',
|
||||
'.cr-tool-web-search__',
|
||||
'.cr-tool-mcp__',
|
||||
'.cr-tool-mcp-display__',
|
||||
'.cr-tool-display-list',
|
||||
'.cr-tool-write__',
|
||||
'.cr-tool-diff'
|
||||
]
|
||||
|
||||
function digest(bytes) {
|
||||
return createHash('sha256').update(bytes).digest('hex')
|
||||
}
|
||||
|
||||
function verifyArtifact(label, bytes, expectedSha256) {
|
||||
const actual = digest(bytes)
|
||||
if (actual !== expectedSha256) throw new Error(`${label} SHA-256 mismatch: expected ${expectedSha256}, got ${actual}`)
|
||||
}
|
||||
|
||||
const runtimeEvidence = JSON.parse(await readFile(runtimeEvidencePath, 'utf8'))
|
||||
if (runtimeEvidence.evidence_id !== runtimeEvidenceId) {
|
||||
throw new Error(`Runtime Evidence changed: expected ${runtimeEvidenceId}, got ${runtimeEvidence.evidence_id ?? 'none'}`)
|
||||
}
|
||||
|
||||
const runtimeMatches = runtimeEvidence.items.filter((item) => item.file_path?.replace(/\\/g, '/').endsWith(runtimeScriptPath))
|
||||
if (runtimeMatches.length !== 1) throw new Error(`Expected one REA runtime script at ${runtimeScriptPath}, found ${runtimeMatches.length}`)
|
||||
const runtimeArtifact = runtimeMatches[0].source?.artifact
|
||||
if (!runtimeMatches[0].source?.included || runtimeArtifact?.media_type !== 'text/javascript') {
|
||||
throw new Error('REA renderer source is not included as JavaScript')
|
||||
}
|
||||
const runtimeBytes = Buffer.from(runtimeArtifact.text, 'utf8')
|
||||
verifyArtifact(runtimeScriptPath, runtimeBytes, runtimeScriptSha256)
|
||||
if (runtimeArtifact.sha256 !== runtimeScriptSha256 || runtimeArtifact.bytes !== runtimeBytes.length) {
|
||||
throw new Error(`REA runtime artifact metadata mismatch for ${runtimeScriptPath}`)
|
||||
}
|
||||
|
||||
const runtimeAst = parse(runtimeArtifact.text, { sourceType: 'unambiguous' })
|
||||
const declarations = new Map()
|
||||
function findFunctions(node) {
|
||||
if (!node || typeof node !== 'object') return
|
||||
if (node.type === 'FunctionDeclaration' && [
|
||||
'getPrefixCls', 'usePrefixCls', 'ToolExpandable', 'ExecuteCommandView', 'convertExecuteCommand',
|
||||
'ReadFileView', 'convertReadFile', 'ListFilesView', 'convertListFiles', 'McpCallToolView',
|
||||
'convertMcpCallTool', 'McpDisplayView', 'convertMcpDisplay', 'WebSearchView', 'convertWebSearch',
|
||||
'SearchReferenceView', 'convertSearchReference', 'WebFetchView', 'convertWebFetch',
|
||||
'computeLineDiff', 'trimToChangedRegion', 'convertWriteFile', 'WriteFileView'
|
||||
].includes(node.id?.name)) {
|
||||
declarations.set(node.id.name, runtimeArtifact.text.slice(node.start, node.end))
|
||||
}
|
||||
for (const value of Object.values(node)) {
|
||||
if (Array.isArray(value)) value.forEach(findFunctions)
|
||||
else if (value && typeof value === 'object') findFunctions(value)
|
||||
}
|
||||
}
|
||||
findFunctions(runtimeAst)
|
||||
|
||||
const prefixFactory = declarations.get('getPrefixCls')
|
||||
const prefixHook = declarations.get('usePrefixCls')
|
||||
const expandable = declarations.get('ToolExpandable')
|
||||
const commandView = declarations.get('ExecuteCommandView')
|
||||
const readFileView = declarations.get('ReadFileView')
|
||||
const readFileConverter = declarations.get('convertReadFile')
|
||||
const listFilesView = declarations.get('ListFilesView')
|
||||
const listFilesConverter = declarations.get('convertListFiles')
|
||||
const mcpCallView = declarations.get('McpCallToolView')
|
||||
const mcpCallConverter = declarations.get('convertMcpCallTool')
|
||||
const mcpDisplayView = declarations.get('McpDisplayView')
|
||||
const mcpDisplayConverter = declarations.get('convertMcpDisplay')
|
||||
const webSearchView = declarations.get('WebSearchView')
|
||||
const webSearchConverter = declarations.get('convertWebSearch')
|
||||
const searchReferenceView = declarations.get('SearchReferenceView')
|
||||
const searchReferenceConverter = declarations.get('convertSearchReference')
|
||||
const webFetchView = declarations.get('WebFetchView')
|
||||
const webFetchConverter = declarations.get('convertWebFetch')
|
||||
const lineDiff = declarations.get('computeLineDiff')
|
||||
const changedRegion = declarations.get('trimToChangedRegion')
|
||||
const writeFileView = declarations.get('WriteFileView')
|
||||
const writeFileConverter = declarations.get('convertWriteFile')
|
||||
if (!prefixFactory?.includes('let c=`cr-${a}`')) throw new Error('REA prefix helper no longer builds the cr- prefix')
|
||||
if (!prefixHook?.includes('getPrefixCls(n)')) throw new Error('REA usePrefixCls no longer calls getPrefixCls')
|
||||
if (!runtimeArtifact.text.includes('useRenderDiag(`ToolHeader`')) throw new Error('REA public ToolHeader anchor changed')
|
||||
for (const marker of ['g(`tool-exp`)', 'UT,{...h,actions:m,collapsible:b,expanded:x,onToggle:b?w:void 0}', 'g(`tool-exp__content-shell`)']) {
|
||||
if (!expandable?.includes(marker)) throw new Error(`REA ToolExpandable is missing ${marker}`)
|
||||
}
|
||||
for (const marker of ['m=usePrefixCls()', 'm(`tool-exec__command`)', 'm(`tool-exec__output`)', 'children:`bash`', 'p.stdout', 'p.stderr', 'tool.command.failed']) {
|
||||
if (!commandView?.includes(marker)) throw new Error(`REA ExecuteCommandView is missing ${marker}`)
|
||||
}
|
||||
const commandRegistration = 'id:`execute_command`,match:[`execute_command`,`ExecuteCommand`,`run_command`,`run_terminal_cmd`,`Bash`,`PowerShell`,`BashOutput`],convert:convertExecuteCommand,Component:ExecuteCommandView'
|
||||
if (!runtimeArtifact.text.includes(commandRegistration)) throw new Error('REA execute_command registration or aliases changed')
|
||||
for (const marker of ['primaryContent:f.fileName', 'primaryTone:`link`', 'onPrimaryClick:y?()=>u(`tool.file.open`']) {
|
||||
if (!readFileView?.includes(marker)) throw new Error(`REA ReadFileView is missing ${marker}`)
|
||||
}
|
||||
for (const marker of ['readCompleteTextContent(n)', 'fileNameFromPath(c)', 'startLine:num(a.startLine)']) {
|
||||
if (!readFileConverter?.includes(marker)) throw new Error(`REA convertReadFile is missing ${marker}`)
|
||||
}
|
||||
const readFileRegistration = 'id:`read_file`,match:[`read_file`,`read-file`,`Read`,`NotebookRead`],convert:convertReadFile,Component:ReadFileView'
|
||||
if (!runtimeArtifact.text.includes(readFileRegistration)) throw new Error('REA read_file registration or aliases changed')
|
||||
if (readFileView.includes('children:')) throw new Error('REA ReadFileView is no longer header-only; review before changing the projection')
|
||||
for (const marker of ['tool-list-files__items', 'tool.file.open', 'canExpand:T']) {
|
||||
if (!listFilesView?.includes(marker)) throw new Error(`REA ListFilesView is missing ${marker}`)
|
||||
}
|
||||
for (const marker of ['readFileResult(n.result)', 'fileNameFromPath(d)', 'searchScope:firstStringValue(c.glob,p)']) {
|
||||
if (!listFilesConverter?.includes(marker)) throw new Error(`REA convertListFiles is missing ${marker}`)
|
||||
}
|
||||
const listFilesRegistration = 'id:`list_files`,match:[`list_dir`,`list_files`,`search_file`,`search_content`,`Glob`,`Grep`],convert:convertListFiles,Component:ListFilesView'
|
||||
if (!runtimeArtifact.text.includes(listFilesRegistration)) throw new Error('REA list_files registration or aliases changed')
|
||||
for (const marker of ['tool-mcp__body', 'tool-mcp__block-title', 'tool-mcp__pre']) {
|
||||
if (!mcpCallView?.includes(marker)) throw new Error(`REA McpCallToolView is missing ${marker}`)
|
||||
}
|
||||
for (const marker of ['parseArgs$1(a)', 'stringifyContent(m)', 'isError:!!c.isError']) {
|
||||
if (!mcpCallConverter?.includes(marker)) throw new Error(`REA convertMcpCallTool is missing ${marker}`)
|
||||
}
|
||||
const mcpCallRegistration = 'id:`mcp_call_tool`,match:`mcp_call_tool`,convert:convertMcpCallTool,Component:McpCallToolView'
|
||||
if (!runtimeArtifact.text.includes(mcpCallRegistration)) throw new Error('REA mcp_call_tool registration changed')
|
||||
for (const marker of ['getMcpDisplayInfo(n.name,n.args,c)', 'getMcpDetailPlan(n.name,n.args)', 'JSON.stringify({parameters:normalizeArgs(n.args),result:f},null,2)']) {
|
||||
if (!mcpDisplayConverter?.includes(marker)) throw new Error(`REA convertMcpDisplay is missing ${marker}`)
|
||||
}
|
||||
if (!mcpDisplayView?.includes('ToolDisplayList')) throw new Error('REA McpDisplayView no longer uses ToolDisplayList')
|
||||
if (!runtimeArtifact.text.includes('id:`mcp_display`,match:n=>isKnownMcpTool(n),convert:convertMcpDisplay,Component:McpDisplayView')) {
|
||||
throw new Error('REA mcp_display registration changed')
|
||||
}
|
||||
for (const marker of ['tool-web-search__results', 'ResultRow', 'tool.link.open']) {
|
||||
if (!webSearchView?.includes(marker)) throw new Error(`REA WebSearchView is missing ${marker}`)
|
||||
}
|
||||
for (const marker of ['getPayloadCandidates(n)', 'parseSearchResultsFromMarkdown(getTextResult(n))', '.map(normalizeResult)']) {
|
||||
if (!webSearchConverter?.includes(marker)) throw new Error(`REA convertWebSearch is missing ${marker}`)
|
||||
}
|
||||
for (const marker of ['tool-search-ref__items', 'tool.link.open']) {
|
||||
if (!searchReferenceView?.includes(marker)) throw new Error(`REA SearchReferenceView is missing ${marker}`)
|
||||
}
|
||||
for (const marker of ['n.result?.result', '/^\\d+$/', 'a.file_name', 'a.source']) {
|
||||
if (!searchReferenceConverter?.includes(marker)) throw new Error(`REA convertSearchReference is missing ${marker}`)
|
||||
}
|
||||
if (!runtimeArtifact.text.includes('id:`search_reference`,match:[`codebase_search`,`CodebaseSearch`,`RAG_search`],convert:convertSearchReference,Component:SearchReferenceView')) {
|
||||
throw new Error('REA search_reference registration or aliases changed')
|
||||
}
|
||||
for (const marker of ['tool.link.open', 'primaryContent:f.displayTitle', 'primaryTitle:f.url']) {
|
||||
if (!webFetchView?.includes(marker)) throw new Error(`REA WebFetchView is missing ${marker}`)
|
||||
}
|
||||
for (const marker of ['toStringValue(a.url)', 'summarizing:!!c.loading']) {
|
||||
if (!webFetchConverter?.includes(marker)) throw new Error(`REA convertWebFetch is missing ${marker}`)
|
||||
}
|
||||
if (!runtimeArtifact.text.includes('id:`web_fetch`,match:[`web_fetch`,`WebFetch`],convert:convertWebFetch,Component:WebFetchView')) {
|
||||
throw new Error('REA web_fetch registration or aliases changed')
|
||||
}
|
||||
for (const marker of ['fileName:u.split(`/`).pop()||u', 'normalizeEdits(a.edits)', 'getResultStats(c)', 'addedLines:_.added??v.added', 'removedLines:_.removed??v.removed']) {
|
||||
if (!writeFileConverter?.includes(marker)) throw new Error(`REA convertWriteFile is missing ${marker}`)
|
||||
}
|
||||
for (const marker of ['primaryContent:A?p.fileName', 'primaryTone:A?`link`', 'tool.file.open', 'secondaryInfo:E', 'tool-write__body', 'aE']) {
|
||||
if (!writeFileView?.includes(marker)) throw new Error(`REA WriteFileView is missing ${marker}`)
|
||||
}
|
||||
const writeFileRegistration = 'id:`write_file`,match:[`write_to_file`,`write_file`,`edit_file`,`replace_in_file`,`append_to_file`,`Write`,`Edit`,`MultiEdit`,`NotebookEdit`],convert:convertWriteFile,Component:WriteFileView'
|
||||
if (!runtimeArtifact.text.includes(writeFileRegistration)) throw new Error('REA write_file registration or aliases changed')
|
||||
if (!lineDiff?.includes('p[n+1][a+1]+1') || !lineDiff.includes('YT')) throw new Error('REA write-file line diff algorithm changed')
|
||||
if (!changedRegion?.includes('n.findIndex(n=>n.type!==`context`)')) throw new Error('REA write-file diff context trimming changed')
|
||||
|
||||
const cssManifest = JSON.parse(await readFile(resolve(cssDirectory, 'manifest.json'), 'utf8'))
|
||||
if (cssManifest.sourceEvidenceId !== cssEvidenceId) {
|
||||
throw new Error(`CSS Evidence changed: expected ${cssEvidenceId}, got ${cssManifest.sourceEvidenceId ?? 'none'}`)
|
||||
}
|
||||
if (cssManifest.target?.title !== 'WorkBuddy') throw new Error('REA CSS target is not the recorded WorkBuddy page')
|
||||
const cssMetadata = cssManifest.files?.find((file) => file.file === cssFile)
|
||||
if (!cssMetadata || cssMetadata.sha256 !== cssSha256) throw new Error(`REA CSS manifest has no expected digest for ${cssFile}`)
|
||||
if (cssMetadata.asarComparison?.status !== 'match' || cssMetadata.asarComparison.expectedSha256 !== cssSha256) {
|
||||
throw new Error(`REA CSS ASAR identity changed for ${cssFile}`)
|
||||
}
|
||||
const cssBytes = await readFile(resolve(cssDirectory, cssFile))
|
||||
verifyArtifact(cssFile, cssBytes, cssSha256)
|
||||
if (cssMetadata.bytes !== cssBytes.length) throw new Error(`REA CSS byte count mismatch for ${cssFile}`)
|
||||
|
||||
const source = postcss.parse(cssBytes, { from: cssFile })
|
||||
const output = postcss.root()
|
||||
const sourceSelectors = new Set()
|
||||
let recoveredRuleCount = 0
|
||||
function projectToolRule(node) {
|
||||
if (node.type === 'atrule' && node.nodes) {
|
||||
const children = node.nodes.map(projectToolRule).filter(Boolean)
|
||||
return children.length ? node.clone({ nodes: children }) : null
|
||||
}
|
||||
if (node.type !== 'rule') return null
|
||||
const rule = node
|
||||
const selectors = rule.selectors.map((selector) => selector.trim())
|
||||
for (const selector of selectors) sourceSelectors.add(selector)
|
||||
if (selectors.every((selector) => selector.startsWith('.cr-tool-exec__'))) {
|
||||
recoveredRuleCount += 1
|
||||
return rule.clone({ selector: selectors.map((selector) => `${commandRoot} ${selector}`).join(',') })
|
||||
}
|
||||
if (selectors.every((selector) => publicClassFamilies.some((family) => selector.startsWith(family)))) {
|
||||
recoveredRuleCount += 1
|
||||
return rule.clone()
|
||||
}
|
||||
return null
|
||||
}
|
||||
for (const node of source.nodes) {
|
||||
const projected = projectToolRule(node)
|
||||
if (projected) output.append(projected)
|
||||
}
|
||||
|
||||
for (const selector of [
|
||||
'.cr-tool-btn', '.cr-tool-btn--primary', '.cr-tool-btn--danger',
|
||||
'.cr-tool-head', '.cr-tool-exp', '.cr-tool-exp__content',
|
||||
'.cr-tool-exec__title', '.cr-tool-exec__output', '.cr-tool-list-files__items',
|
||||
'.cr-tool-search-ref__items', '.cr-tool-web-search__results', '.cr-tool-mcp__body',
|
||||
'.cr-tool-display-list', '.cr-tool-write__content', '.cr-tool-write__body',
|
||||
'.cr-tool-write__pre', '.cr-tool-diff', '.cr-tool-diff__viewport',
|
||||
'.cr-tool-diff__line', '.cr-tool-diff__sign', '.cr-tool-diff__code'
|
||||
]) {
|
||||
if (!sourceSelectors.has(selector)) throw new Error(`REA tool CSS is missing ${selector}`)
|
||||
}
|
||||
if (recoveredRuleCount === 0) throw new Error('No REA tool result CSS rules were recovered')
|
||||
|
||||
const header = `/* Generated by recover-tool-result-styles.mjs from REA runtime JavaScript ${runtimeEvidenceId} (${runtimeScriptSha256}) and CSS ${cssEvidenceId} (${cssSha256}).
|
||||
* Shared ToolHeader and ToolExpandable rules are projected with their source class names.
|
||||
* ExecuteCommandView combines stdout and stderr into one tool-exec__output div; command rules are scoped to registered command aliases.
|
||||
* ReadFileView is header-only and passes complete text to the file-open action. WriteFileView retains the source write/diff classes.
|
||||
* File-list, Web, MCP and tool-display rules retain their source classes.
|
||||
*/\n`
|
||||
await writeFile(outputPath, header + output.toString() + '\n')
|
||||
|
||||
console.log(JSON.stringify({
|
||||
runtimeEvidenceId,
|
||||
runtimeScriptPath,
|
||||
runtimeScriptSha256,
|
||||
prefixFactory,
|
||||
commandViewStart: runtimeArtifact.text.indexOf('function ExecuteCommandView'),
|
||||
commandAliases,
|
||||
sourceOutputBehavior: 'stdout and stderr are joined and rendered with tool-exec__output; failure text is appended for error status or nonzero exit code',
|
||||
readFileViewStart: runtimeArtifact.text.indexOf('function ReadFileView'),
|
||||
readFileViewShape: 'header-only; file path is a tool.file.open action',
|
||||
writeFileViewStart: runtimeArtifact.text.indexOf('function WriteFileView'),
|
||||
writeFileViewShape: 'file path opens by tool.file.open; changed content is rendered with the source aE diff view',
|
||||
cssEvidenceId,
|
||||
cssFile,
|
||||
cssSha256,
|
||||
recoveredRuleCount,
|
||||
publicClassFamilies,
|
||||
outputPath
|
||||
}, null, 2))
|
||||
Reference in new issue
Block a user