Files
ycode/scripts/audit-model-select-reference.mjs

73 lines
5.9 KiB
JavaScript

// Static assessment of already-exported REA artifacts. This script never changes production files.
import fs from 'node:fs/promises'
import { createHash } from 'node:crypto'
import { parse } from '@babel/parser'
import generateModule from '@babel/generator'
import postcss from 'postcss'
const generate = generateModule.default ?? generateModule
const output = '.tmp/model-select-audit'
await fs.mkdir(output, { recursive: true })
const runtime = JSON.parse(await fs.readFile('.tmp/rea-runtime-scripts.json', 'utf8'))
const panel = JSON.parse(await fs.readFile('.tmp/rea-assessment-model-source.json', 'utf8'))
const shared = runtime.items.find(item => item.file_path.endsWith('src-DPDj7_qD.js')).source.artifact
const settings = panel.normalized_result.files.find(file => file.path.endsWith('ModelsSettingsPanel-Dn7mp8BK.js'))
for (const [text, hash] of [[shared.text, '747e41d215375e1214c366213aea7e077d85421923029c61cbb6e9562be58de0'],
[settings.text, '739ab43ee521d8ef6e5b5b7731bb4e71b51454b2865f44a1228d7fcc2700149c']]) {
if (createHash('sha256').update(text).digest('hex') !== hash) throw Error('Pinned REA source changed')
}
function definitions(text, names, plugins = []) {
const found = []
function visit(node) {
if (!node || typeof node !== 'object') return
const name = node.type === 'FunctionDeclaration' ? node.id?.name : node.type === 'AssignmentExpression' ? node.left.name : undefined
if (names.includes(name)) found.push({ name, offset: node.start, length: node.end - node.start, text: text.slice(node.start, node.end), formatted: generate(node).code })
for (const value of Object.values(node)) if (Array.isArray(value)) value.forEach(visit); else if (value && typeof value === 'object') visit(value)
}
visit(parse(text, { sourceType: 'module', plugins }))
return found
}
const originals = definitions(shared.text, ['isOptionGroup', 'flattenOptions', 'defaultFilter', 'OptionLabel', 'OptionStringLabel', 'Select',
'Popover', 'PopoverLayer', 'usePopoverActivation', 'useExitTransition', 'buildTriggerAria', 'mergeRefs'])
const panelFunctions = definitions(settings.text, ['getProviderIcon', 'getLocalizedSearchText', 'formatProviderLabel'])
const own = definitions(await fs.readFile('src/renderer/src/components/ModelSettingsPanel.tsx', 'utf8'), ['Select'], ['typescript', 'jsx'])
for (const required of ['Select', 'Popover', 'PopoverLayer']) if (!originals.some(item => item.name === required)) throw Error(`Missing original ${required}`)
await fs.writeFile(`${output}/shared-select-readable.js`, originals.map(item => `// ${item.name} offset=${item.offset} length=${item.length}\n${item.formatted}`).join('\n\n'))
await fs.writeFile(`${output}/models-provider-readable.js`, panelFunctions.map(item => item.formatted).join('\n\n'))
await fs.writeFile(`${output}/own-select-readable.tsx`, own.map(item => item.formatted).join('\n\n'))
const css = []
for (const file of ['src-Bh3YZ35H.css', 'ModelsSettingsPanel-FfiX-Du7.css']) {
const text = file.startsWith('Models') ? panel.normalized_result.files.find(item => item.path.endsWith(file)).text : await fs.readFile(`.tmp/rea-css-recovered/${file}`, 'utf8')
const groups = { select: [], popover: [], input: [], provider: [] }
postcss.parse(text).walkRules(rule => {
const kind = /models-settings-panel__provider-(?:option|icon-image)/.test(rule.selector) ? 'provider'
: /\.wb-select/.test(rule.selector) ? 'select' : /\.wb-popover/.test(rule.selector) ? 'popover'
: /\.wb-input/.test(rule.selector) ? 'input' : undefined
if (kind) {
let copy = rule.clone()
for (let parent = rule.parent; parent?.type === 'atrule'; parent = parent.parent) { const wrapped = parent.clone({ nodes: [] }); wrapped.append(copy); copy = wrapped }
groups[kind].push(copy.toString())
}
})
css.push({ file, sha256: createHash('sha256').update(text).digest('hex'), rules: Object.fromEntries(Object.entries(groups).map(([key, value]) => [key, value.length])) })
await fs.writeFile(`${output}/${file}`, Object.values(groups).flat().join('\n'))
}
const states = []
for (const directory of ['rea-model-select-provider-static-20261016', 'rea-model-select-model-static-20261016']) {
const capture = JSON.parse(await fs.readFile(`.tmp/${directory}/layout.json`, 'utf8'))
const nodes = capture.layout.documents[0].nodes
const matches = selector => nodes.filter(node => node.attributes.class?.split(' ').includes(selector.slice(1)))
const selectors = ['.models-settings-panel__provider-select', '.models-settings-panel__model-select', '.wb-select-popover', '.wb-select__panel',
'.wb-select__search', '.wb-select__search-input', '.wb-select__list', '.wb-select__group-label', '.wb-select__option', '.models-settings-panel__editor-body']
states.push({ directory, evidenceId: capture.evidenceId, viewport: capture.viewport,
nodes: selectors.flatMap(selector => matches(selector).map((node, index) => ({ selector, index, nodeIndex: node.node_index,
bounds: node.bounds, styles: node.styles }))) })
}
const report = { runtimeEvidenceId: runtime.evidence_id, modelsPanelEvidenceId: panel.evidence_id,
sourceHashes: { shared: shared.sha256, panel: settings.sha256 },
originalDefinitions: originals.map(({ text, formatted, ...item }) => item), ownDefinitions: own.map(({ text, formatted, ...item }) => item), css, states,
scope: 'Read-only assessment of fixed REA source plus current own adapter. No production Select edits.',
limits: ['REA probe schema currently has no arbitrary text action. Search input/query/clear behavior is source-proven but query typing was not replayed on original.',
'Provider/model native screenshots cover default Tencent provider only; exact provider switches, filtered/no-result and viewport flip states remain to capture.'] }
await fs.writeFile(`${output}/report.json`, JSON.stringify(report, null, 2))
console.log(JSON.stringify({ originals: report.originalDefinitions, css, states: states.map(({ directory, evidenceId, viewport }) => ({ directory, evidenceId, viewport })) }))