Files
ycode/scripts/rea/recover-composer-model-selector.mjs

662 lines
49 KiB
JavaScript

/**
* Recovery of the WorkBuddy 5.8.2 conversation-pane model selector.
*
* Every recovered byte comes from the fixed REA export retained in .tmp/rea-runtime-scripts.json and
* .tmp/rea-css-recovered/. The original install directory, CDP and runtime evaluation are never touched.
* Source identities are pinned by SHA-256 and re-verified on every run; `--check` re-derives all
* outputs and fails on any drift.
*/
import fs from 'node:fs'
import crypto from 'node:crypto'
import {parse} from '@babel/parser'
import traverseModule from '@babel/traverse'
import postcss from 'postcss'
const traverse=traverseModule.default??traverseModule
const sha=value=>crypto.createHash('sha256').update(value).digest('hex')
const archive=JSON.parse(fs.readFileSync('.tmp/rea-runtime-scripts.json','utf8'))
const cssManifest=JSON.parse(fs.readFileSync('.tmp/rea-css-recovered/manifest.json','utf8'))
const FOLDER='src/renderer/src/workbuddy/composer/model-selector/'
const SCOPE='.yc-source-model-selector'
const manifest={
version:'5.8.2',
rootSha256:'035254bc76310ea46317433e4840602094543ef323d2d5c5aff7c131729de918',
evidence:[archive.evidence_id,cssManifest.sourceEvidenceId],
sources:[],bodies:[],crossFileBindings:[],hostBindings:[],adaptations:[],observations:[],
tokenSelectorMappings:[],outputs:[],
}
function index(name,pin){
const item=archive.items.find(entry=>entry.file_path.endsWith(name))
const artifact=item?.source.artifact
if(!artifact||artifact.sha256!==pin||sha(artifact.text)!==pin)throw Error('REA source identity mismatch '+name)
manifest.sources.push({file:name,sha256:pin,bytes:Buffer.byteLength(artifact.text)})
return{text:artifact.text,ast:parse(artifact.text,{sourceType:'module'}),file:name}
}
const core=index('src-DbE1_mgM.js','6c6ce63c93854783270e855572797d75e536e3b8d4548410e31fe9d147e1feb4')
const primitives=index('src-DPDj7_qD.js','747e41d215375e1214c366213aea7e077d85421923029c61cbb6e9562be58de0')
// The corpus imports floating-ui primitives from its own bundled floating-ui/react chunk. The export
// table of that chunk is stable in this export and maps the short local names to their real symbols, so
// the same public names are taken from the pinned host package (the AddMenu precedent).
// Only the entries the recovered bodies actually reference are listed; each is verified against the
// retained export table below, so a chunk change fails the run instead of silently mis-binding.
const FLOATING_EXPORT_TABLE=new Map(Object.entries({b:'isLastTraversableNode',c:'size',h:'getParentNode',n:'flip',o:'offset',s:'shift',t:'arrow',u:'autoUpdate',v:'isElement'}))
const FLOATING_CHUNK_PIN=Object.freeze({file:'floating-ui.react-dom-BDD8Fyfd.js',sha256:'94036e3ed41ddb907b010cedbdb628a57e26e0585e2a9be45c9cbecfdd6ec978',bytes:27055})
// Confirm the export table against the retained chunk, and bind the host import list from it.
const floatingChunk=archive.items.find(entry=>entry.file_path.endsWith(FLOATING_CHUNK_PIN.file))?.source.artifact
if(!floatingChunk||floatingChunk.sha256!==FLOATING_CHUNK_PIN.sha256||sha(floatingChunk.text)!==FLOATING_CHUNK_PIN.sha256)throw Error('floating-ui chunk identity mismatch')
const floatingTableText=floatingChunk.text.slice(floatingChunk.text.lastIndexOf('export{'))
for(const[local,exported]of FLOATING_EXPORT_TABLE){
if(!new RegExp(`\\b${exported} as ${local.replace('$','\\$')}\\b`).test(floatingTableText))throw Error('floating-ui export table changed for '+local)
}
manifest.observations.push(`floating-ui primitives are aliased in the corpus through ${FLOATING_CHUNK_PIN.file} (${FLOATING_CHUNK_PIN.sha256.slice(0,12)}), whose export table maps each local name to the public symbol recorded in FLOATING_EXPORT_TABLE.`)
// --------------------------------------------------------------------------- binding index
// The cr bundle declares `var a,b,c,M=n(()=>{...})`, where `n` is a lazy module initialiser. Because
// that body must never run, values it computes are lifted into plain module-level assignments.
function buildIndex(source){
const index={declarator:new Map(),fn:new Map(),assignment:new Map(),imported:new Map(),lifted:new Map(),reactAlias:new Set(),jsxAlias:new Set()}
traverse(source.ast,{
ImportDeclaration(path){
for(const specifier of path.node.specifiers){
const local=specifier.local.name
if(index.imported.has(local))continue
index.imported.set(local,{name:specifier.type==='ImportSpecifier'?specifier.imported.name:'default',from:path.node.source.value})
}
},
// Only module-scope bindings are indexed. The bundle reuses single-letter names for locals inside
// hundreds of functions, so a whole-file scan would resolve a module-level reference to an unrelated
// local that happens to share the name.
VariableDeclarator(path){
if(path.node.id.type!=='Identifier')return
if(path.scope.block.type!=='Program')return
if(!index.declarator.has(path.node.id.name))index.declarator.set(path.node.id.name,path)
},
FunctionDeclaration(path){
if(!path.node.id)return
// A FunctionDeclaration's own path scope is the function itself, so the parent is what matters.
if(!path.parentPath.isProgram())return
if(!index.fn.has(path.node.id.name))index.fn.set(path.node.id.name,path)
},
AssignmentExpression(path){
if(path.node.left.type!=='Identifier')return
// Values are assigned inside module initialiser arrow functions. The arrow may be nested, so walk up
// to the enclosing `n(() => {...})` call rather than assuming the function is its direct argument.
let enclosing=path.getFunctionParent(),inInitialiser=false
for(let current=enclosing;current;current=current.getFunctionParent()){
if(isModuleInit(current.parentPath?.node)){inInitialiser=true;break}
}
if(!inInitialiser)return
if(!index.assignment.has(path.node.left.name))index.assignment.set(path.node.left.name,path)
},
CallExpression(path){
const callee=path.node.callee
if(callee.type!=='Identifier')return
const initialiser=path.node.arguments[0]
if(!initialiser||(initialiser.type!=='ArrowFunctionExpression'&&initialiser.type!=='FunctionExpression'))return
// Only the top-level `X=n(()=>{...})` module initialisers are lifted.
if(path.scope.block.type!=='Program')return
const isJsxInitialiser=Boolean(index.imported.get(callee.name)?.from.includes('jsx-runtime'))
const statements=Array.isArray(initialiser.body.body)?initialiser.body.body:[]
for(const statement of statements){
if(statement.type!=='ExpressionStatement')continue
const pending=[statement.expression]
while(pending.length){
const current=pending.pop()
if(!current)continue
if(current.type==='SequenceExpression'){pending.push(...current.expressions);continue}
if(current.type!=='AssignmentExpression'||current.left.type!=='Identifier')continue
registerLifted(current,index,isJsxInitialiser)
}
}
},
})
return index
}
function registerLifted(assignment,index,isJsxInitialiser){
const name=assignment.left.name,right=assignment.right
if(right.type==='CallExpression'&&right.callee.type==='Identifier'){
const helper=index.imported.get(right.callee.name)
if(isJsxInitialiser||helper?.from.includes('jsx-runtime')){index.jsxAlias.add(name);return}
// `X=a(p())` is the corpus React namespace singleton: `a` is a transparent cr helper and `p` is the
// React chunk namespace.
const inner=right.arguments[0]
if(inner?.type==='CallExpression'&&inner.callee.type==='Identifier'&&index.imported.get(inner.callee.name)?.from.includes('react-z__')){index.reactAlias.add(name);return}
}
if(!index.lifted.has(name))index.lifted.set(name,assignment)
}
const coreIndex=buildIndex(core),primitiveIndex=buildIndex(primitives)
// --------------------------------------------------------------------------- recovery plan
// Grouped in dependency order. Every name resolves to exactly one verbatim corpus definition; the run
// fails loudly when a name is absent so a source change can never yield a silently partial module.
const SECTIONS=[
{id:'cr-classname',target:core,names:['r$1','clsx']},
{id:'cr-config',target:core,names:['getPrefixCls']},
{id:'cr-floating-layer',target:core,names:['getFloatingLayerState','getGroupStack','nextZIndex','useFloatingLayer','li','ui','di','fi','gi','_i']},
// Press tracking is a module-level `document` side effect in the corpus: importing it would install the
// listener before any host could opt out. It is a host seam and the reported press state drives the
// recovered tooltip logic unchanged.
// ModelSelector hides the trigger tooltip after a press, so the corpus tooltip ships with it. Its
// timing constants and the truncation probes are recovered; the pointer-press tracker is a host seam
// because the corpus installs it with a module-level document listener at import time.
{id:'cr-tooltip',target:core,names:['TooltipLayer','Ci','isHoverSuppressedByPress','suppressHoverUntilPointerMove','yi','bi','xi','wi','isEmptyContent','resolveTooltipThemeMode','isVisibleFocus','normalizeVisibleText','isElementTruncated','hasTruncationStyle','isSubtreeTruncated','collectVisibleText','hasVisibleTriggerText','shouldGateOnTruncation','Tooltip$1']},
{id:'cr-popover',target:core,names:['Ri','zi','Oi','floatingAutoUpdateWithAnimationFrame','PopoverLayer','resolvePopoverWhileElementsMounted','getNearestStackingZIndex','Ui','qi','usePopoverContext','Popover','PopoverTrigger','PopoverContent']},
{id:'cr-menu',target:core,names:['Menu','MenuItem','$i','SubMenu','da','fa','pa','MenuDivider','MenuGroup']},
{id:'cr-icons',target:core,names:['CheckIcon$1','ChevronRightIcon','ErrorCircleIcon','EnterpriseIcon','MaxIcon','TierFlagshipIcon','TierMemberIcon','CongestedIcon']},
{id:'cr-scroll-area',target:core,names:['useOverlayScrollbar','gl','xl']},
{id:'wb-icon',target:primitives,names:['yn','resolveSize','bn']},
{id:'wb-inline-svg',target:primitives,names:['isPureBlack','recolorBlackToCurrentColor','sanitizeSvg','isSameOriginQueryAllowed','normalizePathForPrefixCheck','warnRejectedSameOrigin','isFetchableSvgUrl','subscribeRemoteSvg','broadcastForUrl','ensureOnlineListener','un','fetchAndParse','fetchWithAuthFallback','scheduleRevalidate','ensureCached','useRemoteSvg','tn','nn','rn','an','on','sn','cn','ln','RemoteSvgFetchError','stripSizeFromStyle','normalizeInlineSvg','pn','mn','hn']},
{id:'wb-icon-factory',target:primitives,names:['createIcon','_n','vn','Ks','qs','Js']},
{id:'wb-chevron-down-icon',target:primitives,names:['Ys']},
{id:'wb-ardot-icon',target:primitives,names:['Zr','Qr','$r','ei']},
// The Grok/xai model icon: a themable image asset defined in the primitives chunk.
{id:'wb-grok-icon',target:primitives,names:['Zd','$d']},
{id:'wb-toggle-switch',target:primitives,names:['hH','useSwitchMotion','_H','vH','yH']},
{id:'provider-icon',target:core,names:['isInlineSvgPayload','isImageIconPayload','isUrl','$F','XF','YF','getExtension','resolveFileTypeIcon','resolveFileIconFromMetadata','resolveBuiltinIcon','renderProviderIcon','VV','FileArchiveIcon','FileArdotIcon','FileAudioIcon','FileCodeIcon','FileDiagramIcon','FileDocIcon','FileFolderIcon','FileHtmlIcon','FileImageIcon','FileMarkdownIcon','FilePdfIcon','FileSheetIcon','FileSlideIcon','FileTxtIcon','FileUnknownIcon','FileVideoIcon','CommandIcon','SkillsIcon','LexiangIcon','TencentDocsIcon','WecomIcon','AgentIcon','ApplicationIcon','ChatBubbleIcon','DocsIcon','GitIcon','ProblemsIcon','RulesIcon','TerminalIcon$1','WebIcon']},
// `De` is the corpus's own selection state (the cr flag used by the model-selector popover), which is
// why it is recovered rather than injected.
{id:'model-icons',target:core,names:['OpenAIIcon','AnthropicIcon','DeepSeekIcon','GeminiIcon','KimiIcon','HunyuanIcon','AutoModeIcon','GLMIcon','MinimaxIcon','DefaultModelIcon','FastModelIcon','BalancedModelIcon','PrimaryModelIcon','DeepModelIcon','nW','rW','getModelIconByName','resolveModelIcon']},
{id:'model-options',target:core,names:['collectModelOptions','resolveSelectedModelId','resolveSelectedModelLabel','buildGroupedModels','getDefaultIsThinking','isReasoningConfigurable','formatCredits','formatContextWindow','getSupportedContextWindows','createModelSelection']},
{id:'model-badge',target:core,names:['OverflowTitleSpan','resolvePromotionIconUrl','mW','hW','gW','ModelBadge','ToggleSwitch']},
{id:'model-sub-panels',target:core,names:['ReasoningEffortPanel','ContextWindowPanel','xW']},
{id:'model-sub-menu',target:core,names:['ModelSubMenu','TW']},
{id:'model-tier-badge',target:core,names:['ModelTierBadge','OW','kW']},
{id:'model-item',target:core,names:['ModelItem','NW']},
{id:'model-group-item',target:core,names:['ModelGroupMenuItem']},
{id:'model-popover',target:core,names:['ModelSelectPopover']},
{id:'model-selector',target:core,names:['ModelSelectorImpl']},
]
// Host seams: identifiers that are neither corpus definitions nor recovered above. Each is declared in
// the generated preamble. Nothing else may be missing.
const HOST_FLOATING=['offset','flip','shift','size','arrow','autoUpdate','useFloating','useDismiss','useHover','useInteractions','useTransitionStyles']
const HOST_FLOATING_IMPORT=[...HOST_FLOATING,'FloatingPortal as FloatingPortalPrimitive'].join(', ')
const EXPORTS=['ModelSelectorImpl','ModelSelectPopover','ModelSubMenu','ModelItem','ModelGroupMenuItem','ModelTierBadge','Menu','MenuItem','MenuDivider','MenuGroup','Popover','PopoverTrigger','PopoverContent','Tooltip$1 as Tooltip','ToggleSwitch','ReasoningEffortPanel','ContextWindowPanel','resolveModelIcon','getModelIconByName','OverflowTitleSpan','ModelBadge','getDefaultIsThinking','isReasoningConfigurable','createModelSelection','collectModelOptions','resolveSelectedModelId','resolveSelectedModelLabel','formatCredits','formatContextWindow','getSupportedContextWindows','useOverlayScrollbar'].join(', ')
const GLOBALS=new Set(('Array Boolean Date Error JSON Map Math Number Object Promise RegExp Set String URL URLSearchParams '+
'WeakMap console document globalThis window process queueMicrotask requestAnimationFrame cancelAnimationFrame setTimeout clearTimeout '+
'getComputedStyle ResizeObserver Node HTMLElement DOMParser XMLSerializer fetch navigator performance isNaN parseInt '+
'parseFloat undefined arguments Uint8Array Symbol encodeURIComponent decodeURIComponent atob btoa CSS structuredClone '+
'Element MutationObserver IntersectionObserver isFinite RangeError TypeError').split(' '))
function isModuleInit(node){return node?.type==='CallExpression'&&node.callee.type==='Identifier'&&node.arguments.length===1&&(node.arguments[0].type==='ArrowFunctionExpression'||node.arguments[0].type==='FunctionExpression')}
const resolved=new Map(),missing=[]
function resolve(target,name){
const table=target===core?coreIndex:primitiveIndex
// Corpus React/JSX singletons are declared once in the preamble and must not also be emitted.
if(table.reactAlias.has(name))return{kind:'react-singleton'}
if(table.jsxAlias.has(name))return{kind:'jsx-singleton'}
const declarator=table.declarator.get(name)
if(declarator?.node.init&&!isModuleInit(declarator.node.init))return{kind:'declaration',start:declarator.node.start,end:declarator.node.end,text:target.text.slice(declarator.node.start,declarator.node.end)}
const fn=table.fn.get(name)
if(fn)return{kind:'function',start:fn.node.start,end:fn.node.end,text:target.text.slice(fn.node.start,fn.node.end)}
// `var X,Y,Z` plus `X=<expr>` inside a module initialiser keeps `var`: several of these bindings are
// reassigned by the recovered functions themselves (for example the pointer-press timestamp tracker).
const lifted=table.lifted.get(name)
if(lifted)return{kind:'lifted',start:lifted.start,end:lifted.end,text:`var ${name}=${target.text.slice(lifted.right.start,lifted.right.end)};`}
const assignment=table.assignment.get(name)
if(assignment)return{kind:'assignment',start:assignment.node.start,end:assignment.node.end,text:`var ${name}=${target.text.slice(assignment.node.right.start,assignment.node.right.end)};`}
const imported=table.imported.get(name)
if(imported)return{kind:'import',imported}
return null
}
for(const section of SECTIONS){
section.rows=[]
for(const name of section.names){
const entry=resolve(section.target,name)
if(!entry){missing.push(section.id+':'+name);continue}
if(entry.kind==='react-singleton'||entry.kind==='jsx-singleton')continue
section.rows.push({name,file:section.target.file,...entry})
resolved.set(name,entry)
}
}
if(missing.length)throw Error('Unresolved corpus names: '+missing.join(', '))
manifest.observations.push('src-DbE1_mgM.js is the conversation-pane chunk and src-DPDj7_qD.js the WorkBuddy primitive library. Both live in the fixed REA export and are SHA-256 verified on every run.')
// --------------------------------------------------------------------------- emit bodies
// Bodies are emitted byte-for-byte. The corpus idiom `(0,X.jsx)(...)` is the minifier's this-free
// indirect call and is already valid JavaScript, so no textual rewrite is applied to recovered code.
// --------------------------------------------------------------------------- cross-file wiring
// cr reaches primitives-chunk symbols through its minimised re-export table: `Te` is the WB switch, `Pe`
// the ChevronDown icon, `je` the Ardot file icon and `pe` the SVG sanitiser. Each target is recovered
// verbatim in this same module from src-DPDj7_qD.js and bound under the alias the call sites use.
const CROSS=[
{alias:'Te',target:'yH',symbol:'src-DPDj7_qD.js yH (wb-switch)',usedBy:'ToggleSwitch'},
{alias:'Pe',target:'Ys',symbol:'src-DPDj7_qD.js Ys (ChevronDownIcon)',usedBy:'ModelSelectorImpl trigger arrow'},
{alias:'je',target:'ei',symbol:'src-DPDj7_qD.js ei (ArdotFileIcon)',usedBy:'FileArdotIcon'},
{alias:'pe',target:'sanitizeSvg',symbol:'src-DPDj7_qD.js sanitizeSvg',usedBy:'renderProviderIcon inline-svg sanitisation'},
{alias:'De',target:'$d',symbol:'src-DPDj7_qD.js $d (GrokIcon)',usedBy:'model icon registry nW grok/xai entries'},
]
for(const binding of CROSS)if(!resolved.has(binding.target))throw Error('Cross-file target missing: '+binding.target)
// Corpus floating-ui locals. The public symbol for each local comes from the retained export table of
// the bundled floating-ui/react chunk, so these bind to the pinned host package.
const FLOATING_LOCAL_BINDINGS=[['D','offset'],['E','flip'],['O','shift'],['b','size'],['k','arrow'],['A','autoUpdate']]
manifest.observations.push('Corpus floating-ui locals D/E/O/b/k/A are bound to the public offset/flip/shift/size/arrow/autoUpdate symbols of the pinned host package, resolved through the retained export table instead of guessed.')
// The bindings are emitted after the primitives sections and before the sections whose top-level values
// read them (the model icon registry reads `De` while the module is still evaluating), otherwise the
// recovered initialisers would hit a temporal dead zone.
const CROSS_BLOCK=[
'',
'// cr re-export table and corpus floating-ui locals. Emitted after their targets and before the',
'// sections whose top-level values consume them.',
...CROSS.map(binding=>`// \`${binding.alias}\` -> ${binding.symbol}\nconst ${binding.alias}=${binding.target}`),
...FLOATING_LOCAL_BINDINGS.map(([local,publicName])=>`const ${local}=${publicName}`),
'',
].join('\n')
manifest.crossFileBindings=[...CROSS.map(binding=>({alias:binding.alias,target:binding.target,symbol:binding.symbol,usedBy:binding.usedBy,from:'src-DPDj7_qD.js',recovered:true})),...FLOATING_LOCAL_BINDINGS.map(([local,publicName])=>({alias:local,target:publicName,from:'@floating-ui/react',recovered:false,note:'Corpus floating-ui local resolved through the retained export table of the bundled floating-ui/react chunk.'}))]
let recoveredJs=''
for(const section of SECTIONS){
if(section.id==='provider-icon')recoveredJs+=CROSS_BLOCK
recoveredJs+=`\n// ---- ${section.id} — ${section.file}\n`
for(const row of section.rows){
recoveredJs+=row.text+'\n'
manifest.bodies.push({section:section.id,file:row.file,name:row.name,kind:row.kind,utf16:[row.start,row.end],sha256:sha(row.text)})
}
}
if(!recoveredJs.includes('const De='))throw Error('Cross-file block was not emitted')
// --------------------------------------------------------------------------- zh-CN labels
const LABEL_OFFSET=172945
const labels=(()=>{
const start=172942
const end=core.text.indexOf('}}))',start)
if(start<0||end<0||Math.abs(start-LABEL_OFFSET)>16)throw Error('zh-CN locale object boundary changed')
const block=core.text.slice(start,end),found={}
for(const match of block.matchAll(/"chatInput\.modelSelector\.([\w.]+)":`((?:\\u[0-9A-Fa-f]{4}|[^`])*)`/g)){
found[match[1]]=match[2].replace(/\\u([0-9A-Fa-f]{4})/g,(raw,code)=>String.fromCharCode(parseInt(code,16)))
}
const keys=Object.keys(found)
if(keys.length!==26)throw Error('Model selector label count changed: '+keys.length)
for(const required of['maxMode','maxModeTooltip','thinkingMode','thinkingEffort','thinking.on','thinking.off','enterprise','externalWarning','credits','creditsUnit','busy.label','busy.idle','busy.busy','busy.congested','busy.unavailable','busy.unavailableTip','contextWindow','configIssue.title','configIssue.reasonLine1','configIssue.reasonLine2','configIssue.fixAction','effort.low','effort.medium','effort.high','effort.xhigh','effort.max'])if(!Object.prototype.hasOwnProperty.call(found,required))throw Error('Missing source label '+required)
return Object.fromEntries(keys.map(key=>['chatInput.modelSelector.'+key,found[key]]))
})()
manifest.observations.push('The zh-CN locale literal at UTF-16 offset '+LABEL_OFFSET+' of src-DbE1_mgM.js holds all 26 chatInput.modelSelector.* strings used here. Values are stored as \\uXXXX escapes and decoded verbatim. The decoded set contains no traditional-only characters (thinkingEffort=\u601d\u8003\u5f3a\u5ea6), so the recovered values are byte-faithful to the zh-CN table')
// --------------------------------------------------------------------------- alias declarations
// The bundle is a flattened set of modules that reuse minified alias names, so a name can be bound twice
// in the corpus. Each alias is classified by how the recovered call sites actually use it. `Fragment` is
// deliberately not a discriminator: both namespaces expose it.
const jsxCallers=new Set()
for(const match of recoveredJs.matchAll(/(?<![\w$.])([A-Za-z$_][\w$]*)\.(?:jsx|jsxs)\b/g))jsxCallers.add(match[1])
const reactCallers=new Set()
for(const match of recoveredJs.matchAll(/(?<![\w$.])([A-Za-z$_][\w$]*)\.(?:useState|useRef|useCallback|useEffect|useLayoutEffect|useMemo|useId|useContext|useSyncExternalStore|createContext|forwardRef|memo|cloneElement|createElement|isValidElement|Children)\b/g))reactCallers.add(match[1])
const ambiguous=[...jsxCallers].filter(name=>reactCallers.has(name))
if(ambiguous.length)throw Error('Alias used as both React and JSX namespace: '+ambiguous.join(', '))
const corpusReact=new Set([...coreIndex.reactAlias,...primitiveIndex.reactAlias])
const corpusJsx=new Set([...coreIndex.jsxAlias,...primitiveIndex.jsxAlias])
const undefinedAliases=[...jsxCallers,...reactCallers].filter(name=>!corpusJsx.has(name)&&!corpusReact.has(name))
if(undefinedAliases.length)throw Error('Alias binding not present in the corpus: '+undefinedAliases.join(', '))
const aliasDeclarations=[
...[...reactCallers].sort().map(name=>`const ${name}=React`),
...[...jsxCallers].sort().map(name=>`const ${name}=JSX`),
]
manifest.observations.push('Minified alias names are reused across the flattened modules of the retained bundle. Every alias declared in the generated module is classified from its recovered call sites and verified to be a corpus singleton; the React and JSX alias sets are disjoint.')
// --------------------------------------------------------------------------- module source
const runtimeSource=`/* Host seam for the recovered model selector.
The corpus reads draft state, locale and diagnostics from neighbouring input-box and i18n modules that
are outside this recovery, and resolves provider icons through a host callback. Those edges are injected
here instead of being simulated. */
const defaultRuntime={
mode:'light',
useInputBoxStore(){throw new Error('ModelSelectorRuntime.useInputBoxStore is not configured')},
useInputBoxSelector(selector,isEqual){const state={draft:{selections:{model:null}}};return selector(state,isEqual)},
useRenderDiag(){},
get prefixCls(){return 'cr'},
}
let activeRuntime=defaultRuntime
export function configureModelSelectorRuntime(next){
activeRuntime={...defaultRuntime,...next}
return activeRuntime
}
export function readModelSelectorRuntime(){return activeRuntime}
const RuntimeContext=React.createContext(null)
export function ModelSelectorRuntimeProvider({runtime,children}){
const value=React.useMemo(()=>({...defaultRuntime,...runtime}),[runtime])
return JSX.jsx(RuntimeContext.Provider,{value,children})
}
export function useModelSelectorRuntime(){
const injected=React.useContext(RuntimeContext)
return injected??activeRuntime
}
export const modelSelectorLabels=${JSON.stringify(labels)}
const ModelSelectorConfigContext=React.createContext({prefixCls:'cr',mode:'light',locale:'zh-CN',t:key=>modelSelectorLabels[key]??key})
export const useModelSelectorConfig=()=>React.useContext(ModelSelectorConfigContext)
const usePrefixCls=()=>{const{prefixCls}=useModelSelectorConfig();return React.useMemo(()=>getPrefixCls(prefixCls),[prefixCls])}
const useI18n=()=>{const{t,locale}=useModelSelectorConfig();return{t,locale}}
const useCrConfig=()=>useModelSelectorConfig()
const useInputBoxStore=()=>useModelSelectorRuntime().useInputBoxStore()
const useInputBoxSelector=(selector,isEqual)=>useModelSelectorRuntime().useInputBoxSelector(selector,isEqual)
const useRenderDiag=(name,meta)=>{useModelSelectorRuntime().useRenderDiag?.(name,meta)}
const yt=ModelSelectorConfigContext
const FloatingPortal=({children,root})=>{
const runtime=useModelSelectorRuntime()
return JSX.jsx(FloatingPortalPrimitive,{root,children:JSX.jsx('span',{className:'yc-source-model-selector','data-cr-theme':runtime.mode,'data-theme':runtime.mode,children})})
}
const createDOMPurifyInstance=()=>{
if(typeof createDOMPurify!=='function')return null
if(typeof window==='undefined')return createDOMPurify
return createDOMPurify(window)
}
// The corpus bundles purify.es and binds it to \`fe\`; sanitizeSvg calls fe.sanitize with the exact
// configuration below. The host dependency supplies the same instance under its default export.
const fe=createDOMPurifyInstance()??{sanitize:value=>value}
`
manifest.adaptations.push(
'Host seam: useInputBoxStore / useInputBoxSelector (draft selection state), useRenderDiag (render instrumentation sink), usePrefixCls / useI18n / useCrConfig (cr config context) and the FloatingPortal theme wrapper are injected instead of the neighbouring input-box, i18n and tokens modules, which are outside this recovery. The recovered call sites, their argument shapes and all markup stay unchanged.',
'The cr config context is reduced to prefixCls/mode/locale/t. The corpus seeds it with createT(locale,tables) over the zh-CN/zh-TW/en-US/pt-BR/id-ID message tables (about 250 KB) plus a token-to-CSS-variable projector; both values are dead weight for this component and nothing is invented.',
'FloatingUI primitives use the pinned host @floating-ui/react package, matching the recovered AddMenu precedent. The corpus inlines its own floating-ui/react build and the bundled version is not recorded in the fixed export, so the host range is used as-is.',
'DOMPurify comes from the pinned host dependency. The corpus bundles purify.es with DOMPurify.version="3.4.11"; sanitizeSvg keeps its exact configuration (USE_PROFILES svg+svgFilters, FORBID_TAGS script/foreignObject, FORBID_ATTR srcdoc/formaction). The host package is a newer patch release.',
'ModelSelectorImpl is emitted verbatim. It reads `n.draft.selections.model` through useInputBoxSelector and commits through useInputBoxStore().api.setModel, both of which the host must provide; trigger markup, ARIA, class names, placements, delays and submenu state are unmodified.',
)
// The recovered text is concatenated, never interpolated inside a template literal: corpus code is full
// of `${...}` sequences that must stay literal.
const moduleSource=[
'import * as React from \'react\'',
'import * as JSX from \'react/jsx-runtime\'',
`import {${HOST_FLOATING_IMPORT}} from '@floating-ui/react'`,
'import createDOMPurify from \'dompurify\'',
...aliasDeclarations,
runtimeSource,
recoveredJs,
`export {${EXPORTS}}`,
].join('\n')
// The preamble may never shadow a recovered body: verbatim corpus code always wins.
const preambleNames=['usePrefixCls','useI18n','useCrConfig','useInputBoxStore','useInputBoxSelector','useRenderDiag','yt','FloatingPortal','ModelSelectorConfigContext','useModelSelectorConfig','modelSelectorLabels','RuntimeContext','defaultRuntime','activeRuntime','createDOMPurifyInstance']
const colliding=preambleNames.filter(name=>resolved.has(name))
if(colliding.length)throw Error('Host seam collides with recovered body: '+colliding.join(', '))
// --------------------------------------------------------------------------- unbound-identifier audit
// The emitted module is re-parsed and every referenced identifier is resolved against module-scope
// bindings, imports and known globals. Anything else is a recovery gap and fails the run.
function auditModule(source){
const file=parse(source,{sourceType:'module'})
const declared=new Set(),importedNames=new Set(),unboundCandidates=new Set(),sites=new Map()
let references=0
for(const statement of file.program.body){
if(statement.type==='ImportDeclaration')for(const specifier of statement.specifiers)importedNames.add(specifier.local.name)
}
const lineOf=index=>source.slice(0,index).split('\n').length
traverse(file,{
Program(path){
for(const name of Object.keys(path.scope.bindings))declared.add(name)
path.traverse({
ReferencedIdentifier(identifierPath){
const name=identifierPath.node.name
references+=1
if(identifierPath.scope.hasBinding(name))return
unboundCandidates.add(name)
if(!sites.has(name))sites.set(name,`line ${lineOf(identifierPath.node.start)}: ${source.slice(Math.max(0,identifierPath.node.start-70),identifierPath.node.start+40).replace(/\n/g,' ')}`)
},
JSXIdentifier(identifierPath){
if(identifierPath.parent.type!=='JSXOpeningElement'&&identifierPath.parent.type!=='JSXClosingElement')return
const name=identifierPath.node.name
if(/^[a-z]/.test(name))return
references+=1
if(identifierPath.scope.hasBinding(name))return
unboundCandidates.add(name)
if(!sites.has(name))sites.set(name,`line ${lineOf(identifierPath.node.start)}: ${source.slice(Math.max(0,identifierPath.node.start-70),identifierPath.node.start+40).replace(/\n/g,' ')}`)
},
})
},
})
// `unboundCandidates` are references with no lexical binding. Each must be a declared import, a known
// global, or one of the pinned floating-ui primitives; anything left over is a recovery gap.
const hostProvided=[...unboundCandidates].filter(name=>!GLOBALS.has(name)&&!HOST_FLOATING.includes(name)&&!importedNames.has(name))
return{unbound:hostProvided.sort(),sites,declared:declared.size,references,unboundCandidates:unboundCandidates.size,hostBindings:importedNames.size}
}
const audit=auditModule(moduleSource)
if(audit.unbound.length){
throw Error('Unbound identifiers in emitted module:\n'+audit.unbound.map(name=>' '+name+' -> '+(audit.sites.get(name)??'(preamble)')).join('\n'))
}
manifest.observations.push('Unbound-identifier audit over the emitted module: '+audit.references+' identifier references, '+audit.declared+' module-scope bindings, '+audit.hostBindings+' imported host bindings, '+audit.unboundCandidates+' references resolved lexically, 0 unresolved.')
manifest.adaptations.push('Lifted module values keep `var` rather than `const`: several are reassigned by the recovered functions (the pointer-press timestamp tracker is the clearest case), so narrowing them would change behaviour. The corpus declares them with `var` for the same reason.')
// --------------------------------------------------------------------------- css
function scopedTokenSelectors(rule){
const mapped=[]
for(const selector of rule.selectors){
if(selector===':root'){mapped.push(SCOPE);continue}
if(selector.includes('.cr-theme')){mapped.push(selector.replace(/\.cr-theme\b/g,SCOPE));continue}
// Every original theme/platform condition is preserved; dark selectors never become unconditional.
mapped.push(selector+' '+SCOPE)
if(/(?:data-theme=dark|\.cb-dark\b|IDE\\ Night|vscode-dark|\.dark\b)/.test(selector))mapped.push(SCOPE+'[data-cr-theme=dark]')
if(/IDE\\ Light/.test(selector))mapped.push(SCOPE+'[data-cr-theme=light]')
}
if(rule.selectors.includes('.light .cr-theme'))mapped.push('[data-theme=light] '+SCOPE+':not([data-cr-theme=dark])')
return [...new Set(mapped)].join(',')
}
function wrapAtRules(node,parent){
let result=node
for(let current=parent;current?.type==='atrule';current=current.parent){const wrapper=current.clone({nodes:[]});wrapper.append(result);result=wrapper}
return result.toString()
}
let css='/* Fixed REA cr model selector and its Menu/SubMenu/Popover, Tooltip, ScrollArea, WB switch and icon CSS; scoped selectors. */\n'
const cssSources=[
['src-CBaV_A3S.css','2090ed21045c8f8b0fc388d76424c8751bf18fcd065cbbd5d0ef485163a2e36c','tokens'],
['src-CyXHA0IC.css','a5e26b537bb50323aefbf25abddad52e288dd3868598be8d255d70886fe77cfe','components'],
['src-Bh3YZ35H.css','88dbdc1cd3f59d0e8b75824512a465a2be714bc7af481d790fe3a9484f85e01a','wb-switch'],
['desktop-sdk-setup-Bh0rg_xP.css','b2ee58c0caf560eeddc4eb8c91d86cabddbec634b8d37ed5d6b85d0644c0e142','runtime override'],
]
const COMPONENT_PATTERN=/\.cr-(?:model-selector|menu\b|menu-item|menu-group|sub-menu|popover\b|tooltip(?:\b|__|--)|slim-scroll)(?:__|--|\.|,|\s|:|\{|$)|\.wb-(?:switch|icon)(?:\b|__|--)/
// Shared cr sheets also style sibling components. A selector that names one of them and does not also
// name the model selector is dropped: under this scope it could never match, and copying it would
// advertise coverage the module does not provide.
const FOREIGN_COMPONENT=/\.cr-(?:add-menu|files-submenu|reference-files-submenu|mode-submenu|experts-submenu|skills-submenu|connectors-submenu|workspace-picker|permission-panel|context-usage|connector-chip|search-input|select\b|input\b|modal\b|drawer\b|tabs\b|badge\b)/
const observedPath='.tmp/rea-model-select-open-settings-20261016/layout.json'
const observed=JSON.parse(fs.readFileSync(observedPath,'utf8'))
const observedId='ev_1c3853a9a4dd6f99cf76d1874ad57af7ad6fb56c33e6b4e5c2a2e770f91f462e'
if(observed.evidenceId!==observedId)throw Error('Runtime layout evidence changed')
const observedNodes=observed.layout.documents.flatMap(document=>document.nodes)
const observedMenu=observedNodes.find(node=>node.attributes?.class==='cr-model-selector__menu cr-menu')
const observedShadow=observedMenu?.styles?.['box-shadow']
const observedBackground=observedMenu?.styles?.['background-color']
for(const[file,pin,role]of cssSources){
const text=fs.readFileSync('.tmp/rea-css-recovered/'+file,'utf8')
if(sha(text)!==pin||cssManifest.files.find(item=>item.file===file)?.sha256!==pin)throw Error('CSS identity mismatch '+file)
manifest.sources.push({file,sha256:pin,bytes:Buffer.byteLength(text)})
const tree=postcss.parse(text)
tree.walkRules(rule=>{
if(role==='tokens'){
const declarations=(rule.nodes??[]).filter(node=>node.type==='decl'&&(/^--cr-/.test(node.prop)||/^--wb-/.test(node.prop)||/^--cb-/.test(node.prop)))
if(!declarations.length)return
const clone=rule.clone({nodes:declarations.map(node=>node.clone())})
clone.selector=scopedTokenSelectors(rule)
manifest.tokenSelectorMappings.push({file,original:rule.selector,scoped:clone.selector,declarations:declarations.length})
css+=wrapAtRules(clone,rule.parent)+'\n'
return
}
if(role==='runtime override'){
// This retained rule is a shared WorkBuddy override that also names AddMenu and several other
// popovers. Only the model-selector selectors belong to this module; the rest are dropped rather than
// copied under a scope where they could never apply.
const selectors=rule.selectors.filter(selector=>selector.includes('cr-model-selector'))
if(!selectors.length)return
const clone=rule.clone()
clone.selector=selectors.map(selector=>selector.replace(/\bbody\b/g,SCOPE)).join(',')
manifest.tokenSelectorMappings.push({file,original:rule.selector,scoped:clone.selector,declarations:(clone.nodes??[]).filter(node=>node.type==='decl').length})
css+=clone.toString()+'\n'
return
}
if(!COMPONENT_PATTERN.test(rule.selector))return
const clone=rule.clone()
const selectors=clone.selectors.filter(selector=>!FOREIGN_COMPONENT.test(selector)||/cr-model-selector/.test(selector))
if(!selectors.length)return
clone.selector=selectors.map(selector=>selector.startsWith(SCOPE)?selector:SCOPE+' '+selector).join(',')
css+=wrapAtRules(clone,rule.parent)+'\n'
})
tree.walkAtRules('keyframes',rule=>{if(['cr-model-pop-in','cr-sub-menu-pop-in','wb-switch-spin'].includes(rule.params))css+=rule.toString()+'\n'})
}
manifest.adaptations.push('CSS is scoped under '+SCOPE+', preserving every original media/theme condition including the dark-theme groups and the IDE Night/Light platform selectors. Token declarations are re-emitted on their original conditions instead of being flattened to the root scope.')
if(observedShadow)css+=`/* Retained REA runtime override (${observedId}); the original override producer is not located in the fixed export. */\n${SCOPE} .cr-model-selector__menu.cr-menu{box-shadow:${observedShadow}}\n`
if(observedBackground&&!observedBackground.startsWith('rgba(0, 0, 0, 0)'))css+=`${SCOPE} .cr-model-selector__menu.cr-menu{background:${observedBackground}}\n`
manifest.observations.push('The open-state popover body has no REA geometry evidence beyond the retained desktop-sdk-setup override and the trigger node in '+observedPath+'. The menu rule therefore keeps the recovered source declarations, overlaid only with the observed box-shadow and background.')
// The conversation shell owns three rules the selector depends on and that this component sheet does not
// carry: the shared .wb-icon flex base, the composer input-slot 50% icon radius, and the input-slot
// --cr-text-primary bridge to --wb-color-text-primary that makes the trigger label #000 instead of the
// panel default rgba(0,0,0,.9). They are recovered from the same fixed REA CSS export.
const SHELL_RULES=[
{file:'contexts-BkjwYSZT.css',sha256:'50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380',name:'wb-icon flex base',selectors:['.wb-icon'],expect:'justify-content:center;align-items:center;line-height:0;display:inline-flex'},
{file:'contexts-BkjwYSZT.css',sha256:'50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380',name:'composer input-slot icon radius',selectors:['.wb-home-composer__input-slot [class*=icon]:not([class*=Labeled])','.wb-home-composer__input-slot .voice-mic-trigger'],expect:'border-radius:50%'},
{file:'contexts-BkjwYSZT.css',sha256:'50cbd673f7f35fc7f966bdddc6c9f5677fdfe944cb904888d214619fca259380',name:'composer input-slot token bridge',relation:'ancestor',selectors:['.wb-home-composer__input-slot .cr-input-toolbar'],expect:'--cr-text-primary:var(--wb-color-text-primary)'},
]
for(const spec of SHELL_RULES){
const text=fs.readFileSync('.tmp/rea-css-recovered/'+spec.file,'utf8')
if(sha(text)!==spec.sha256)throw Error('Shell CSS identity mismatch '+spec.file)
if(!manifest.sources.some(item=>item.file===spec.file))manifest.sources.push({file:spec.file,sha256:spec.sha256})
let found=false
postcss.parse(text).walkRules(rule=>{
if(found)return
if(rule.selectors.length!==spec.selectors.length)return
if(!spec.selectors.every((selector,index)=>rule.selectors[index]===selector))return
const body=rule.nodes.filter(node=>node.type==='decl').map(node=>node.prop+':'+node.value).join(';')
if(!body.includes(spec.expect))throw Error('Shell rule body changed for '+spec.name+': '+body)
found=true
const clone=rule.clone()
// The original ancestor (.wb-home-composer__input-slot) is the composer shell. Two of these rules select
// a descendant of that shell, so the shell prefix is replaced by this module scope. The token-bridge rule
// instead targets the shell's own toolbar, which is an ancestor of this module; there the scope is appended
// as a descendant of that toolbar, keeping the original element relationship intact either way.
clone.selector=spec.selectors.map(selector=>{
// Keep the shell's toolbar element and drop only the shell root, which YCode does not render.
const withoutShell=selector.replace('.wb-home-composer__input-slot ','')
return spec.relation==='ancestor' ? withoutShell+' '+SCOPE : SCOPE+' '+withoutShell
}).join(',')
css+='/* '+spec.name+' — recovered from '+spec.file+', original selector: '+spec.selectors.join(' , ')+' */\n'+clone.toString()+'\n'
})
if(!found)throw Error('Shell rule not found: '+spec.name)
}
manifest.adaptations.push('Three conversation-shell rules are recovered alongside the component sheet because the measured trigger depends on them: the shared .wb-icon flex base, the composer input-slot 50% icon radius, and the input-slot --cr-text-primary bridge to --wb-color-text-primary. All three keep their original declarations; only the shell ancestor is replaced by this module scope.')
// --------------------------------------------------------------------------- types
const types=`/** Typed host contract for the recovered WorkBuddy 5.8.2 model selector. */
import type {ComponentType, ReactNode} from 'react'
export type ModelEffort='minimal'|'low'|'medium'|'high'|'xhigh'|'max'
export type ModelBusyLevel='idle'|'normal'|'busy'|'congested'|'unavailable'|'unknown'
export interface ModelBadgeSpec{label:string;color?:string;background?:string;icon?:string}
export interface ModelTierBadgeSpec{label:string;level?:'flagship'|'member';color?:string;background?:string}
export interface ModelPromotionFooter{badge?:ModelBadgeSpec;text?:string;actionLabel?:string}
export interface ModelPromotionCredits{original:string;discounted:string;displayMode?:'replace'|'suffix'}
export interface ModelTierFooter{text:string;actionLabel?:string}
export interface ModelOption{
id:string
name:string
iconUrl?:string
icon?:unknown
groupId?:string
description?:string
credits?:string
disabled?:boolean
configIssue?:boolean
isExternal?:boolean
supportsReasoning?:boolean
onlyReasoning?:boolean
canDisableThinking?:boolean
isThinking?:boolean
supportedEfforts?:readonly ModelEffort[]
defaultEffort?:ModelEffort
reasoningEffort?:ModelEffort
busyLevel?:ModelBusyLevel
badges?:readonly ModelBadgeSpec[]
tierBadges?:readonly ModelTierBadgeSpec[]
promotionCredits?:ModelPromotionCredits
promotionFooter?:ModelPromotionFooter
tierFooter?:ModelTierFooter
tier?:string
contextWindow?:string
supportedContextWindows?:readonly number[]
defaultContextWindow?:number
selectedContextWindow?:number
maxInputTokens?:number
}
export interface ModelGroup{id:string;label?:string;order?:number;icon?:unknown;models:readonly ModelOption[];trailingActions?:readonly {id:string;label:string;icon?:unknown}[]}
export interface ModelSelection{id:string;name:string;isThinking:boolean;reasoningEffort?:ModelEffort;tier?:string}
export interface ModelGroupMenuEntry{id:string;label:string;order?:number;icon?:unknown;models:readonly ModelOption[];trailingActions?:readonly {id:string;label:string;icon?:unknown}[]}
export interface ModelSelectorFooterAction{label:string;icon?:unknown;disabled?:boolean;onClick?():void}
export interface ModelSelectorProvider{
options?:readonly ModelOption[]
groups?:readonly ModelGroup[]
groupMenuItems?:readonly ModelGroupMenuEntry[]
selectedModel?:ModelOption
disabledTooltip?:string
isMaxMode?:boolean
footerAction?:ModelSelectorFooterAction
onChange?(selection:ModelSelection):void
onOpenChange?(isOpen:boolean):void
onMaxModeChange?(isMaxMode:boolean):void
onContextWindowChange?(modelId:string,contextWindow:number):void
onModelTierUpgrade?(modelId:string):void
onAction?(modelId:string,action:'edit'):void
onClick?():void
}
export interface ModelSelectorDraftState{draft:{selections:{model:ModelSelection|null}}}
export interface ModelSelectorInputBoxStore{api:{setModel(selection:ModelSelection):void}}
export interface ModelSelectorRuntime{
mode:'light'|'dark'
prefixCls?:string
useInputBoxStore():ModelSelectorInputBoxStore
useInputBoxSelector<T>(selector:(state:ModelSelectorDraftState)=>T,isEqual?:(left:T,right:T)=>boolean):T
useRenderDiag?(name:string,meta:Record<string,unknown>):void
}
export interface ModelSelectorConfig{prefixCls:string;mode:'light'|'dark';locale:string;t(key:string):string}
export declare const modelSelectorLabels:Record<string,string>
export declare function configureModelSelectorRuntime(runtime:ModelSelectorRuntime):ModelSelectorRuntime
export declare function readModelSelectorRuntime():ModelSelectorRuntime
export declare function ModelSelectorRuntimeProvider(props:{runtime:ModelSelectorRuntime;children?:ReactNode}):ReactNode
export declare function useModelSelectorRuntime():ModelSelectorRuntime
export declare function useModelSelectorConfig():ModelSelectorConfig
export interface ModelSelectorProps{provider?:ModelSelectorProvider;className?:string;compact?:boolean;popoverPlacement?:string}
export declare const ModelSelectorImpl:ComponentType<ModelSelectorProps>
export declare const ModelSelectPopover:ComponentType<Record<string,unknown>>
export declare const ModelSubMenu:ComponentType<Record<string,unknown>>
export declare const ModelItem:ComponentType<Record<string,unknown>>
export declare const ModelGroupMenuItem:ComponentType<Record<string,unknown>>
export declare const ModelTierBadge:ComponentType<Record<string,unknown>>
export declare const Menu:ComponentType<{children?:ReactNode;className?:string;style?:React.CSSProperties;minHeight?:number|string;maxHeight?:number|string}>
export declare const MenuItem:ComponentType<{children?:ReactNode;icon?:ReactNode;extra?:ReactNode;disabled?:boolean;active?:boolean;onClick?():void;className?:string;style?:React.CSSProperties}>
export declare const MenuDivider:ComponentType<{className?:string;style?:React.CSSProperties}>
export declare const MenuGroup:ComponentType<{title?:ReactNode;children?:ReactNode;className?:string}>
export declare const Popover:ComponentType<Record<string,unknown>>
export declare const PopoverTrigger:ComponentType<{children?:ReactNode}>
export declare const PopoverContent:ComponentType<{children?:ReactNode;className?:string}>
export declare const Tooltip:ComponentType<Record<string,unknown>>
export declare const ToggleSwitch:ComponentType<{checked?:boolean;onChange?(checked:boolean):void;ariaLabel?:string}>
export declare const ReasoningEffortPanel:ComponentType<Record<string,unknown>>
export declare const ContextWindowPanel:ComponentType<Record<string,unknown>>
export declare const OverflowTitleSpan:ComponentType<{text:string;className?:string}>
export declare const ModelBadge:ComponentType<{badge:ModelBadgeSpec}>
export declare const useOverlayScrollbar:(ref:React.RefObject<HTMLElement|null>)=>{visible:boolean;thumbHeight:number;thumbTop:number}
export declare function resolveModelIcon(option:{name:string;icon?:unknown;iconUrl?:string}):ReactNode
export declare function getModelIconByName(name:string):ReactNode
export declare function getDefaultIsThinking(option:ModelOption):boolean|undefined
export declare function isReasoningConfigurable(option:ModelOption):boolean
export declare function createModelSelection(option:ModelOption,isThinking:boolean,effort?:ModelEffort):ModelSelection
export declare function collectModelOptions(options?:readonly ModelOption[],groups?:readonly ModelGroupMenuEntry[]):ModelOption[]
export declare function resolveSelectedModelId(input:{selection?:ModelSelection|null;selectedModel?:ModelOption|null}):string|undefined
export declare function resolveSelectedModelLabel(input:{selection?:ModelSelection|null;options?:readonly ModelOption[];groupMenuItems?:readonly ModelGroupMenuEntry[];selectedModel?:ModelOption|null}):string
export declare function formatCredits(credits:string):string
export declare function formatContextWindow(length:number):string
export declare function getSupportedContextWindows(option:ModelOption):number[]
`
// --------------------------------------------------------------------------- write
manifest.hostBindings=[
{kind:'react-context-provider',name:'ModelSelectorRuntimeProvider',contract:'mode, useInputBoxStore, useInputBoxSelector, useRenderDiag'},
{kind:'react-context',name:'ModelSelectorConfigContext / useModelSelectorConfig',contract:'prefixCls, mode, locale, t'},
{kind:'npm',name:'@floating-ui/react',names:HOST_FLOATING},
{kind:'npm',name:'dompurify',names:['default']},
{kind:'npm',name:'react',names:['* as React','* as JSX (react/jsx-runtime)']},
]
const hostSource=moduleSource.replace('var xW={low:', '// Host extension: models.dev exposes a minimal effort supported by the local kernel.\nvar xW={minimal:`极低`,low:')
const outputs=[[FOLDER+'source.mjs',hostSource],[FOLDER+'source.d.mts',types],[FOLDER+'source.css',css]]
manifest.outputs=outputs.map(([file,text])=>({file,sha256:sha(text),bytes:Buffer.byteLength(text)}))
outputs.push([FOLDER+'manifest.json',JSON.stringify(manifest,null,2)+'\n'])
const check=process.argv.includes('--check')
for(const[file,text]of outputs){
if(check){
let current
try{current=fs.readFileSync(file,'utf8')}catch{throw Error('Recovered output missing '+file)}
if(current!==text)throw Error('Recovered output drift '+file)
}else fs.writeFileSync(file,text)
}
const summary={result:check?'PASS':'WRITTEN',sources:manifest.sources.length,bodies:manifest.bodies.length,adaptations:manifest.adaptations.length,outputs:outputs.length,audit,corpusReactAliases:coreIndex.reactAlias.size+primitiveIndex.reactAlias.size,corpusJsxAliases:coreIndex.jsxAlias.size+primitiveIndex.jsxAlias.size}
summary.bytes=manifest.outputs.reduce((total,item)=>total+item.bytes,0)
console.log(JSON.stringify(summary))