68 lines
3.7 KiB
JavaScript
68 lines
3.7 KiB
JavaScript
// Derive readable reference slices from a previously exported REA record only.
|
|
// Never opens WorkBuddy's package or connects to its runtime; never executes its code.
|
|
import fs from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import crypto from 'node:crypto'
|
|
import { parse } from '@babel/parser'
|
|
import generatePackage from '@babel/generator'
|
|
|
|
const generate = generatePackage.default ?? generatePackage
|
|
const bundle = JSON.parse(await fs.readFile('.tmp/rea-runtime-scripts.json', 'utf8'))
|
|
const script = bundle.items.find((item) => item.file_path?.endsWith('src-DbE1_mgM.js'))
|
|
if (!script?.source?.included || !script.source.artifact?.text) throw new Error('Missing REA-captured source')
|
|
const source = script.source.artifact.text
|
|
const digest = crypto.createHash('sha256').update(source).digest('hex')
|
|
if (digest !== script.source.artifact.sha256) throw new Error('REA source digest mismatch')
|
|
const ast = parse(source, { sourceType: 'module' })
|
|
const output = path.resolve('.tmp/rea-chat-recovered')
|
|
await fs.mkdir(output, { recursive: true })
|
|
await fs.mkdir(path.join(output, 'definitions'), { recursive: true })
|
|
const ranges = [[624800, 660500], [716400, 798700], [804500, 825000], [979000, 995000]]
|
|
const declarations = []
|
|
const definitions = []
|
|
function visit(node) {
|
|
if (!node || typeof node !== 'object') return
|
|
if (node.type === 'AssignmentExpression' && node.operator === '=' && node.left.type === 'Identifier' &&
|
|
ranges.some(([start, end]) => node.start >= start && node.end <= end) &&
|
|
['ArrowFunctionExpression', 'FunctionExpression', 'ObjectExpression', 'ArrayExpression', 'NewExpression', 'RegExpLiteral'].includes(node.right.type)) {
|
|
const name = node.left.name
|
|
const filename = `definitions/${name}.js`
|
|
awaitWrites.push(fs.writeFile(path.join(output, filename), `const ${name} = ${generate(node.right, { compact: false }).code};\n`))
|
|
definitions.push({ name, start: node.start, end: node.end, filename })
|
|
}
|
|
for (const value of Object.values(node)) {
|
|
if (Array.isArray(value)) value.forEach(visit)
|
|
else if (value && typeof value === 'object' && value.type) visit(value)
|
|
}
|
|
}
|
|
const awaitWrites = []
|
|
visit(ast.program)
|
|
await Promise.all(awaitWrites)
|
|
for (const statement of ast.program.body) {
|
|
const nodes = statement.type === 'VariableDeclaration' ? statement.declarations : [statement]
|
|
for (const node of nodes) {
|
|
if (!ranges.some(([start, end]) => node.start < end && node.end > start)) continue
|
|
// Skip bundled library wrappers crossing a whole region; report them as boundaries.
|
|
if (node.end - node.start > 60000) {
|
|
declarations.push({ name: node.id?.name, start: node.start, end: node.end, skipped: 'large-library-wrapper' })
|
|
continue
|
|
}
|
|
const name = node.id?.name ?? `${node.type}-${node.start}`
|
|
const declaration = statement.type === 'VariableDeclaration'
|
|
? { ...statement, declarations: [node] }
|
|
: node
|
|
const text = generate(declaration, { comments: true, compact: false }).code
|
|
const filename = `${node.start}-${name}.js`
|
|
await fs.writeFile(path.join(output, filename), text + '\n')
|
|
declarations.push({ name, start: node.start, end: node.end, filename })
|
|
}
|
|
}
|
|
const manifest = {
|
|
evidenceId: bundle.evidence_id, sourcePath: script.file_path, sourceSha256: digest,
|
|
ranges: ranges.map(([start, end]) => ({ start, end, units: 'UTF-16', endExclusive: true })),
|
|
method: 'Babel parse/generate, split top-level declarations; reference only, not executed',
|
|
declarations, definitions
|
|
}
|
|
await fs.writeFile(path.join(output, 'manifest.json'), JSON.stringify(manifest, null, 2))
|
|
console.log(JSON.stringify({ evidenceId: manifest.evidenceId, sourceSha256: digest, declarations: declarations.length, definitions: definitions.length, manifest: path.join(output, 'manifest.json') }))
|