import fs from 'node:fs/promises' import path from 'node:path' import { createHash } from 'node:crypto' import { parse } from '@babel/parser' import traverseModule from '@babel/traverse' import { exportSelectedArtifactText } from '../../.tmp/rea-css-runtime/dist/artifacts/SelectedArtifactText.js' const traverse = traverseModule.default, hash = value => createHash('sha256').update(value).digest('hex') const rootSha = '035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918' const archive = 'C:/Users/Administrator/AppData/Local/Programs/WorkBuddy/resources/app.asar' const target = path.resolve('src/renderer/src/workbuddy/workbench/source-code-assets') const runtime = JSON.parse(await fs.readFile('.tmp/rea-runtime-scripts.json', 'utf8')) const selected = JSON.parse(await fs.readFile('.tmp/rea-selected-editor-evidence.json', 'utf8')) const cssManifest = JSON.parse(await fs.readFile('.tmp/rea-css-recovered/manifest.json', 'utf8')) if (selected.normalized_result.root_sha256 !== rootSha) throw Error('Source archive identity changed') const files = new Map(), graph = {}, records = [] for (const item of runtime.items) { const a = item.source?.artifact if (!a?.text) continue if (hash(a.text) !== a.sha256) throw Error('Runtime source digest changed') files.set(path.basename(item.file_path.replaceAll('\\', '/')), { text: a.text, sha256: a.sha256, evidenceId: runtime.evidence_id }) } for (const f of selected.normalized_result.files) { if (hash(f.text) !== f.sha256) throw Error('Selected editor digest changed') files.set(path.basename(f.path), { text: f.text, sha256: f.sha256, evidenceId: selected.evidence_id }) } for (const name of (await fs.readdir('.tmp')).filter(name => /^rea-monaco-chunks-\d+\.json$/.test(name)).sort()) { const evidencePath = path.resolve('.tmp', name), evidence = JSON.parse(await fs.readFile(evidencePath, 'utf8')) if (evidence.authority !== 'shipped-artifact' || evidence.normalized_result.root_sha256 !== rootSha) throw Error('Cached REA identity changed') records.push({ evidenceId: evidence.evidence_id, path: evidencePath }) for (const f of evidence.normalized_result.files) { const body = f.text ?? Buffer.from(f.data_base64, 'base64') if (hash(body) !== f.sha256) throw Error('Cached REA source digest changed') files.set(path.basename(f.path), { [f.text === undefined ? 'binary' : 'text']: body, sha256: f.sha256, evidenceId: evidence.evidence_id }) } } for (const f of cssManifest.files) { const text = await fs.readFile(path.join('.tmp/rea-css-recovered', f.file), 'utf8') if (hash(text) !== f.sha256) throw Error('CSS digest changed') files.set(f.file, { text, sha256: f.sha256, evidenceId: cssManifest.sourceEvidenceId }) } function dependencies(name, text) { const deps = new Set() const add = value => { if (value?.startsWith('./') && /\.(?:js|css|ttf|woff2?)$/.test(value)) deps.add(value.slice(2)) } if (name.endsWith('.css')) for (const m of text.matchAll(/url\(['"]?(\.\/[^'"\)]+)['"]?\)/g)) add(m[1]) else if (name.endsWith('.js')) { const ast = parse(text, { sourceType: 'module' }) traverse(ast, { ImportDeclaration(p) { add(p.node.source.value) }, NewExpression(p) { if (p.node.callee.type !== 'Identifier' || p.node.callee.name !== 'URL') return const n = p.node.arguments[0], value = n?.type === 'StringLiteral' ? n.value : n?.type === 'TemplateLiteral' && !n.expressions.length ? n.quasis[0].value.cooked : undefined if (value && /^[\w.-]+\.(?:js|css)$/.test(value)) add('./' + value) else add(value) }, CallExpression(p) { if (p.node.callee.type !== 'Import') return const n = p.node.arguments[0]; add(n.type === 'StringLiteral' ? n.value : n.type === 'TemplateLiteral' && !n.expressions.length ? n.quasis[0].value.cooked : undefined) }, AssignmentExpression(p) { if (p.node.left.type === 'MemberExpression' && p.node.left.property.name === 'f' && p.node.right.type === 'ArrayExpression') for (const n of p.node.right.elements) if (n?.type === 'StringLiteral') add(n.value) } }) } return [...deps].filter(name => name !== 'react-z__Ncn__.js') } const wanted = new Set(['editor.main-POO0Vbhx.js', 'monaco-init-CE4MbM4x.js', 'editor-gwlzV742.css', 'codeEditor-Bxmo_AI3.css']) for (;;) { const missing = [...wanted].filter(name => !files.has(name)) for (let offset = 0; offset < missing.length; offset += 16) { const batch = missing.slice(offset, offset + 16) for (const binary of [false, true]) { const names = batch.filter(name => /\.(?:ttf|woff2?)$/.test(name) === binary) if (!names.length) continue const evidence = await exportSelectedArtifactText(archive, rootSha, names.map(name => 'renderer/assets/' + name), binary) const evidencePath = path.resolve(`.tmp/rea-monaco-chunks-${records.length.toString().padStart(3, '0')}.json`) await fs.writeFile(evidencePath, JSON.stringify(evidence)) records.push({ evidenceId: evidence.evidence_id, path: evidencePath }) for (const f of evidence.normalized_result.files) { const body = binary ? Buffer.from(f.data_base64, 'base64') : f.text if (hash(body) !== f.sha256) throw Error('REA export digest mismatch') files.set(path.basename(f.path), { [binary ? 'binary' : 'text']: body, sha256: f.sha256, evidenceId: evidence.evidence_id }) } } } const before = wanted.size for (const name of wanted) { const file = files.get(name) if (!file) continue graph[name] = file.text ? dependencies(name, file.text) : [] for (const dep of graph[name]) wanted.add(dep) } if (wanted.size === before && [...wanted].every(name => files.has(name))) break } await fs.mkdir(target, { recursive: true }) const assets = [] for (const name of wanted) { const file = files.get(name); let text = file.text, adapters = [] if (name.endsWith('.js') && text.includes('__vite__mapDeps')) { const ast = parse(text, { sourceType: 'module' }), edits = [] traverse(ast, { VariableDeclarator(p) { if (p.node.id.name === '__vite__mapDeps') edits.push({ start: p.node.start, end: p.node.end, text: '__ycodeMonacoMapDeps=()=>[]' }) }, Identifier(p) { if (p.node.name === '__vite__mapDeps' && p.parent.type === 'CallExpression' && p.parent.callee === p.node) edits.push({ start: p.node.start, end: p.node.end, text: '__ycodeMonacoMapDeps' }) } }) for (const edit of edits.sort((a, b) => b.start - a.start)) text = text.slice(0, edit.start) + edit.text + text.slice(edit.end) adapters.push('Original bundler preload table replaced by empty host preload adapter; Vite owns imports/CSS, avoiding its reserved helper binding and obsolete original URLs.') } if (name === 'monaco-init-CE4MbM4x.js') { const fallback = 'P.config({paths:{vs:`https://cdn.jsdelivr.net/npm/monaco-editor@0.45.0/min/vs`}})' if (text.split(fallback).length !== 3) throw Error('Monaco local-only fallback boundary changed') text = text.replaceAll(fallback, '(()=>{throw Error(`YCode local Monaco assets failed to load`)})()') adapters.push('Two CDN fallback branches fail locally; source local loader/theme/React host preserved.') } const bytes = file.binary ?? text await fs.writeFile(path.join(target, name), bytes) assets.push({ name, sourceSha256: file.sha256, outputSha256: hash(bytes), evidenceId: file.evidenceId, adapters }) } // Use YCode's existing React instance, never initialize the original application's React globals. await fs.writeFile(path.join(target, 'react-z__Ncn__.js'), "import React from 'react';export function t(){return React}\n") const source = files.get('codeEditor-D3P9alks.js').text const ast = parse(source, { sourceType: 'module' }), snippets = {} traverse(ast, { AssignmentExpression(p) { const n = p.node, name = n.left.type === 'Identifier' ? n.left.name : '' if ((name === 're' && n.start > 14000 && n.start < 15000) || (name === 'ee' && n.start > 11000 && n.start < 12000) || (['R', 'B'].includes(name) && n.start > 8000 && n.start < 11624) || (name === 'q' && n.start > 14287 && n.start < 14737) || ['UpArrowIcon', 'DownArrowIcon'].includes(name)) snippets[name] = { text: source.slice(n.start, n.end), start: n.start, end: n.end } }, FunctionDeclaration(p) { if (['getMonacoLanguage', 'getFontSizeOffset$1'].includes(p.node.id?.name)) snippets[p.node.id.name] = { text: source.slice(p.node.start, p.node.end), start: p.node.start, end: p.node.end } } }) for (const name of ['re', 'ee', 'R', 'B', 'q', 'UpArrowIcon', 'DownArrowIcon', 'getMonacoLanguage', 'getFontSizeOffset$1']) if (!snippets[name]) throw Error('Missing source closure ' + name) const locale = files.get('zh-cn-Dfzn8myY.js'), labels = {} for (const m of locale.text.matchAll(/"(search\.[^"]+)":(`(?:\\.|[^`])*`)/g)) { const literal = parse(m[2], { sourceType: 'module' }).program.body[0].expression if (literal.type !== 'TemplateLiteral' || literal.expressions.length) throw Error('Locale must be a static string') labels[m[1]] = literal.quasis[0].value.cooked } const media = files.get('media-preview-DMz4TW4q.js').text let extensionBody traverse(parse(media, { sourceType: 'module' }), { AssignmentExpression(p) { if (p.node.left.name === 'getLanguageFromFileName') extensionBody = media.slice(p.node.start, p.node.end) } }) if (!extensionBody || hash(extensionBody) !== '666dfd63d32a89ed66020d0a4fb6d1a41c25be41692c3538e6b167c157fa1465') throw Error('Language source body changed') await fs.writeFile(path.join(target, 'extension.mjs'), 'let getLanguageFromFileName;' + extensionBody + ';export {getLanguageFromFileName};\n') await fs.writeFile(path.join(target, 'extension.d.mts'), 'export function getLanguageFromFileName(name:string):string;\n') const wrapper = `// Generated source bodies; host bindings are explicit adapters below. No WorkBuddy services.\nimport * as K from 'react';import * as ne from 'react/jsx-runtime';import {c as O,d as A,r as F} from './monaco-init-CE4MbM4x.js';\nconst U=K,W=ne;const classes=(...a)=>a.flatMap(x=>typeof x==='string'?[x]:x&&typeof x==='object'?Object.keys(x).filter(k=>x[k]):[]).join(' ');const H={default:classes},te=H;const labels=${JSON.stringify(labels)};function u(){return key=>labels[key]||key}\nconst g=K.forwardRef(({value,onChange,placeholder,className},ref)=>ne.jsx('span',{className:'wb-input-wrapper wb-input-wrapper--small wb-input-wrapper--borderless '+className,children:ne.jsx('input',{ref,value,placeholder,className:'wb-input__inner',onChange:e=>onChange(e.target.value)})}));\nconst p=({variant='ghost',size='small',iconOnly,className,children,...props})=>ne.jsx('button',{...props,type:'button',className:classes('wb-button','wb-button--'+variant,'wb-button--'+size,iconOnly&&'wb-button--icon-only',className),children});const m=p;const h=()=>ne.jsx('svg',{width:16,height:16,viewBox:'0 0 16 16',fill:'none',children:ne.jsx('path',{d:'M4 4l8 8M12 4l-8 8',stroke:'currentColor',strokeWidth:1.2,strokeLinecap:'round'})});\nlet R,B,q,ee,re,UpArrowIcon,DownArrowIcon;\n${['R','B','q','UpArrowIcon','DownArrowIcon','ee','getMonacoLanguage','getFontSizeOffset$1','re'].map(n=>snippets[n].text+';').join('\n')}\nexport {re as MonacoEditor,O as configureMonaco,F as themeManager};\n` const sourceUi = files.get('src-0FGg1seX.js').text let closeBody traverse(parse(sourceUi, { sourceType: 'module' }), { AssignmentExpression(p) { if (p.node.left.name === 'CloseIcon$2' && p.node.start === 245582) closeBody = sourceUi.slice(p.node.start, p.node.end) } }) if (!closeBody) throw Error('Source close icon changed') const closeAdapter = `const Lm=ne;let CloseIcon$2;${closeBody};const h=CloseIcon$2;` const finalWrapper = wrapper.replace(/const h=\(\)=>ne\.jsx\('svg',[^\n]+?\);\nlet R/, closeAdapter + '\nlet R') if (finalWrapper === wrapper) throw Error('Close icon adapter replacement failed') await fs.writeFile(path.join(target, 'wrapper.mjs'), finalWrapper) await fs.writeFile(path.join(target, 'wrapper.d.mts'), `import type {ComponentType} from 'react';export const MonacoEditor:ComponentType<{value:string;language?:string;readOnly?:boolean;minimap?:boolean;lineNumbers?:string;wordWrap?:string;fontSize?:number;height?:string;onMount?:(editor:any,monaco:any)=>void}>;export function configureMonaco():Promise;export function themeManager():{setTheme(name:string):void};\n`) await fs.writeFile(path.join(target, 'manifest.json'), JSON.stringify({ rootSha256: rootSha, version: '5.8.2', monacoPackageVersion: 'unconfirmed; exact shipped chunks used', records, assets, graph, wrapper: Object.fromEntries(Object.entries(snippets).map(([name, body]) => [name, { start: body.start, end: body.end, sha256: hash(body.text) }])), sourceCloseIcon: { offset: 245582, sha256: hash(closeBody), evidenceId: runtime.evidence_id }, hostAdapters: ['YCode React singleton', 'native input/button/className/i18n bindings', 'local-only failure instead of CDN fallback', 'Vite owns preloading paths'] }, null, 2)) console.log(JSON.stringify({ result: 'PASS', assets: assets.length, newEvidence: records.length, target, wrapperBody: snippets.re.end - snippets.re.start }))