import {CentralBridge} from './instinct-central-client.mjs'; import {CENTRAL_CONFIG} from './instinct-central-config.mjs'; export function mountCentralUI(AP){ let lastJob=null;const shown=new Set();const prior=AP.ask.bind(AP);let client=null,enabled=false,draft=null,proof=null,timer=null,busy=false,widget=null; const button=document.createElement('button');button.className='nav-item';button.id='central-open';button.textContent='☁ Instinct · puente de pruebas';document.getElementById('ap-sidebar').append(button); const panel=document.createElement('section');panel.id='central-panel';panel.hidden=true;panel.setAttribute('aria-label','Puente central de pruebas'); const style=document.createElement('style');style.textContent='#central-panel{position:fixed;inset:8%;z-index:100001;background:var(--bg,#0b1220);color:var(--text,#edf3ff);border:1px solid #677b91;border-radius:16px;padding:22px;overflow:auto}#central-panel label{display:block;margin:12px 0}#central-panel button,#central-panel select{padding:8px;margin:4px;font:inherit}#central-panel pre{white-space:pre-wrap;overflow-wrap:anywhere;max-height:32vh;overflow:auto;background:#101a2e;color:#e9f1ff;padding:12px}#central-open{margin-top:8px}';document.head.append(style); panel.innerHTML=`
Solo datos ficticios. Respuestas NO AUTENTICADAS: texto inerte, sin acciones. No prueba identidad del remitente.
La consulta y el snapshot mínimo se guardan en la cola hasta 24h y se envían desde fivetech2@gmail.com a 3xdy4j@mail.instinct.com. Gmail y el destinatario conservan copias aparte. Los datos ERP siguen en este navegador (IndexedDB).
Pendiente de despliegue. No envía ni cambia el chat.
Sin consulta preparada.
Revisa cada consulta antes de enviarla. No se ejecutan herramientas. Cerrar la pestaña no borra la cola; al reabrir este dispositivo usa de nuevo el puente para recuperar. No compartas tu sesión.
`;document.body.append(panel); const el=id=>panel.querySelector('#'+id),status=x=>el('ic-status').textContent=x,show=()=>panel.hidden=false; const ready=()=>!!CENTRAL_CONFIG.workerURL&&!!CENTRAL_CONFIG.turnstileSiteKey; function enableState(){el('ic-enable').disabled=!ready()||!el('ic-consent').checked||!proof;} button.onclick=async()=>{show();if(!ready())return;try{await loadTurnstile();if(widget===null)widget=turnstile.render(el('ic-challenge'),{sitekey:CENTRAL_CONFIG.turnstileSiteKey,action:'adaptapro-session',callback:t=>{proof=t;enableState();},'expired-callback':()=>{proof=null;enableState();}});status('Completa la comprobación y acepta solo datos demo.');}catch{status('No se pudo cargar la comprobación. Puente pausado.');}}; el('ic-close').onclick=()=>panel.hidden=true;el('ic-consent').onchange=enableState; function pause(){enabled=false;clearInterval(timer);draft=null;el('ic-send').disabled=true;status('Puente pausado. El ciclo automático sigue detenido.');} el('ic-disable').onclick=pause; el('ic-enable').onclick=async()=>{try{ if(!ready()||!el('ic-consent').checked||!proof)throw Error('Falta consentimiento o comprobación'); client=new CentralBridge(CENTRAL_CONFIG.workerURL); if(!client.storage.getItem(client.key))await client.start({consent:true,turnstileToken:proof}); proof=null;el('ic-enable').disabled=true;if(widget!==null)turnstile.reset(widget); const manual=document.getElementById('ig-enabled');if(manual?.checked)manual.click(); enabled=true;clearInterval(AP.cycleTimer);AP.startCycle=function(){clearInterval(this.cycleTimer);}; el('ic-check').disabled=false;el('ic-clear').disabled=false;status('Chat central activo, sin OAuth por tester. Datos demo; cada mensaje se revisa.'); await check();clearInterval(timer); }catch(e){pause();status(e.message);}}; // Selecting the manual bridge pauses this one; no double sends. document.getElementById('ig-enabled')?.addEventListener('change',e=>{if(e.target.checked)pause();}); AP.ask=async function(text,quiet=false,...rest){if(!enabled)return prior(text,quiet,...rest);if(quiet)return;try{ if(!el('ic-consent').checked)throw Error('Consentimiento retirado');if(!AP.db)throw Error('ERP no listo'); const c=AP.context();const tables={stock:c.stock||[],orders:c.orders||[],proposals:c.proposals||[],suppliers:AP.rows('SELECT s.id,s.name,s.lead_days,sp.sku,sp.unit_cost_cents,sp.min_order_qty FROM suppliers s JOIN supplier_products sp ON sp.supplier_id=s.id WHERE s.active=1')}; const fields={stock:['sku','on_hand','reserved','available','reorder_point','target_stock','needs_restock'],orders:['order_id','sku','quantity','status','region'],proposals:['id','sku','proposed_qty','status'],suppliers:['id','sku','name','lead_days','unit_cost_cents','min_order_qty']}; const clean={};for(const[t,keys]of Object.entries(fields))clean[t]=tables[t].slice(0,80).map(r=>Object.fromEntries(keys.filter(k=>r[k]!==undefined).map(k=>[k,r[k]]))); draft={agent:el('ic-agent').value,question:String(text),context:{tables:clean},reviewed:true,consent:true}; el('ic-preview').textContent='Desde: fivetech2@gmail.com\nDestino: 3xdy4j@mail.instinct.com\nNO AUTENTICADA · solo análisis demo\n\n'+JSON.stringify(draft,null,2);el('ic-send').disabled=false;status('Revisa cuenta, destinatario, pregunta y snapshot. Nada enviado.');show(); }catch(e){status(e.message);show();}}; el('ic-send').onclick=async()=>{if(busy)return;busy=true;el('ic-send').disabled=true;try{if(!enabled||!draft||!el('ic-consent').checked)throw Error('Revisión/consentimiento pendiente');const r=await client.submit(draft);lastJob=r.id;el('ic-run').disabled=false;AP.tab('chat');AP.append(draft.question,'user');draft=null;status('Cola aceptó '+r.id+' ('+r.mode+'). No prueba envío ni entrega.');}catch(e){draft=null;status('Resultado de cola pendiente de verificar: '+e.message+'. Comprueba estado; no reenvíes a ciegas.');}finally{busy=false;}}; async function check(){if(!client)return;try{let x=await client.check();lastJob=(x.jobs||[]).find(j=>['queued','sent','uncertain','sending'].includes(j.status))?.id||null;el('ic-run').disabled=!lastJob||(x.jobs||[]).find(j=>j.id===lastJob)?.status!=='queued';if(lastJob){const j=x.jobs.find(j=>j.id===lastJob);if(['sent','uncertain'].includes(j.status)){await client.collect(lastJob);x=await client.check();}}const seen=shown;for(const j of x.jobs||[]){if(j.status==='answered'&&typeof j.text==='string'&&!seen.has(j.id)){ AP.tab('chat');const node=document.createElement('div');node.className='chat-msg ai';node.textContent='[NO AUTENTICADA · prueba central] '+j.agent+': '+j.text;document.querySelector('.chat-body').append(node);seen.add(j.id);}} status('Estado: '+(x.jobs||[]).map(j=>j.agent+' '+j.id+' '+j.status).join('; ')); }catch(e){status(e.message);}} el('ic-run').onclick=async()=>{if(busy||!lastJob)return;if(!confirm('Enviar SOLO este turno revisado desde fivetech2@gmail.com a 3xdy4j@mail.instinct.com? Requiere selección previa del dueño y modo prueba.'))return;busy=true;el('ic-run').disabled=true;try{const r=await client.run(lastJob);status('Turno '+r.id+': '+(r.status||r.error||'dry-run')+'. Gmail accepted no prueba entrega. No reintentar resultado incierto.');}catch(e){status(e.message+'; comprobar estado antes de intentar de nuevo.');}finally{busy=false;}}; el('ic-check').onclick=check;el('ic-clear').onclick=async()=>{if(!confirm('Borrar consulta/respuesta de esta sesión de la cola? No borra las copias de correo.'))return;try{await client.clear();pause();el('ic-check').disabled=true;el('ic-clear').disabled=true;status('Sesión de cola borrada. Copias de correo no borradas.');}catch(e){status(e.message);}}; globalThis.AdaptaProCentral={show,check,getState:()=>({enabled,configured:ready(),prepared:!!draft})}; } let turnstileLoad; function loadTurnstile(){if(globalThis.turnstile)return Promise.resolve();return turnstileLoad||=(new Promise((resolve,reject)=>{const s=document.createElement('script');s.src='https://challenges.cloudflare.com/turnstile/v0/api.js?render=explicit';s.onload=resolve;s.onerror=reject;document.head.append(s);}));}