// Live model/Skill readiness only. Never uploads a reference or submits H3. import assert from 'node:assert/strict'; const base='http://127.0.0.1:5173'; const abort=new AbortController(); async function api(path,method='GET',body){ const response=await fetch(base+path,{method,redirect:'error',signal:AbortSignal.timeout(20000),headers:{Origin:base,...(body?{'Content-Type':'application/json'}:{})},...(body?{body:JSON.stringify(body)}:{})}); assert(response.ok,`${method} ${path}: HTTP ${response.status}`); return response.json(); } let sessionId; try { const catalog=await api('/api/skills'); assert(catalog.skills.some(skill=>skill.name==='swads-image-to-video'),'New Skill missing from live catalog'); const history=await api('/api/image-video/tasks'); console.log(JSON.stringify({stage:'catalog-and-history',skillFound:true,historyAvailable:history!==undefined,remoteMutation:false})); ({sessionId}=await api('/api/sessions','POST',{})); const stream=await fetch(`${base}/api/sessions/${sessionId}/events`,{signal:abort.signal}); assert(stream.ok&&stream.body,'SSE unavailable'); const reader=stream.body.getReader(); const sent=await api(`/api/sessions/${sessionId}/messages`,'POST',{text:'仅做 swads-image-to-video 接入只读检查:完整读取该 Skill 的 SKILL.md 和 references/swads.md。然后简短说明它不需要 CMS,以及必须分别批准参考图外传和 H3 生成。不要调用任何 CMS 工具,不读取图片或私人业务数据,不上传、不入库、不生成、不写文件。',attachmentIds:[]}); const timer=setTimeout(()=>abort.abort(),150000); let buffer='';const decoder=new TextDecoder();let loaded=false;let answer=false;let referenceRead=false;let done=false;const referenceCalls=new Set(); try { while(!done){ const chunk=await reader.read();assert(!chunk.done,'Unexpected SSE end');buffer+=decoder.decode(chunk.value,{stream:true}); let boundary; while((boundary=buffer.indexOf('\n\n'))!==-1){ const frame=buffer.slice(0,boundary);buffer=buffer.slice(boundary+2); const data=frame.split('\n').find(line=>line.startsWith('data: '))?.slice(6);if(!data)continue; const event=JSON.parse(data);if(event.runId!==sent.runId)continue; assert(event.type!=='approval.required','Unexpected external/mutating action request'); if(event.type==='tool.requested'){ assert(['read','ls','find','grep'].includes(event.payload.toolName),'Unexpected business tool requested'); if(event.payload.toolName==='read'&&JSON.stringify(event.payload.arguments).includes('references/swads.md'))referenceCalls.add(event.payload.toolCallId); } if(event.type==='skill.loaded')loaded=true; if(event.type==='tool.completed'&&referenceCalls.has(event.payload.toolCallId))referenceRead=true; if(event.type==='assistant.delta'&&event.payload.delta?.trim())answer=true; if(['run.completed','run.failed','run.cancelled'].includes(event.type)){ console.log(JSON.stringify({stage:'model-skill',terminal:event.type,skillLoaded:loaded,referenceRead,answerReceived:answer,remoteMutation:false})); assert(event.type==='run.completed');done=true; } } } assert(loaded&&referenceRead&&answer,'Skill/read/answer evidence incomplete'); }finally{clearTimeout(timer);abort.abort();} console.log(JSON.stringify({result:'PASS',scope:'live Skill reading and local history only',h3GenerationVerified:false})); }catch(error){console.error(JSON.stringify({result:'FAIL',message:String(error.message).slice(0,300)}));process.exitCode=1;} finally{ abort.abort(); if(sessionId){await api(`/api/sessions/${sessionId}/cancel`,'POST',{}).catch(()=>{});await api(`/api/sessions/${sessionId}`,'DELETE').catch(()=>{});} }