Verify analysis recovery in browser and refresh new job status

This commit is contained in:
2026-09-06 12:47:11 +03:00
parent bfef768974
commit fa28fb5f85
7 changed files with 49 additions and 19 deletions
+10 -2
View File
@@ -17,6 +17,7 @@ let apiKeyListFailure=false;
process.env.IHALEIST_USER_DATA_DIR=dir;
const qaJobs=await import('../server/ai-job-store.mjs');
const {qualifyOfferDraft}=await import('../server/offer-draft.mjs');
const {executeAnalysisJob}=await import('../server/analysis-job.mjs');
const pendingQaJobs=new Map();
const qaHeartbeat=setInterval(()=>{for(const job of pendingQaJobs.values())qaJobs.heartbeatAiJob(job.id,job.runId);},5000);qaHeartbeat.unref();
const probe=netServer();await new Promise(r=>probe.listen(0,'127.0.0.1',r));const port=probe.address().port;await new Promise(r=>probe.close(r));
@@ -28,9 +29,16 @@ process.env.IHALEIST_SHARED_DATA_DIR=join(dir,'shared');
const {observeTenders}=await import('../server/tender-history.mjs');
observeTenders(tenders);
for(let revision=1;revision<=22;revision++) observeTenders([{...tenders[0],saat:revision%2?'11:00':'10:00'}]);
const ui=await createServer({server:{host:'127.0.0.1',port:0,proxy:{'/api':{target:'http://127.0.0.1:'+port}}},plugins:[{name:'qa-fixtures',configureServer(server){server.middlewares.use((req,res,next)=>{
const ui=await createServer({server:{host:'127.0.0.1',port:0,proxy:{'/api':{target:'http://127.0.0.1:'+port}}},plugins:[{name:'qa-fixtures',configureServer(server){server.middlewares.use(async(req,res,next)=>{
if(req.url==='/qa-ai-controls') {res.setHeader('Content-Type','text/html; charset=utf-8');res.end(`<html lang="tr"><h1>Yerel AI işi testi</h1><p>Sağlayıcı taklidi kullanılır; ücretli AI çağrısı yapılmaz.</p><button id="finish">Bekleyen QA işini tamamla</button><p role="status"></p><script>document.querySelector('#finish').onclick=async()=>{const r=await fetch('/qa-ai-complete',{method:'POST'});document.querySelector('[role=status]').textContent=await r.text();};</script></html>`);return;}
if(req.url==='/qa-ai-complete' && req.method==='POST') {for(const job of pendingQaJobs.values())qaJobs.finishAiJob(job.id,job.runId,{success:true,...qualifyOfferDraft({bolumler:[{baslik:'Teklif Mektubu (Kapak)',icerik:'QA kayıtlı sonuç: Laboratuvar teklif taslağı. Bu sentetik metin resmi teklif değildir.'}]},['Teklif Mektubu (Kapak)'])});pendingQaJobs.clear();res.end('QA işleri tamamlandı');return;}
if(req.url==='/qa-ai-complete' && req.method==='POST') {
for(const job of pendingQaJobs.values()) {
const result=job.operation==='analiz' ? await executeAnalysisJob(job,{pin:qaJobs.pinAiJobInput,analyze:async()=>({result:{summary:'QA kayıtlı genel analiz: Laboratuvar kaynak metni korundu.',items:[],requiredDocuments:[],roadmap:[]},mode:job.input.mode,model:{label:'QA',provider:'sentetik',model:'qa'},attempts:[]})})
: {success:true,...qualifyOfferDraft({bolumler:[{baslik:'Teklif Mektubu (Kapak)',icerik:'QA kayıtlı sonuç: Laboratuvar teklif taslağı. Bu sentetik metin resmi teklif değildir.'}]},['Teklif Mektubu (Kapak)'])};
qaJobs.finishAiJob(job.id,job.runId,result);
}
pendingQaJobs.clear();res.end('QA işleri tamamlandı');return;
}
if(req.url==='/api/me/ai-jobs' && req.method==='POST') {
if(req.headers.authorization!=='Bearer '+token){res.writeHead(401);res.end('{}');return;}
let body='';req.on('data',chunk=>body+=chunk);req.on('end',()=>{try{