ai-helper-agent 1.14.10 → 1.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/bin/agent.js CHANGED
@@ -372,20 +372,32 @@ if (command === 'start') {
372
372
 
373
373
  const running = await isRunning(config);
374
374
  if (running) {
375
+ let apiShutdownOk = false;
375
376
  try {
376
377
  const resp = await fetch(`http://${config.host}:${config.port}/api/shutdown`, {
377
378
  method: 'POST'
378
379
  });
379
380
  if (resp.ok) {
380
- const data = await resp.json();
381
- console.log(`[Agent] ${data.message || t('agentStopped')}`);
381
+ try {
382
+ const data = await resp.json();
383
+ console.log(`[Agent] ${data.message || t('agentStopped')}`);
384
+ } catch {
385
+ // 服务端在发送响应后关闭连接,json() 可能读不到完整数据
386
+ // 但 shutdown 请求已成功送达,服务正在关闭
387
+ console.log(`[Agent] ${t('agentStopped')}`);
388
+ }
389
+ apiShutdownOk = true;
382
390
  removePidFile();
383
391
  process.exit(0);
384
392
  }
385
- } catch (err) {
386
- console.error(`[Agent] ${t('apiShutdownFailed')}: ${err.message}`);
393
+ } catch {
394
+ // isRunning() 刚确认服务在线,fetch 出错说明服务端已关闭连接(shutdown 正在执行)
395
+ // 视为关闭成功,不打印错误
396
+ apiShutdownOk = true;
397
+ }
398
+ if (!apiShutdownOk) {
399
+ console.log(`[Agent] ${t('apiShutdownFallback')}`);
387
400
  }
388
- console.log(`[Agent] ${t('apiShutdownFallback')}`);
389
401
  }
390
402
 
391
403
  const pid = getPidFromFile();
@@ -93,9 +93,9 @@ Output the evaluation result in JSON format (do not include markdown code blocks
93
93
  "issues": ["discovered issue 1", "discovered issue 2"],
94
94
  "suggestions": ["improvement suggestion 1"],
95
95
  "refinedAnswer": null // if revision is needed, provide the revised answer here
96
- }`;try{let e=`${o.apiBase}/chat/completions`,i=s.model||a||o.modelName,c=await ur(e,{method:`POST`,headers:{Authorization:`Bearer ${o.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify({model:i,messages:[{role:`system`,content:`You are a strict quality evaluator. Output the evaluation result in JSON format; do not include markdown code block markers.`},{role:`user`,content:_}],stream:!1,temperature:s.temperature||.3,max_tokens:s.maxTokens||1024})},3e4,1,1e3);if(!c.ok)throw Error(`Subtask reflection API error: ${c.status}`);let u=await c.json(),m=u.choices?.[0]?.message?.content||``,h=kt(m),g=Date.now()-f;return p.push({id:crypto.randomUUID(),iteration:0,timestamp:new Date().toISOString(),status:`success`,nodeType:`reflection`,nodeName:t(`reflection.subtaskNodeName`,{name:l}),reflectionType:`subtask`,overallScore:h.overallScore,dimensions:h.dimensions,issues:h.issues,suggestions:h.suggestions,prompt:_,rawContent:m,apiRequest:{model:i,messageCount:2,temperature:s.temperature||.3,maxTokens:s.maxTokens||1024},apiResponse:{tokenUsage:u.usage||null},duration:g}),r.debug(`[Background] subtask reflectioncomplete: ${l}, score: ${h.overallScore}/10, elapsed: ${g}ms`),u.usage&&yt({sessionId:d,model:i,usage:u.usage,callType:`subtask_reflection`}).catch(()=>{}),{score:h.overallScore,refinedContent:h.refinedAnswer&&h.refinedAnswer!==n?h.refinedAnswer:null,reflectionLog:p}}catch(e){r.warn(`[Background] subtask reflection failed:`,e.message);let n=Date.now()-f;return p.push({id:crypto.randomUUID(),iteration:0,timestamp:new Date().toISOString(),status:`failed`,nodeType:`reflection`,nodeName:t(`reflection.subtaskNodeName`,{name:l}),reflectionType:`subtask`,error:e.message,duration:n}),{score:null,refinedContent:null,reflectionLog:p}}}e(`zh`,{reactLoop:{apiCallNode:`API调用 (第{count}次{subtask})`,apiCallSubtask:`, 子任务第{iteration}次`,preparing:`准备开始执行...`,toolExec:`工具执行:{name}`,toolExecStart:`执行工具: {name}`,taskPlanDone:`任务规划完成`,executionDone:`执行完成`,userDenied:`用户拒绝了此操作`,subtaskRolledBack:`子任务 {name} (已回滚)`,subtaskRollbackFailed:`子任务 {name} (回滚失败)`,subtaskCount:`已拆解为 {count} 个子任务`,toolReflection:`工具反思: {name}`,subtaskNode:`子任务 {index}: {name}`,subtaskCompleted:`子任务 {index}: {name} (完成)`,subtaskFailed:`子任务 {index}: {name} (失败)`,userCancelled:`用户取消`,skippedAfterPlanTask:`已跳过(plan_task 已拆分子任务,本轮其他工具调用不再执行)`,toolError:`错误: {message}`,loopTimeout:`ReAct 循环总超时 ({timeout}ms,不含澄清等待时间)`,apiInvalidJson:`API 响应不是有效的 JSON (HTTP {status}): {error}。响应前100字符: {preview}`,infiniteLoopDetected:`连续{count}次执行完全相同的工具调用(入参和返参均相同),疑似陷入死循环,已自动终止。请更换策略或缩小任务范围后重试。`,maxIterationsExceeded:`ReAct 循环超过最大迭代次数 ({maxIterations})`,toolTimeout:`工具执行超时 ({timeout}ms): {tool}`,toolAborted:`工具执行已被用户终止: {tool}`,jsonParseFailed:`JSON 解析失败 (HTTP {status}): {error}。响应前100字符: {preview}`}}),e(`en`,{reactLoop:{apiCallNode:`API Call (#{count}{subtask})`,apiCallSubtask:`, Subtask #{iteration}`,preparing:`Preparing to execute...`,toolExec:`Tool Exec:{name}`,toolExecStart:`Executing: {name}`,taskPlanDone:`Task planning completed`,executionDone:`Execution completed`,userDenied:`User denied this operation`,subtaskRolledBack:`Subtask {name} (rolled back)`,subtaskRollbackFailed:`Subtask {name} (rollback failed)`,subtaskCount:`Broken down into {count} subtasks`,toolReflection:`Tool Reflection: {name}`,subtaskNode:`Subtask {index}: {name}`,subtaskCompleted:`Subtask {index}: {name} (completed)`,subtaskFailed:`Subtask {index}: {name} (failed)`,skippedAfterPlanTask:`Skipped (plan_task has decomposed subtasks, other tool calls in this round are no longer executed)`,toolError:`Error: {message}`,loopTimeout:`ReAct loop total timeout ({timeout}ms, excluding clarification wait time)`,apiInvalidJson:`API response is not valid JSON (HTTP {status}): {error}. First 100 chars: {preview}`,infiniteLoopDetected:`Executed the exact same tool call {count} times in a row (both inputs and outputs identical), likely stuck in an infinite loop. Automatically terminated. Please change strategy or narrow the task scope and retry.`,maxIterationsExceeded:`ReAct loop exceeded maximum iterations ({maxIterations})`,toolTimeout:`Tool execution timed out ({timeout}ms): {tool}`,toolAborted:`Tool execution was aborted by user: {tool}`,jsonParseFailed:`JSON parse failed (HTTP {status}): {error}. First 100 chars: {preview}`}});var Nt=new Set,Pt=new Set,Ft={manage_cookies:`sensitiveTool.manage_cookies`,clear_data:`sensitiveTool.clear_data`,download_file:`sensitiveTool.download_file`,manage_tab:`sensitiveTool.manage_tab`,agent_file:`sensitiveTool.agent_file`};async function It(e,n,i,a){let o=Ft[e],s=o?t(o):e,c=3e5;r.debug(`[Background] requesting user confirmation for tool operation: ${e}`,n);let l=``;if(e===`manage_tab`&&n.action===`close`&&n.tabId!==void 0)try{let e=await chrome.tabs.get(parseInt(n.tabId,10));l=t(`sensitiveTool.tabInfo`,{title:e.title||t(`sensitiveTool.untitled`),url:e.url||t(`sensitiveTool.unknownUrl`)})}catch(e){l=t(`sensitiveTool.tabInfoError`,{error:e.message})}return new Promise(i=>{let o=t=>{t.type===`TOOL_CONFIRMATION_RESPONSE`&&t.toolCallId===e&&(chrome.runtime.onMessage.removeListener(o),clearTimeout(u),r.debug(`[Background] userconfirmresult: ${e} = ${t.confirmed}, scope: ${t.scope}`),t.confirmed&&t.scope===`loop`&&(Pt.add(a),r.debug(`[Background] session ${a} set as current taskallow`)),i(t.confirmed))};chrome.runtime.onMessage.addListener(o);let u=setTimeout(()=>{chrome.runtime.onMessage.removeListener(o),r.debug(`[Background] confirmtimeout,defaultdeny: ${e}`),i(!1)},c);chrome.runtime.sendMessage({type:`SHOW_CONFIRM_DIALOG`,data:{toolName:e,toolLabel:s,args:n,toolCallId:e,sessionId:a,timeout:c,message:l?t(`dialog.confirmAction`,{name:s})+l:void 0}}).catch(e=>{r.debug(`[Background] sendconfirm dialogmessage failed:`,e.message),chrome.runtime.onMessage.removeListener(o),clearTimeout(u),i(!0)})})}function Lt(e,t){let n=Error(e);return n.executionLog=t,n}async function Rt(e,t){if(e)try{if(await D({sessionId:e,...t})){r.debug(`[Background] checkpoint saved (sessionId=${e}, iteration=${t.iteration}, reason=${t.interruptedReason})`);try{let t=await I(e);t?r.debug(`[Background] checkpoint write verifypassed,message=${t.currentMessages?.length||0}`):r.error(`[Background] ⚠️ checkpoint write returned successfulbut read-back empty!sessionId=${e}, possibly is DB store does not exist or transaction not committed`)}catch(e){r.error(`[Background] checkpoint read-backverify failed:`,e.message)}}else r.error(`[Background] checkpoint save returned false (sessionId=${e}, iteration=${t.iteration}), possibly is reactCheckpoints store not found,DB upgrade blocked`)}catch(e){r.error(`[Background] save checkpoint failed:`,e.message,e.stack)}}async function zt(e){if(e)try{await ie(e),r.debug(`[Background] checkpoint cleaned (sessionId=${e})`)}catch(e){r.warn(`[Background] cleanup checkpoint failed:`,e.message)}}function Bt(e){if(!e||e.length===0)return e;let t=[],n=0;for(;n<e.length;){let i=e[n];if(i.role===`tool`){let t=n>0?e[n-1]:null;if(!t||t.role!==`assistant`||!t.tool_calls){r.warn(`[Background] cleanupIncompleteMessagePairs: skip orphaned tool message (index=`+n+`)`),n++;continue}}if(i.role===`assistant`&&i.tool_calls&&i.tool_calls.length>0){let a=n+1<e.length?e[n+1]:null;if(!a||a.role!==`tool`){r.warn(`[Background] cleanupIncompleteMessagePairs: orphaned assistant(tool_calls),clear tool_calls (index=`+n+`)`),t.push({...i,tool_calls:void 0}),n++;continue}}t.push(i),n++}return t.length!==e.length&&r.debug(`[Background] cleanupIncompleteMessagePairs: cleanup complete,message:`,e.length,`→`,t.length),t}async function Vt(e,t=``,n=null){if(!e)return null;let i=await I(e);if(!i){r.warn(`[Background] not found sessionId=${e} checkpoint, no way to restore`);try{let e=await F();e.length===0?r.warn(`[Background] IndexedDB contains no checkpoint record (may never have been saved successful)`):(r.warn(`[Background] current IndexedDB checkpoint column table:`,e.map(e=>({sessionId:e.sessionId,iteration:e.iteration,updatedAt:new Date(e.updatedAt).toISOString(),reason:e.interruptedReason}))),`${e.length}${e.map(e=>e.sessionId).join(`, `)}`)}catch(e){r.error(`[Background] read checkpoint column table failed:`,e),`${e.message}`}return null}r.debug(`[Background] from checkpoint restore ReAct loop: sessionId=${e}, iteration=${i.iteration}, messages=${i.currentMessages?.length}, userGuidance=${t?` has `:` no `}, resumeCallId=${n}`);let a=JSON.parse(JSON.stringify(i.currentMessages||[]));if(a=Bt(a),t&&t.trim()){let e={role:`user`,content:`[Task Resume Notice] The task was previously interrupted during execution and is now resuming from the checkpoint.\n\nAdditional user instructions: ${t.trim()}\n\nPlease continue completing the task based on the previous tool call results, taking the above instructions into account. Do not repeat already completed steps.`};a.push(e),r.debug(`[Background] injected user additionaldescription,messagetotal:`,a.length)}else a.push({role:`user`,content:`[Task Resume Notice] The task was previously interrupted during execution and is now resuming from the checkpoint. Please continue completing the task based on the previous tool call results. Do not repeat already completed steps.`}),r.debug(`[Background] injected defaultrestoreprompt,messagetotal:`,a.length);let o=await Ht(a,i.model,await In(),i.tabId,i.apiParams||{},e,null,null,i.globalIteration||{value:i.iteration||0},i.executionLog||[],n||i.callId||null);return await zt(e),o}async function Ht(e,n,i,o,c={},u=null,d=null,f=null,p={value:0},m=[],h=null){u&&Nt.add(u);let g=0,v=0,T=[...e],D=new Map,ee=null,k=0,A=null,j=null,ie=e=>{if(j===null){let t=S(typeof T[0]?.content==`string`?T[0].content:JSON.stringify(T[0]?.content||``)),n=S(JSON.stringify(i.map(e=>{let{id:t,...n}=e;return n}))),a=x(e,0,le.customModelMap);j=a-t-n-4096-2e3,j<1e3&&(r.warn(`[Background] ReAct Token budget too low: ${j},using minimumbudget 1000`),j=1e3),r.debug(`[Background] ReAct Token budget: ${j} tokens (model: ${e}, actualsystem promptword: ${t}, actual tooldefinition: ${n}, context window: ${a})`)}return j},ae=6e3,M=async()=>{let e=ie(n||`default`),t=_(y(T));if(t<=e)return;let i=T.length,a=t,o=T[0]?.role===`system`?[T[0]]:[],s=o.length?[...T.slice(1)]:[...T],c=e=>_(y(e.map(e=>({...e,content:w(e.content)}))));for(let i=0;i<3&&(t=c([...o,...s]),!(t<=e));i++){let e=-1,t=-1;for(let n=0;n<s.length;n++)if(s[n].role===`assistant`&&Array.isArray(s[n].tool_calls)&&s[n].tool_calls.length>0){for(e=n,t=n+1;t<s.length&&s[t].role===`tool`;)t++;break}if(e===-1)break;let l=s.slice(e,t);r.debug(`[Background] attemptsummarystep ${i+1} round (message ${e}-${t-1})`);let u=await wt(l,R,n,{signal:L,timeout:15e3});if(!u){r.debug(`[Background] summary failed,downgraded to weight-based trimming`);break}let d=(A?.match(/Round \d+:/g)?.length||0)+1;A=(A||``)+`Round ${d}: ${u}\n`;let f=s.findIndex(e=>e.role===`user`),p={role:`user`,content:`[History Summary] The following is a summary of previous steps:\n${A.trim()}`,_isSummary:!0},m=s.findIndex(e=>e._isSummary);if(m>=0){s.splice(m,1);let e=s.findIndex(e=>e.role===`user`);s.splice(e+1,0,p)}else s.splice(f+1,0,p);let h=s.findIndex(e=>e===l[0]);h>=0&&s.splice(h,l.length);let g=c([...o,...s]);r.debug(`[Background] summary complete: ${a} → ${g} tokens (${l.length} → 1summary)`)}if(t=c([...o,...s]),t>e){r.debug(`[Background] still exceeding after summary (${t} > ${e}),enablefallbacktrimming`);let n=e=>e._reflection?3:e.role===`tool`?2:1;for(;s.length>0&&!(c([...o,...s])<=e);){let e=-1,t=0;for(let r=0;r<s.length;r++){let i=n(s[r]);if(i>t&&(t=i,e=r),t>=3)break}(e<0||t===0)&&(e=0);let r=s.splice(e,1)[0];if(r?.role===`assistant`&&r.tool_calls)for(;s.length>0&&s[e]?.role===`tool`;)s.splice(e,1);else if(r?.role===`tool`)for(let t=e-1;t>=0&&s[t]?.role===`assistant`&&s[t]?.tool_calls;t--){let e=s[t+1];(!e||e.role!==`tool`)&&delete s[t].tool_calls}}}T=[...o,...s];let l=c(T);r.debug(`[Background] ReAct Token trimming: ${a} → ${l} tokens (${i} → ${T.length} )`)},N=[...m],P=null,se=0,F=1500;async function I(e=``,t=!1){if(d){r.debug(`[Background] saveCheckpointNow skip (subtask): reason=${e}`);return}if(!u){r.warn(`[Background] saveCheckpointNow skip (sessionId empty)`);return}let i=Date.now();if(!t&&i-se<F){r.debug(`[Background] saveCheckpointNow throttlestreamskip: reason=${e}, since last save ${i-se}ms < ${F}ms`);return}se=i,r.debug(`[Background] saveCheckpointNow start saving: sessionId=${u}, reason=${e}, force=${t}, iteration=${g}, messages=${T.length}, callId=${h}`),await Rt(u,{currentMessages:T.map(e=>{let t={...e};return typeof t.content==`function`&&(t.content=String(t.content)),t}),executionLog:[...N],iteration:g,globalIteration:{value:p?.value||g},subtaskPlan:P,currentSubtaskIndex:null,totalReflectionRounds:v,model:n||R?.modelName,apiParams:c,taskContext:null,tabId:o,callId:h,interruptedReason:e||`in_progress`})}me(u||o),_e(o);let ce=u?he(u,!d):null,L=ce?.signal,R=await V(),le=await we();c&&c.imageApiBase&&(R.apiBase=c.imageApiBase),c&&c.imageApiKey&&(R.apiKey=c.imageApiKey);let z=R.reactConfig,ue=z.maxIterations,pe=z.apiTimeout,ge=z.loopTimeout,ve=z.toolTimeout,ye=z.clarifyTimeout,be=d&&(d.subtaskId||d.type===`subagent`),xe=be?{...R.streamConfig,streamEnabled:!1}:R.streamConfig;r.debug(`[Background] reactLoop configuration:`,z),r.debug(`[Background] reactLoop received tool column table:`,i.map(e=>e.function.name),`count:`,i.length),r.debug(`[Background] reactLoop tasktext:`,d?`subtask ${d.subtaskId||` no `} (${d.subtaskName||`maintask`})`:` no `);let Se=0,Ce=``,H=new Map;function U(e,t){try{let n=Date.now();if(typeof f==`function`&&f([...N]),e===Ce&&n-Se<200)return;Se=n,Ce=e;let i=[];for(let e of N){let t=H.get(e.id);(!t||t.status!==e.status||t.nodeName!==e.nodeName)&&(i.push(e),H.set(e.id,{status:e.status,nodeName:e.nodeName}))}let a={type:`EXECUTION_STATUS_UPDATE`,nodeName:e,status:t,callId:h,executionLog:i};u&&(a.sessionId=u),chrome.runtime.sendMessage(a).catch(e=>{r.debug(`[Background] sendexecution statusupdate failed:`,e.message)})}catch(e){r.debug(`[Background] sendexecution statusupdate exception:`,e.message)}}let Te=Date.now(),Ee=0,De=null,W=!1;U(t(`reactLoop.preparing`),`processing`),await I(`initial`,!0);function Oe(){W||(De=Date.now(),W=!0,r.debug(`[Background] overall looptimeoutpaused`))}function ke(){let e=Date.now()-Te;return ge+Ee-e}function Ae(){if(W&&De!==null){let e=Date.now()-De;Ee+=e,De=null,W=!1,r.debug(`[Background] overall looptimeoutrestored,pause duration:`,Math.round(e/1e3),`s,remaining time:`,Math.round(ke()/1e3),`s`)}}me(u||o);try{for(;g<ue;){if(B(o)||u&&B(u))throw Lt(t(`bg.reactCancelled`),N);let e=Date.now()-Te,f=ge+Ee;if(e>f)throw Lt(t(`reactLoop.loopTimeout`,{timeout:ge}),N);g++,de(u);let m=f-e;r.debug(`[Background] ReAct loopstep ${g} times,remaining time: ${Math.round(m/1e3)}s (paused: ${Math.round(Ee/1e3)}s)`);let A,se=Date.now(),F=O(T);for(let e=0;e<F.length-1;e++)F[e]={...F[e],content:w(F[e].content)};let ue=crypto.randomUUID(),me=fe(u),he=i.some(e=>e.function?.name===`plan_task`),_e=i;he&&r.debug(`[Background] current iterationcontains plan_task,using Agent limittool into task decomposition,tool count :`,_e.length);let Se=y(F),Ce=_(Se),we=x(n||R.modelName,0,le.customModelMap),De=S(JSON.stringify(_e.map(e=>{let{id:t,...n}=e;return n}))),W=_(De),ke=Ce+W+4096,G=Se+De,K=E(ke,we);if(K.level!==`safe`&&(r.warn(`[Background] context pressure: ${K.level} (${Math.round(K.ratio*100)}% used, message: ${Ce}, tool: ${W}, estimated total: ${ke}/${we} tokens)`),K.level===`critical`||ke>we*.85)){let e=ie(n||`default`),t=Math.floor(e*.75);r.warn(`[Background] context pressure too high,maindynamictrimmingmessage: current ${Ce} tokens → target budget ${t}`);let i=oe(T,Math.max(t,2e3));if(i.trimmedCount>0){T=i.messages,F=O(T);for(let e=0;e<F.length-1;e++)F[e]={...F[e],content:w(F[e].content)};r.warn(`[Background] maindynamictrimmingcomplete: ${i.trimmedCount} messageremove,remaining ${T.length} , ${y(F)} tokens`)}}N.push({id:ue,iteration:g,globalIteration:me,timestamp:new Date().toISOString(),status:`processing`,nodeType:`api_call`,nodeName:t(`reactLoop.apiCallNode`,{count:me,subtask:d?t(`reactLoop.apiCallSubtask`,{iteration:g}):``}),apiRequest:{messageCount:F.length,toolCount:_e.length}}),U(t(`reactLoop.apiCallNode`,{count:me,subtask:d?t(`reactLoop.apiCallSubtask`,{iteration:g}):``}),`processing`);let je;try{let e=`${R.apiBase}/chat/completions`;r.debug(`[Background] API requesttool count count :`,_e.length);let i={model:n||R.modelName,messages:b(F),tools:_e.map(e=>{let{id:t,...n}=e;return n}),stream:xe.streamEnabled!==!1};r.debug(`[Background] API requestbody stream mode:`,i.stream,`tool count count :`,i.tools.length,`messagecount:`,i.messages.length,`model:`,i.model),c.temperature!==void 0&&(i.temperature=c.temperature),c.top_p!==void 0&&(i.top_p=c.top_p);let a=Math.max(m-3e4,pe);je=setTimeout(()=>{r.warn(`[Background] ⚠️ API call outertimeoutprotection triggered (${Math.round(a/1e3)}s),force abort`),ce?.abort()},a),xe.streamEnabled!==!1&&(chrome.runtime.sendMessage({type:`STREAM_START`,sessionId:u,callId:h}).catch(()=>{}),r.debug(`[Background] STREAM_START sent (API call with before )`));let o=await ur(e,{method:`POST`,headers:{Authorization:`Bearer ${R.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify(i),signal:L},pe,z.apiRetryCount,z.apiRetryBaseDelay,(e,t)=>{r.warn(`[Background] API retry ${e} times after :`,t.message)});if(clearTimeout(je),!o.ok){let e=await o.text();throw r.error(`[Background] API response error:`,o.status,e),Error(`HTTP error! status: ${o.status}, message: ${e.substring(0,500)}`)}if(xe.streamEnabled!==!1&&o.body){r.debug(`[Background] enteringstreamingmode,streamEnabled:`,xe.streamEnabled);let e=new ct(u,xe,{callId:h,preStarted:!0}),t=await lt(o.body.getReader(),e,L);r.debug(`[Background] streaming API responsecomplete,content length:`,t.content.length,`tool_calls:`,t.toolCalls?.length,`usage:`,t.usage);let n=t.toolCalls?t.toolCalls.map(e=>({...e,id:e.id||`tc_fb_${crypto.randomUUID().slice(0,8)}`})):null;A={choices:[{message:{role:`assistant`,content:t.content||``,reasoning_content:t.reasoningContent,...n?{tool_calls:n}:{}},finish_reason:t.status===`tool_calls`?`tool_calls`:t.truncated?`length`:`stop`}],usage:t.usage}}else{let e=await o.text();r.debug(`[Background] API responsestate:`,o.status,`originaltext length:`,e.length,`preview:`,e.substring(0,200));try{A=JSON.parse(e)}catch(n){throw r.error(`[Background] JSON parse failed:`,n),r.error(`[Background] originalresponse:`,e),Error(t(`reactLoop.apiInvalidJson`,{status:o.status,error:n.message,preview:e.substring(0,100)}))}let n=A.choices?.[0]?.message?.tool_calls;if(n&&n.length>0){let e=n.map(e=>({...e,id:e.id||`tc_fb_${crypto.randomUUID().slice(0,8)}`}));A.choices[0].message.tool_calls=e}}}catch(e){clearTimeout(je);let i=e.name===`AbortError`;i?r.debug(`[Background] API call with by usercancel`):r.error(`[Background] API call with failed:`,e.message||e);let a=N.findIndex(e=>e.id===ue);throw a!==-1&&(N[a]={...N[a],duration:Date.now()-se,status:i?`cancelled`:`failed`,apiRequest:{...N[a].apiRequest,model:n||R.modelName,temperature:c.temperature,top_p:c.top_p,messageCount:F.length,toolCount:_e.length},error:i?t(`reactLoop.userCancelled`):e.message}),Lt(i?t(`bg.requestCancelled`):e.message,N)}let Me=Date.now()-se,q=A.choices?.[0]?.message;A.choices?.[0]?.finish_reason===`length`&&r.warn(`[Background] API response reason token limit truncated (finish_reason: length),contentmay be incomplete`);let Ne=N.findIndex(e=>e.id===ue);if(Ne!==-1&&(N[Ne]={...N[Ne],duration:Me,status:`success`,thought:q?.content||``,action:q?.tool_calls?.length>0?{name:q.tool_calls[0].function?.name||q.tool_calls[0].name,params:(()=>{try{return JSON.parse(q.tool_calls[0].function?.arguments||`{}`)}catch{return{}}})()}:null,apiRequest:{...N[Ne].apiRequest,model:n||R.modelName,temperature:c.temperature,top_p:c.top_p,messageCount:F.length,toolCount:_e.length},apiResponse:{finishReason:A.choices?.[0]?.finish_reason,tokenUsage:A.usage}}),A.usage&&(yt({sessionId:u,model:n||R.modelName,usage:A.usage,callType:`react_loop`}).catch(()=>{}),G>0&&A.usage.prompt_tokens>0)){ne(G,A.usage.prompt_tokens);let e=te();e.active&&r.debug(`[Background] Tokencalibration activated: factor=${e.factor.toFixed(3)}, samples=${e.samples}`)}if(U(t(`reactLoop.apiCallNode`,{count:me,subtask:d?t(`reactLoop.apiCallSubtask`,{iteration:g}):``}),`success`),q?.tool_calls&&q.tool_calls.length>0){r.debug(`[Background] recei to tool call:`,q.tool_calls);let e=JSON.stringify(q.tool_calls.map(e=>({name:e.function?.name||e.name,args:typeof e.function?.arguments==`string`?(()=>{try{return JSON.parse(e.function.arguments)}catch{return e.function.arguments}})():e.function?.arguments||{}})));r.debug(`[Background] this roundtool callinput fingerprint:`,e.substring(0,200)),T.push(q),await M();let d=[],f=z.reflection;async function m(e,o,u,m,g,_,v,y,b){if(B(o)||_&&B(_))throw Lt(t(`bg.reactCancelled`),y);let x=e.function?.name||e.name,w=Date.now(),T=e.function?.arguments;r.debug(`[Background] executeSingleToolCall recei to tool call:`,JSON.stringify({name:x,argsType:typeof T,argsRaw:typeof T==`string`?T.substring(0,200):JSON.stringify(T).substring(0,200),id:e.id}));let E=(()=>{if(!T)return{};if(typeof T==`object`)return T;try{return JSON.parse(T||`{}`)}catch{return{}}})(),O=e.id||`tc_fallback_${crypto.randomUUID()}`,ee=a.has(x),te=l[x]?.includes(E.action);if((ee||te)&&z.toolConfirmationEnabled)if(_&&Pt.has(_))r.debug(`[Background] session ${_} got currenttaskallow,skip confirm: ${x}`);else{Oe(),chrome.runtime.sendMessage({type:`TOOL_CONFIRM_START`,..._?{sessionId:_}:{}}).catch(e=>{r.debug(`[Background] send TOOL_CONFIRM_START message failed:`,e.message)});let n;try{n=await It(x,E,o,_)}finally{Ae(),chrome.runtime.sendMessage({type:`TOOL_CONFIRM_END`,..._?{sessionId:_}:{}}).catch(e=>{r.debug(`[Background] send TOOL_CONFIRM_END message failed:`,e.message)})}if(!n){let n=crypto.randomUUID();return y.push({id:n,iteration:v,timestamp:new Date().toISOString(),status:`cancelled`,nodeType:`tool_exec`,nodeName:t(`reactLoop.toolExec`,{name:x}),action:{name:x,params:E},error:t(`reactLoop.userDenied`)}),U(t(`reactLoop.toolExec`,{name:x}),`cancelled`),b.push({role:`tool`,content:`The user declined this operation.`,tool_call_id:O}),await M(),{toolCall:e,result:{success:!1,content:`The user declined this operation.`,error:`user_denied`},toolResultStr:`The user declined this operation.`,toolLogEntry:{id:n,iteration:v,timestamp:new Date().toISOString(),status:`cancelled`,nodeType:`tool_exec`,nodeName:t(`reactLoop.toolExec`,{name:x}),action:{name:x,params:E},error:t(`reactLoop.userDenied`)}}}}let k=`${x}:${JSON.stringify(E)}`;if(D.has(k)){let e=D.get(k);if(Date.now()-e.timestamp<6e4){if(s.has(x))return{...e,fromCache:!0};D.clear()}else D.delete(k)}s.has(x)||D.clear(),await new Promise(e=>setTimeout(e,0));let ne=crypto.randomUUID();y.push({id:ne,iteration:v,timestamp:new Date().toISOString(),status:`processing`,nodeType:`tool_exec`,nodeName:t(`reactLoop.toolExecStart`,{name:x})}),U(t(`reactLoop.toolExecStart`,{name:x}),`processing`),x===`clarify_question`&&(Oe(),chrome.runtime.sendMessage({type:`CLARIFY_START`,..._?{sessionId:_}:{}}).catch(e=>{r.debug(`[Background] send CLARIFY_START message failed:`,e.message)}));let A;try{if(A=await qt(e,o,u,m,g,_),x===`clarify_question`){Ae(),chrome.runtime.sendMessage({type:`CLARIFY_END`,..._?{sessionId:_}:{}}).catch(e=>{r.debug(`[Background] send CLARIFY_END message failed:`,e.message)}),r.debug(`[Background] clarification complete,re-filteringtool...`);try{let e=await In(),t=await V(),a=t.reactConfig.enableToolPreselect,o=t.reactConfig.preselectMinToolCount||3;if(a&&e.length>o){let t=await vt(b,n,e,c);t.type===`tools`&&(i=t.tools,j=null,r.debug(`[Background] clarification after toolre-filtercomplete:`,i.map(e=>e.function.name))),t.executionLog&&y.push(...t.executionLog)}else a||r.debug(`[Background] toolpre-filterclosed,after clarification, notre-filter`)}catch(e){r.warn(`[Background] clarification after toolre-filter failed, continue withcurrenttoolset:`,e.message)}}let a;a=typeof A==`string`?A:A&&typeof A==`object`&&`content`in A?A.content??JSON.stringify(A):JSON.stringify(A);let l=A&&A.success!==!1,T=S(a),ee=!1,te=a;if(T>ae){let e=re(a,ae);r.debug(`[Background] tool ${x} result truncated: ${T} → ${S(e)} tokens`),ee=!0,te=e,a=e}be||chrome.runtime.sendMessage({type:`STREAM_TOOL_RESULT`,sessionId:_,result:{toolCallId:O,toolName:x,success:l,content:l?te:A?.error||te,truncated:ee,duration:Date.now()-w}}).catch(()=>{});let ie=y.filter(e=>e.nodeType===`tool_exec`&&e.iteration===v).sort((e,t)=>y.indexOf(e)-y.indexOf(t)),N=0;for(let e=ie.length-1;e>=0&&ie[e].status===`failed`;e--)N++;if(y.filter(e=>e.nodeType===`reflection`&&e.reflectionType===`tool`).length<(f?.toolReflection?.maxPerIteration||2)&&Dt(a,N,f)&&d.push({toolName:x,toolResultStr:a,toolCallParams:E,toolCallId:O,priority:Et(x,a,N)}),x===`plan_task`&&A&&A.success&&A.data){P=A.data,r.debug(`[Background] received taskplanresult:`,JSON.stringify(P));let e=JSON.stringify({success:!0,message:`Task planning complete. Decomposed into ${P.subtasks.length} subtasks.`,data:P});b.push({role:`tool`,content:e,tool_call_id:O}),await M();let a=y.findIndex(e=>e.id===ne);a!==-1&&(y[a]={...y[a],duration:Date.now()-w,status:`success`,nodeName:t(`reactLoop.taskPlanDone`),action:{name:x,params:E},observation:t(`reactLoop.subtaskCount`,{count:P.subtasks.length}),subtaskCount:P.subtasks.length,strategy:P.strategy}),U(t(`reactLoop.taskPlanDone`),`success`);let l=q.tool_calls.findIndex(e=>e.id===O);if(l!==-1&&l<q.tool_calls.length-1){for(let e=l+1;e<q.tool_calls.length;e++){let n=q.tool_calls[e],i=n.function?.name||n.name||`unknown`,a=n.id||`tc_fallback_${crypto.randomUUID()}`;r.debug(`[Background] resend skiptool STREAM_TOOL_RESULT:`,i,`id:`,a),b.push({role:`tool`,content:JSON.stringify({success:!1,message:`Skipped: plan_task has decomposed subtasks; other tool calls in this round will not be executed.`}),tool_call_id:a}),be||chrome.runtime.sendMessage({type:`STREAM_TOOL_RESULT`,sessionId:_,result:{toolCallId:a,toolName:i,success:!1,content:t(`reactLoop.skippedAfterPlanTask`),truncated:!1,duration:0}}).catch(()=>{})}await M()}let u=await Wt(P,n,i,o,c,_,y,p,z.reflection,R,H,h);if(B(o)||_&&B(_))throw Lt(t(`bg.reactCancelled`),y);let d=3e3,f=u.map((e,t)=>{let n=typeof e.result==`string`?e.result:JSON.stringify(e.result),r=S(n)>d?C(n,d):n;return`Subtask ${t+1}: ${e.subtaskName}\nResult: ${r}`}).join(`
96
+ }`;try{let e=`${o.apiBase}/chat/completions`,i=s.model||a||o.modelName,c=await ur(e,{method:`POST`,headers:{Authorization:`Bearer ${o.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify({model:i,messages:[{role:`system`,content:`You are a strict quality evaluator. Output the evaluation result in JSON format; do not include markdown code block markers.`},{role:`user`,content:_}],stream:!1,temperature:s.temperature||.3,max_tokens:s.maxTokens||1024})},3e4,1,1e3);if(!c.ok)throw Error(`Subtask reflection API error: ${c.status}`);let u=await c.json(),m=u.choices?.[0]?.message?.content||``,h=kt(m),g=Date.now()-f;return p.push({id:crypto.randomUUID(),iteration:0,timestamp:new Date().toISOString(),status:`success`,nodeType:`reflection`,nodeName:t(`reflection.subtaskNodeName`,{name:l}),reflectionType:`subtask`,overallScore:h.overallScore,dimensions:h.dimensions,issues:h.issues,suggestions:h.suggestions,prompt:_,rawContent:m,apiRequest:{model:i,messageCount:2,temperature:s.temperature||.3,maxTokens:s.maxTokens||1024},apiResponse:{tokenUsage:u.usage||null},duration:g}),r.debug(`[Background] subtask reflectioncomplete: ${l}, score: ${h.overallScore}/10, elapsed: ${g}ms`),u.usage&&yt({sessionId:d,model:i,usage:u.usage,callType:`subtask_reflection`}).catch(()=>{}),{score:h.overallScore,refinedContent:h.refinedAnswer&&h.refinedAnswer!==n?h.refinedAnswer:null,reflectionLog:p}}catch(e){r.warn(`[Background] subtask reflection failed:`,e.message);let n=Date.now()-f;return p.push({id:crypto.randomUUID(),iteration:0,timestamp:new Date().toISOString(),status:`failed`,nodeType:`reflection`,nodeName:t(`reflection.subtaskNodeName`,{name:l}),reflectionType:`subtask`,error:e.message,duration:n}),{score:null,refinedContent:null,reflectionLog:p}}}e(`zh`,{reactLoop:{apiCallNode:`API调用 (第{count}次{subtask})`,apiCallSubtask:`, 子任务第{iteration}次`,preparing:`准备开始执行...`,toolExec:`工具执行:{name}`,toolExecStart:`执行工具: {name}`,taskPlanDone:`任务规划完成`,executionDone:`执行完成`,userDenied:`用户拒绝了此操作`,subtaskRolledBack:`子任务 {name} (已回滚)`,subtaskRollbackFailed:`子任务 {name} (回滚失败)`,subtaskCount:`已拆解为 {count} 个子任务`,toolReflection:`工具反思: {name}`,subtaskNode:`子任务 {index}: {name}`,subtaskCompleted:`子任务 {index}: {name} (完成)`,subtaskFailed:`子任务 {index}: {name} (失败)`,userCancelled:`用户取消`,skippedAfterPlanTask:`已跳过(plan_task 已拆分子任务,本轮其他工具调用不再执行)`,toolError:`错误: {message}`,loopTimeout:`ReAct 循环总超时 ({timeout}ms,不含澄清等待时间)`,apiInvalidJson:`API 响应不是有效的 JSON (HTTP {status}): {error}。响应前100字符: {preview}`,infiniteLoopDetected:`连续{count}次执行完全相同的工具调用(入参和返参均相同),疑似陷入死循环,已自动终止。请更换策略或缩小任务范围后重试。`,maxIterationsExceeded:`ReAct 循环超过最大迭代次数 ({maxIterations})`,toolTimeout:`工具执行超时 ({timeout}ms): {tool}`,toolAborted:`工具执行已被用户终止: {tool}`,jsonParseFailed:`JSON 解析失败 (HTTP {status}): {error}。响应前100字符: {preview}`}}),e(`en`,{reactLoop:{apiCallNode:`API Call (#{count}{subtask})`,apiCallSubtask:`, Subtask #{iteration}`,preparing:`Preparing to execute...`,toolExec:`Tool Exec:{name}`,toolExecStart:`Executing: {name}`,taskPlanDone:`Task planning completed`,executionDone:`Execution completed`,userDenied:`User denied this operation`,subtaskRolledBack:`Subtask {name} (rolled back)`,subtaskRollbackFailed:`Subtask {name} (rollback failed)`,subtaskCount:`Broken down into {count} subtasks`,toolReflection:`Tool Reflection: {name}`,subtaskNode:`Subtask {index}: {name}`,subtaskCompleted:`Subtask {index}: {name} (completed)`,subtaskFailed:`Subtask {index}: {name} (failed)`,skippedAfterPlanTask:`Skipped (plan_task has decomposed subtasks, other tool calls in this round are no longer executed)`,toolError:`Error: {message}`,loopTimeout:`ReAct loop total timeout ({timeout}ms, excluding clarification wait time)`,apiInvalidJson:`API response is not valid JSON (HTTP {status}): {error}. First 100 chars: {preview}`,infiniteLoopDetected:`Executed the exact same tool call {count} times in a row (both inputs and outputs identical), likely stuck in an infinite loop. Automatically terminated. Please change strategy or narrow the task scope and retry.`,maxIterationsExceeded:`ReAct loop exceeded maximum iterations ({maxIterations})`,toolTimeout:`Tool execution timed out ({timeout}ms): {tool}`,toolAborted:`Tool execution was aborted by user: {tool}`,jsonParseFailed:`JSON parse failed (HTTP {status}): {error}. First 100 chars: {preview}`}});var Nt=new Set,Pt=new Set,Ft={manage_cookies:`sensitiveTool.manage_cookies`,clear_data:`sensitiveTool.clear_data`,download_file:`sensitiveTool.download_file`,manage_tab:`sensitiveTool.manage_tab`,agent_file:`sensitiveTool.agent_file`};async function It(e,n,i,a){let o=Ft[e],s=o?t(o):e,c=3e5;r.debug(`[Background] requesting user confirmation for tool operation: ${e}`,n);let l=``;if(e===`manage_tab`&&n.action===`close`&&n.tabId!==void 0)try{let e=await chrome.tabs.get(parseInt(n.tabId,10));l=t(`sensitiveTool.tabInfo`,{title:e.title||t(`sensitiveTool.untitled`),url:e.url||t(`sensitiveTool.unknownUrl`)})}catch(e){l=t(`sensitiveTool.tabInfoError`,{error:e.message})}return new Promise(i=>{let o=t=>{t.type===`TOOL_CONFIRMATION_RESPONSE`&&t.toolCallId===e&&(chrome.runtime.onMessage.removeListener(o),clearTimeout(u),r.debug(`[Background] userconfirmresult: ${e} = ${t.confirmed}, scope: ${t.scope}`),t.confirmed&&t.scope===`loop`&&(Pt.add(a),r.debug(`[Background] session ${a} set as current taskallow`)),i(t.confirmed))};chrome.runtime.onMessage.addListener(o);let u=setTimeout(()=>{chrome.runtime.onMessage.removeListener(o),r.debug(`[Background] confirmtimeout,defaultdeny: ${e}`),i(!1)},c);chrome.runtime.sendMessage({type:`SHOW_CONFIRM_DIALOG`,data:{toolName:e,toolLabel:s,args:n,toolCallId:e,sessionId:a,timeout:c,message:l?t(`dialog.confirmAction`,{name:s})+l:void 0}}).catch(e=>{r.debug(`[Background] sendconfirm dialogmessage failed:`,e.message),chrome.runtime.onMessage.removeListener(o),clearTimeout(u),i(!0)})})}function Lt(e,t){let n=Error(e);return n.executionLog=t,n}async function Rt(e,t){if(e)try{if(await D({sessionId:e,...t})){r.debug(`[Background] checkpoint saved (sessionId=${e}, iteration=${t.iteration}, reason=${t.interruptedReason})`);try{let t=await I(e);t?r.debug(`[Background] checkpoint write verifypassed,message=${t.currentMessages?.length||0}`):r.error(`[Background] ⚠️ checkpoint write returned successfulbut read-back empty!sessionId=${e}, possibly is DB store does not exist or transaction not committed`)}catch(e){r.error(`[Background] checkpoint read-backverify failed:`,e.message)}}else r.error(`[Background] checkpoint save returned false (sessionId=${e}, iteration=${t.iteration}), possibly is reactCheckpoints store not found,DB upgrade blocked`)}catch(e){r.error(`[Background] save checkpoint failed:`,e.message,e.stack)}}async function zt(e){if(e)try{await ie(e),r.debug(`[Background] checkpoint cleaned (sessionId=${e})`)}catch(e){r.warn(`[Background] cleanup checkpoint failed:`,e.message)}}function Bt(e){if(!e||e.length===0)return e;let t=[],n=0;for(;n<e.length;){let i=e[n];if(i.role===`tool`){let t=n>0?e[n-1]:null;if(!t||t.role!==`assistant`||!t.tool_calls){r.warn(`[Background] cleanupIncompleteMessagePairs: skip orphaned tool message (index=`+n+`)`),n++;continue}}if(i.role===`assistant`&&i.tool_calls&&i.tool_calls.length>0){let a=n+1<e.length?e[n+1]:null;if(!a||a.role!==`tool`){r.warn(`[Background] cleanupIncompleteMessagePairs: orphaned assistant(tool_calls),clear tool_calls (index=`+n+`)`),t.push({...i,tool_calls:void 0}),n++;continue}}t.push(i),n++}return t.length!==e.length&&r.debug(`[Background] cleanupIncompleteMessagePairs: cleanup complete,message:`,e.length,`→`,t.length),t}async function Vt(e,t=``,n=null){if(!e)return null;let i=await I(e);if(!i){r.warn(`[Background] not found sessionId=${e} checkpoint, no way to restore`);try{let e=await F();e.length===0?r.warn(`[Background] IndexedDB contains no checkpoint record (may never have been saved successful)`):(r.warn(`[Background] current IndexedDB checkpoint column table:`,e.map(e=>({sessionId:e.sessionId,iteration:e.iteration,updatedAt:new Date(e.updatedAt).toISOString(),reason:e.interruptedReason}))),`${e.length}${e.map(e=>e.sessionId).join(`, `)}`)}catch(e){r.error(`[Background] read checkpoint column table failed:`,e),`${e.message}`}return null}r.debug(`[Background] from checkpoint restore ReAct loop: sessionId=${e}, iteration=${i.iteration}, messages=${i.currentMessages?.length}, userGuidance=${t?` has `:` no `}, resumeCallId=${n}`);let a=JSON.parse(JSON.stringify(i.currentMessages||[]));if(a=Bt(a),t&&t.trim()){let e={role:`user`,content:`[Task Resume Notice] The task was previously interrupted during execution and is now resuming from the checkpoint.\n\nAdditional user instructions: ${t.trim()}\n\nPlease continue completing the task based on the previous tool call results, taking the above instructions into account. Do not repeat already completed steps.`};a.push(e),r.debug(`[Background] injected user additionaldescription,messagetotal:`,a.length)}else a.push({role:`user`,content:`[Task Resume Notice] The task was previously interrupted during execution and is now resuming from the checkpoint. Please continue completing the task based on the previous tool call results. Do not repeat already completed steps.`}),r.debug(`[Background] injected defaultrestoreprompt,messagetotal:`,a.length);let o=await Ht(a,i.model,await In(),i.tabId,i.apiParams||{},e,null,null,i.globalIteration||{value:i.iteration||0},i.executionLog||[],n||i.callId||null);return await zt(e),o}async function Ht(e,n,i,o,c={},u=null,d=null,f=null,p={value:0},m=[],h=null){u&&Nt.add(u);let g=0,v=0,T=[...e],D=new Map,ee=null,k=0,A=null,j=null,ie=e=>{if(j===null){let t=S(typeof T[0]?.content==`string`?T[0].content:JSON.stringify(T[0]?.content||``)),n=S(JSON.stringify(i.map(e=>{let{id:t,...n}=e;return n}))),a=x(e,0,le.customModelMap);j=a-t-n-4096-2e3,j<1e3&&(r.warn(`[Background] ReAct Token budget too low: ${j},using minimumbudget 1000`),j=1e3),r.debug(`[Background] ReAct Token budget: ${j} tokens (model: ${e}, actualsystem promptword: ${t}, actual tooldefinition: ${n}, context window: ${a})`)}return j},ae=6e3,M=async()=>{let e=ie(n||`default`),t=_(y(T));if(t<=e)return;let i=T.length,a=t,o=T[0]?.role===`system`?[T[0]]:[],s=o.length?[...T.slice(1)]:[...T],c=e=>_(y(e.map(e=>({...e,content:w(e.content)}))));for(let i=0;i<3&&(t=c([...o,...s]),!(t<=e));i++){let e=-1,t=-1;for(let n=0;n<s.length;n++)if(s[n].role===`assistant`&&Array.isArray(s[n].tool_calls)&&s[n].tool_calls.length>0){for(e=n,t=n+1;t<s.length&&s[t].role===`tool`;)t++;break}if(e===-1)break;let l=s.slice(e,t);r.debug(`[Background] attemptsummarystep ${i+1} round (message ${e}-${t-1})`);let u=await wt(l,R,n,{signal:L,timeout:15e3});if(!u){r.debug(`[Background] summary failed,downgraded to weight-based trimming`);break}let d=(A?.match(/Round \d+:/g)?.length||0)+1;A=(A||``)+`Round ${d}: ${u}\n`;let f=s.findIndex(e=>e.role===`user`),p={role:`user`,content:`[History Summary] The following is a summary of previous steps:\n${A.trim()}`,_isSummary:!0},m=s.findIndex(e=>e._isSummary);if(m>=0){s.splice(m,1);let e=s.findIndex(e=>e.role===`user`);s.splice(e+1,0,p)}else s.splice(f+1,0,p);let h=s.findIndex(e=>e===l[0]);h>=0&&s.splice(h,l.length);let g=c([...o,...s]);r.debug(`[Background] summary complete: ${a} → ${g} tokens (${l.length} → 1summary)`)}if(t=c([...o,...s]),t>e){r.debug(`[Background] still exceeding after summary (${t} > ${e}),enablefallbacktrimming`);let n=e=>e._reflection?3:e.role===`tool`?2:1;for(;s.length>0&&!(c([...o,...s])<=e);){let e=-1,t=0;for(let r=0;r<s.length;r++){let i=n(s[r]);if(i>t&&(t=i,e=r),t>=3)break}(e<0||t===0)&&(e=0);let r=s.splice(e,1)[0];if(r?.role===`assistant`&&r.tool_calls)for(;s.length>0&&s[e]?.role===`tool`;)s.splice(e,1);else if(r?.role===`tool`)for(let t=e-1;t>=0&&s[t]?.role===`assistant`&&s[t]?.tool_calls;t--){let e=s[t+1];(!e||e.role!==`tool`)&&delete s[t].tool_calls}}}T=[...o,...s];let l=c(T);r.debug(`[Background] ReAct Token trimming: ${a} → ${l} tokens (${i} → ${T.length} )`)},N=[...m],P=null,se=0,F=1500;async function I(e=``,t=!1){if(d){r.debug(`[Background] saveCheckpointNow skip (subtask): reason=${e}`);return}if(!u){r.warn(`[Background] saveCheckpointNow skip (sessionId empty)`);return}let i=Date.now();if(!t&&i-se<F){r.debug(`[Background] saveCheckpointNow throttlestreamskip: reason=${e}, since last save ${i-se}ms < ${F}ms`);return}se=i,r.debug(`[Background] saveCheckpointNow start saving: sessionId=${u}, reason=${e}, force=${t}, iteration=${g}, messages=${T.length}, callId=${h}`),await Rt(u,{currentMessages:T.map(e=>{let t={...e};return typeof t.content==`function`&&(t.content=String(t.content)),t}),executionLog:[...N],iteration:g,globalIteration:{value:p?.value||g},subtaskPlan:P,currentSubtaskIndex:null,totalReflectionRounds:v,model:n||R?.modelName,apiParams:c,taskContext:null,tabId:o,callId:h,interruptedReason:e||`in_progress`})}me(u||o),_e(o);let ce=u?he(u,!d):null,L=ce?.signal,R=await V(),le=await we();c&&c.imageApiBase&&(R.apiBase=c.imageApiBase),c&&c.imageApiKey&&(R.apiKey=c.imageApiKey);let z=R.reactConfig,ue=z.maxIterations,pe=z.apiTimeout,ge=z.loopTimeout,ve=z.toolTimeout,ye=z.clarifyTimeout,be=d&&(d.subtaskId||d.type===`subagent`),xe=be?{...R.streamConfig,streamEnabled:!1}:R.streamConfig;r.debug(`[Background] reactLoop configuration:`,z),r.debug(`[Background] reactLoop received tool column table:`,i.map(e=>e.function.name),`count:`,i.length),r.debug(`[Background] reactLoop tasktext:`,d?`subtask ${d.subtaskId||` no `} (${d.subtaskName||`maintask`})`:` no `);let Se=0,Ce=``,H=new Map;function U(e,t){try{let n=Date.now();if(typeof f==`function`&&f([...N]),e===Ce&&n-Se<200)return;Se=n,Ce=e;let i=[];for(let e of N){let t=H.get(e.id);(!t||t.status!==e.status||t.nodeName!==e.nodeName)&&(i.push(e),H.set(e.id,{status:e.status,nodeName:e.nodeName}))}let a={type:`EXECUTION_STATUS_UPDATE`,nodeName:e,status:t,callId:h,executionLog:i};u&&(a.sessionId=u),chrome.runtime.sendMessage(a).catch(e=>{r.debug(`[Background] sendexecution statusupdate failed:`,e.message)})}catch(e){r.debug(`[Background] sendexecution statusupdate exception:`,e.message)}}let Te=Date.now(),Ee=0,De=null,W=!1;U(t(`reactLoop.preparing`),`processing`),await I(`initial`,!0);function Oe(){W||(De=Date.now(),W=!0,r.debug(`[Background] overall looptimeoutpaused`))}function ke(){let e=Date.now()-Te;return ge+Ee-e}function Ae(){if(W&&De!==null){let e=Date.now()-De;Ee+=e,De=null,W=!1,r.debug(`[Background] overall looptimeoutrestored,pause duration:`,Math.round(e/1e3),`s,remaining time:`,Math.round(ke()/1e3),`s`)}}me(u||o);try{for(;g<ue;){if(B(o)||u&&B(u))throw Lt(t(`bg.reactCancelled`),N);let e=Date.now()-Te,f=ge+Ee;if(e>f)throw Lt(t(`reactLoop.loopTimeout`,{timeout:ge}),N);g++,de(u);let m=f-e;r.debug(`[Background] ReAct loopstep ${g} times,remaining time: ${Math.round(m/1e3)}s (paused: ${Math.round(Ee/1e3)}s)`);let A,se=Date.now(),F=O(T);for(let e=0;e<F.length-1;e++)F[e]={...F[e],content:w(F[e].content)};let ue=crypto.randomUUID(),me=fe(u),he=i.some(e=>e.function?.name===`plan_task`),_e=i;he&&r.debug(`[Background] current iterationcontains plan_task,using Agent limittool into task decomposition,tool count :`,_e.length);let Se=y(F),Ce=_(Se),we=x(n||R.modelName,0,le.customModelMap),De=S(JSON.stringify(_e.map(e=>{let{id:t,...n}=e;return n}))),W=_(De),ke=Ce+W+4096,G=Se+De,K=E(ke,we);if(K.level!==`safe`&&(r.warn(`[Background] context pressure: ${K.level} (${Math.round(K.ratio*100)}% used, message: ${Ce}, tool: ${W}, estimated total: ${ke}/${we} tokens)`),K.level===`critical`||ke>we*.85)){let e=ie(n||`default`),t=Math.floor(e*.75);r.warn(`[Background] context pressure too high,maindynamictrimmingmessage: current ${Ce} tokens → target budget ${t}`);let i=oe(T,Math.max(t,2e3));if(i.trimmedCount>0){T=i.messages,F=O(T);for(let e=0;e<F.length-1;e++)F[e]={...F[e],content:w(F[e].content)};r.warn(`[Background] maindynamictrimmingcomplete: ${i.trimmedCount} messageremove,remaining ${T.length} , ${y(F)} tokens`)}}N.push({id:ue,iteration:g,globalIteration:me,timestamp:new Date().toISOString(),status:`processing`,nodeType:`api_call`,nodeName:t(`reactLoop.apiCallNode`,{count:me,subtask:d?t(`reactLoop.apiCallSubtask`,{iteration:g}):``}),apiRequest:{messageCount:F.length,toolCount:_e.length}}),U(t(`reactLoop.apiCallNode`,{count:me,subtask:d?t(`reactLoop.apiCallSubtask`,{iteration:g}):``}),`processing`);let je;try{let e=`${R.apiBase}/chat/completions`;r.debug(`[Background] API requesttool count count :`,_e.length);let i={model:n||R.modelName,messages:b(F),tools:_e.map(e=>{let{id:t,...n}=e;return n}),stream:xe.streamEnabled!==!1};i.stream&&(i.stream_options={include_usage:!0}),r.debug(`[Background] API requestbody stream mode:`,i.stream,`tool count count :`,i.tools.length,`messagecount:`,i.messages.length,`model:`,i.model),c.temperature!==void 0&&(i.temperature=c.temperature),c.top_p!==void 0&&(i.top_p=c.top_p);let a=Math.max(m-3e4,pe);je=setTimeout(()=>{r.warn(`[Background] ⚠️ API call outertimeoutprotection triggered (${Math.round(a/1e3)}s),force abort`),ce?.abort()},a),xe.streamEnabled!==!1&&(chrome.runtime.sendMessage({type:`STREAM_START`,sessionId:u,callId:h}).catch(()=>{}),r.debug(`[Background] STREAM_START sent (API call with before )`));let o=await ur(e,{method:`POST`,headers:{Authorization:`Bearer ${R.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify(i),signal:L},pe,z.apiRetryCount,z.apiRetryBaseDelay,(e,t)=>{r.warn(`[Background] API retry ${e} times after :`,t.message)});if(clearTimeout(je),!o.ok){let e=await o.text();throw r.error(`[Background] API response error:`,o.status,e),Error(`HTTP error! status: ${o.status}, message: ${e.substring(0,500)}`)}if(xe.streamEnabled!==!1&&o.body){r.debug(`[Background] enteringstreamingmode,streamEnabled:`,xe.streamEnabled);let e=new ct(u,xe,{callId:h,preStarted:!0}),t=await lt(o.body.getReader(),e,L);r.debug(`[Background] streaming API responsecomplete,content length:`,t.content.length,`tool_calls:`,t.toolCalls?.length,`usage:`,t.usage);let n=t.toolCalls?t.toolCalls.map(e=>({...e,id:e.id||`tc_fb_${crypto.randomUUID().slice(0,8)}`})):null;A={choices:[{message:{role:`assistant`,content:t.content||``,reasoning_content:t.reasoningContent,...n?{tool_calls:n}:{}},finish_reason:t.status===`tool_calls`?`tool_calls`:t.truncated?`length`:`stop`}],usage:t.usage}}else{let e=await o.text();r.debug(`[Background] API responsestate:`,o.status,`originaltext length:`,e.length,`preview:`,e.substring(0,200));try{A=JSON.parse(e)}catch(n){throw r.error(`[Background] JSON parse failed:`,n),r.error(`[Background] originalresponse:`,e),Error(t(`reactLoop.apiInvalidJson`,{status:o.status,error:n.message,preview:e.substring(0,100)}))}let n=A.choices?.[0]?.message?.tool_calls;if(n&&n.length>0){let e=n.map(e=>({...e,id:e.id||`tc_fb_${crypto.randomUUID().slice(0,8)}`}));A.choices[0].message.tool_calls=e}}}catch(e){clearTimeout(je);let i=e.name===`AbortError`;i?r.debug(`[Background] API call with by usercancel`):r.error(`[Background] API call with failed:`,e.message||e);let a=N.findIndex(e=>e.id===ue);throw a!==-1&&(N[a]={...N[a],duration:Date.now()-se,status:i?`cancelled`:`failed`,apiRequest:{...N[a].apiRequest,model:n||R.modelName,temperature:c.temperature,top_p:c.top_p,messageCount:F.length,toolCount:_e.length},error:i?t(`reactLoop.userCancelled`):e.message}),Lt(i?t(`bg.requestCancelled`):e.message,N)}let Me=Date.now()-se,q=A.choices?.[0]?.message;A.choices?.[0]?.finish_reason===`length`&&r.warn(`[Background] API response reason token limit truncated (finish_reason: length),contentmay be incomplete`);let Ne=N.findIndex(e=>e.id===ue);if(Ne!==-1&&(N[Ne]={...N[Ne],duration:Me,status:`success`,thought:q?.content||``,action:q?.tool_calls?.length>0?{name:q.tool_calls[0].function?.name||q.tool_calls[0].name,params:(()=>{try{return JSON.parse(q.tool_calls[0].function?.arguments||`{}`)}catch{return{}}})()}:null,apiRequest:{...N[Ne].apiRequest,model:n||R.modelName,temperature:c.temperature,top_p:c.top_p,messageCount:F.length,toolCount:_e.length},apiResponse:{finishReason:A.choices?.[0]?.finish_reason,tokenUsage:A.usage}}),A.usage&&(yt({sessionId:u,model:n||R.modelName,usage:A.usage,callType:`react_loop`}).catch(()=>{}),G>0&&A.usage.prompt_tokens>0)){ne(G,A.usage.prompt_tokens);let e=te();e.active&&r.debug(`[Background] Tokencalibration activated: factor=${e.factor.toFixed(3)}, samples=${e.samples}`)}if(U(t(`reactLoop.apiCallNode`,{count:me,subtask:d?t(`reactLoop.apiCallSubtask`,{iteration:g}):``}),`success`),q?.tool_calls&&q.tool_calls.length>0){r.debug(`[Background] recei to tool call:`,q.tool_calls);let e=JSON.stringify(q.tool_calls.map(e=>({name:e.function?.name||e.name,args:typeof e.function?.arguments==`string`?(()=>{try{return JSON.parse(e.function.arguments)}catch{return e.function.arguments}})():e.function?.arguments||{}})));r.debug(`[Background] this roundtool callinput fingerprint:`,e.substring(0,200)),T.push(q),await M();let d=[],f=z.reflection;async function m(e,o,u,m,g,_,v,y,b){if(B(o)||_&&B(_))throw Lt(t(`bg.reactCancelled`),y);let x=e.function?.name||e.name,w=Date.now(),T=e.function?.arguments;r.debug(`[Background] executeSingleToolCall recei to tool call:`,JSON.stringify({name:x,argsType:typeof T,argsRaw:typeof T==`string`?T.substring(0,200):JSON.stringify(T).substring(0,200),id:e.id}));let E=(()=>{if(!T)return{};if(typeof T==`object`)return T;try{return JSON.parse(T||`{}`)}catch{return{}}})(),O=e.id||`tc_fallback_${crypto.randomUUID()}`,ee=a.has(x),te=l[x]?.includes(E.action);if((ee||te)&&z.toolConfirmationEnabled)if(_&&Pt.has(_))r.debug(`[Background] session ${_} got currenttaskallow,skip confirm: ${x}`);else{Oe(),chrome.runtime.sendMessage({type:`TOOL_CONFIRM_START`,..._?{sessionId:_}:{}}).catch(e=>{r.debug(`[Background] send TOOL_CONFIRM_START message failed:`,e.message)});let n;try{n=await It(x,E,o,_)}finally{Ae(),chrome.runtime.sendMessage({type:`TOOL_CONFIRM_END`,..._?{sessionId:_}:{}}).catch(e=>{r.debug(`[Background] send TOOL_CONFIRM_END message failed:`,e.message)})}if(!n){let n=crypto.randomUUID();return y.push({id:n,iteration:v,timestamp:new Date().toISOString(),status:`cancelled`,nodeType:`tool_exec`,nodeName:t(`reactLoop.toolExec`,{name:x}),action:{name:x,params:E},error:t(`reactLoop.userDenied`)}),U(t(`reactLoop.toolExec`,{name:x}),`cancelled`),b.push({role:`tool`,content:`The user declined this operation.`,tool_call_id:O}),await M(),{toolCall:e,result:{success:!1,content:`The user declined this operation.`,error:`user_denied`},toolResultStr:`The user declined this operation.`,toolLogEntry:{id:n,iteration:v,timestamp:new Date().toISOString(),status:`cancelled`,nodeType:`tool_exec`,nodeName:t(`reactLoop.toolExec`,{name:x}),action:{name:x,params:E},error:t(`reactLoop.userDenied`)}}}}let k=`${x}:${JSON.stringify(E)}`;if(D.has(k)){let e=D.get(k);if(Date.now()-e.timestamp<6e4){if(s.has(x))return{...e,fromCache:!0};D.clear()}else D.delete(k)}s.has(x)||D.clear(),await new Promise(e=>setTimeout(e,0));let ne=crypto.randomUUID();y.push({id:ne,iteration:v,timestamp:new Date().toISOString(),status:`processing`,nodeType:`tool_exec`,nodeName:t(`reactLoop.toolExecStart`,{name:x})}),U(t(`reactLoop.toolExecStart`,{name:x}),`processing`),x===`clarify_question`&&(Oe(),chrome.runtime.sendMessage({type:`CLARIFY_START`,..._?{sessionId:_}:{}}).catch(e=>{r.debug(`[Background] send CLARIFY_START message failed:`,e.message)}));let A;try{if(A=await qt(e,o,u,m,g,_),x===`clarify_question`){Ae(),chrome.runtime.sendMessage({type:`CLARIFY_END`,..._?{sessionId:_}:{}}).catch(e=>{r.debug(`[Background] send CLARIFY_END message failed:`,e.message)}),r.debug(`[Background] clarification complete,re-filteringtool...`);try{let e=await In(),t=await V(),a=t.reactConfig.enableToolPreselect,o=t.reactConfig.preselectMinToolCount||3;if(a&&e.length>o){let t=await vt(b,n,e,c);t.type===`tools`&&(i=t.tools,j=null,r.debug(`[Background] clarification after toolre-filtercomplete:`,i.map(e=>e.function.name))),t.executionLog&&y.push(...t.executionLog)}else a||r.debug(`[Background] toolpre-filterclosed,after clarification, notre-filter`)}catch(e){r.warn(`[Background] clarification after toolre-filter failed, continue withcurrenttoolset:`,e.message)}}let a;a=typeof A==`string`?A:A&&typeof A==`object`&&`content`in A?A.content??JSON.stringify(A):JSON.stringify(A);let l=A&&A.success!==!1,T=S(a),ee=!1,te=a;if(T>ae){let e=re(a,ae);r.debug(`[Background] tool ${x} result truncated: ${T} → ${S(e)} tokens`),ee=!0,te=e,a=e}be||chrome.runtime.sendMessage({type:`STREAM_TOOL_RESULT`,sessionId:_,result:{toolCallId:O,toolName:x,success:l,content:l?te:A?.error||te,truncated:ee,duration:Date.now()-w}}).catch(()=>{});let ie=y.filter(e=>e.nodeType===`tool_exec`&&e.iteration===v).sort((e,t)=>y.indexOf(e)-y.indexOf(t)),N=0;for(let e=ie.length-1;e>=0&&ie[e].status===`failed`;e--)N++;if(y.filter(e=>e.nodeType===`reflection`&&e.reflectionType===`tool`).length<(f?.toolReflection?.maxPerIteration||2)&&Dt(a,N,f)&&d.push({toolName:x,toolResultStr:a,toolCallParams:E,toolCallId:O,priority:Et(x,a,N)}),x===`plan_task`&&A&&A.success&&A.data){P=A.data,r.debug(`[Background] received taskplanresult:`,JSON.stringify(P));let e=JSON.stringify({success:!0,message:`Task planning complete. Decomposed into ${P.subtasks.length} subtasks.`,data:P});b.push({role:`tool`,content:e,tool_call_id:O}),await M();let a=y.findIndex(e=>e.id===ne);a!==-1&&(y[a]={...y[a],duration:Date.now()-w,status:`success`,nodeName:t(`reactLoop.taskPlanDone`),action:{name:x,params:E},observation:t(`reactLoop.subtaskCount`,{count:P.subtasks.length}),subtaskCount:P.subtasks.length,strategy:P.strategy}),U(t(`reactLoop.taskPlanDone`),`success`);let l=q.tool_calls.findIndex(e=>e.id===O);if(l!==-1&&l<q.tool_calls.length-1){for(let e=l+1;e<q.tool_calls.length;e++){let n=q.tool_calls[e],i=n.function?.name||n.name||`unknown`,a=n.id||`tc_fallback_${crypto.randomUUID()}`;r.debug(`[Background] resend skiptool STREAM_TOOL_RESULT:`,i,`id:`,a),b.push({role:`tool`,content:JSON.stringify({success:!1,message:`Skipped: plan_task has decomposed subtasks; other tool calls in this round will not be executed.`}),tool_call_id:a}),be||chrome.runtime.sendMessage({type:`STREAM_TOOL_RESULT`,sessionId:_,result:{toolCallId:a,toolName:i,success:!1,content:t(`reactLoop.skippedAfterPlanTask`),truncated:!1,duration:0}}).catch(()=>{})}await M()}let u=await Wt(P,n,i,o,c,_,y,p,z.reflection,R,H,h);if(B(o)||_&&B(_))throw Lt(t(`bg.reactCancelled`),y);let d=3e3,f=u.map((e,t)=>{let n=typeof e.result==`string`?e.result:JSON.stringify(e.result),r=S(n)>d?C(n,d):n;return`Subtask ${t+1}: ${e.subtaskName}\nResult: ${r}`}).join(`
97
97
 
98
- `);if(b.push({role:`system`,content:`The following are the execution results of the decomposed subtasks. Please summarize them:\n\n${f}`}),await M(),s.has(x)){if(D.size>=30){let e=D.keys().next().value;D.delete(e)}D.set(k,{planTaskHandled:!0,toolName:x,toolCallId:O,timestamp:Date.now()})}return{planTaskHandled:!0}}b.push({role:`tool`,content:a,tool_call_id:O,subtaskId:null,subtaskName:P?.subtasks[null]?.name||null}),await M(),r.debug(`[Background] toolexec result length:`,a.length,`content preview:`,a.substring(0,200));let oe=y.findIndex(e=>e.id===ne);if(oe!==-1){let e={...y[oe],duration:Date.now()-w,status:l?`success`:`failed`,nodeName:t(`reactLoop.toolExec`,{name:x}),action:{name:x,params:E},observation:l?a.length>500?a.substring(0,500)+`...`:a:void 0,prototypeId:A?.prototypeId||null};!l&&A?.error&&(e.error=A.error),y[oe]=e}if(s.has(x)){if(D.size>=30){let e=D.keys().next().value;D.delete(e)}D.set(k,{planTaskHandled:!1,toolResultStr:a,toolName:x,toolCallId:O,toolResult:A,timestamp:Date.now()})}return{planTaskHandled:!1,toolResultStr:a,toolName:x,toolCallId:O,toolResult:A}}catch(e){r.warn(`[Background] toolexecution failed (ReAct loop continue):`,e.message),x===`clarify_question`&&(Ae(),chrome.runtime.sendMessage({type:`CLARIFY_END`,..._?{sessionId:_}:{}}).catch(e=>{r.debug(`[Background] send CLARIFY_END message failed:`,e.message)}));let n=JSON.stringify({success:!1,error:e.message||`Tool execution error`});b.push({role:`tool`,content:n,tool_call_id:O,subtaskId:null,subtaskName:P?.subtasks[null]?.name||null}),await M();let i=y.findIndex(e=>e.id===ne);return i!==-1&&(y[i]={...y[i],duration:Date.now()-w,status:`failed`,nodeName:t(`reactLoop.toolExec`,{name:x}),action:{name:x,params:E},error:e.message}),r.warn(`[Background] tool ${x} execution failed,ReAct loop continue:`,e.message),U(t(`reactLoop.toolExec`,{name:x}),`failed`),be||chrome.runtime.sendMessage({type:`STREAM_TOOL_RESULT`,sessionId:_,result:{toolCallId:O,toolName:x,success:!1,content:t(`reactLoop.toolError`,{message:e.message}),truncated:!1,duration:Date.now()-w}}).catch(()=>{}),{error:e.message,toolName:x,toolCallId:O,toolResult:{success:!1,error:e.message},toolResultStr:JSON.stringify({success:!1,error:e.message})}}}async function _(){if(d.length===0)return;if(v>=10){r.warn(`[Background] reflectiontotal roundsreached limit,skip toolreflection`);return}d.sort((e,t)=>t.priority-e.priority);let e=f?.toolReflection?.maxPerIteration||2;for(let i of d.slice(0,e)){if(v>=10)break;v++;let e=await jt(i.toolName,i.toolResultStr,i.toolCallParams,R,n,f,N,g,u);if(e){let n={id:crypto.randomUUID(),iteration:g,timestamp:new Date().toISOString(),status:e.useful?`success`:`failed`,nodeType:`reflection`,nodeName:t(`reactLoop.toolReflection`,{name:i.toolName}),reflectionType:`tool`,useful:e.useful,reasoning:e.reasoning,suggestion:e.suggestion};if(N.push(n),r.debug(`[Background] toolreflection: ${i.toolName} - ${e.useful?` has with `:`invalid`} - ${e.reasoning}`),!e.useful&&e.suggestion){let t=`\n\n[Reflection Notice] The result returned by tool "${i.toolName}" was assessed as unhelpful (${e.reasoning}). Suggestion: ${e.suggestion}. Please consider adjusting your strategy in subsequent steps.`;for(let e=T.length-1;e>=0;e--)if(T[e].role===`tool`&&T[e].tool_call_id===i.toolCallId){T[e]={...T[e],content:T[e].content+t};break}}}}}if(q.tool_calls.every(e=>s.has(e.function?.name||e.name))&&q.tool_calls.length>1){r.debug(`[Background] parallel exectool call:`,q.tool_calls.map(e=>e.function?.name||e.name));let e=T.length,t=q.tool_calls.map(e=>m(e,o,ve,ge,ye,u,g,N,T).catch(e=>({error:e.message}))),n=await Promise.all(t),i=T.splice(e),a=new Map(q.tool_calls.map((e,t)=>[e.id,t])),s=i.filter(e=>e.role===`tool`),c=i.filter(e=>e.role!==`tool`);s.sort((e,t)=>(a.get(e.tool_call_id)??999)-(a.get(t.tool_call_id)??999)),T.push(...c,...s);let l=!1;for(let e=0;e<q.tool_calls.length;e++){let t=n[e];t.error&&r.warn(`[Background] parallel toolsexecution failed: ${q.tool_calls[e].function?.name||q.tool_calls[e].name} - ${t.error}`),t.planTaskHandled&&(l=!0)}if(await _(),l){await I(`plan_task_completed`);continue}}else{let e=!1;for(let t=0;t<q.tool_calls.length;t++){let n=q.tool_calls[t];if((await m(n,o,ve,ge,ye,u,g,N,T)).planTaskHandled){e=!0,await _();break}}if(await _(),e){await I(`plan_task_completed`);continue}}let y=[];for(let e=T.length-1;e>=0;e--){let t=T[e];if(t.role===`tool`)y.unshift(t.content);else if(t.role===`assistant`&&t.tool_calls)break}let b=JSON.stringify(q.tool_calls.map((e,t)=>({name:e.function?.name||e.name,args:typeof e.function?.arguments==`string`?(()=>{try{return JSON.parse(e.function.arguments)}catch{return e.function.arguments}})():e.function?.arguments||{},result:y[t]||``})));if(b===ee){k++;let e=q.tool_calls.map(e=>e.function?.name||e.name).join(`, `);if(r.warn(`[Background] detected infiniteloop:input and outputidentical (${k} consecutive repeats): ${e}`),k>=8)throw Lt(t(`reactLoop.infiniteLoopDetected`,{count:k}),N);if(k>=5){let e={role:`user`,content:`[System Notice] You have called the exact same tool with the same parameters ${k} times in a row and received identical results, which indicates the current strategy is making no progress. Please switch to a different strategy or tool immediately and do not repeat this operation. If the current tool cannot obtain the required data, try alternative approaches, or directly provide a conclusion based on the information already available.`};T.push(e),r.debug(`[Background] inject infinite loopwarningmessage`)}}else ee=b,k=1;await I(`tools_completed`);continue}let Pe=q?.content||``,Fe=q?.reasoning_content||null;r.debug(`[Background] ReAct loop complete,finalcontent length:`,Pe.length),await I(`final_answer`),await zt(u);let Ie=z.reflection;if(Ie?.enabled&&Ie?.postReflection?.enabled&&Tt(N,d)){r.debug(`[Background] triggered post-reflection...`);let e=await At(T,Pe,N,n,R,Ie,o,U,p,d,u,v);return e.reflectionLog&&e.reflectionLog.length>0&&N.push(...e.reflectionLog),U(t(`reactLoop.executionDone`),`success`),{content:e.content,executionLog:N,reflectionScore:e.overallScore,wasRevised:e.wasRevised,reasoningContent:Fe}}return U(t(`reactLoop.executionDone`),`success`),{content:Pe,executionLog:N,reasoningContent:Fe}}let e=Error(t(`reactLoop.maxIterationsExceeded`,{maxIterations:ue}));throw e.executionLog=N,e}catch(e){throw await I(e.name===`AbortError`||e.message===`请求已被用户取消`||e.message===`ReAct 循环已被用户取消`?`user_cancelled`:`error`,!0),e}finally{u&&(Nt.delete(u),Pt.delete(u))}}var Ut={DEFAULT_FAILURE_STRATEGY:`continue`,DEFAULT_MAX_RETRIES:1,DEFAULT_MAX_PARALLEL:3};async function Wt(e,n,i,a,o,s,c,l={value:0},u=null,d=null,f=new Map,p=null){let{subtasks:m=[],strategy:h=`sequential`,taskDescription:g,failureStrategy:_=Ut.DEFAULT_FAILURE_STRATEGY,maxRetries:v=Ut.DEFAULT_MAX_RETRIES,maxParallel:y=Ut.DEFAULT_MAX_PARALLEL}=e,b=[],x=[];function S(e,t,n,r={}){let i=[];for(let e of n){let t=f.get(e.id);(!t||t.status!==e.status||t.nodeName!==e.nodeName)&&(i.push(e),f.set(e.id,{status:e.status,nodeName:e.nodeName}))}if(i.length===0)return;let a={type:`EXECUTION_STATUS_UPDATE`,nodeName:e,status:t,executionLog:i,...s?{sessionId:s}:{},...p?{callId:p}:{},...r};r.subtaskTotal!=null&&(a.subtaskTotal=r.subtaskTotal,a.subtaskIndex=r.subtaskIndex,a.subtaskName=r.subtaskName),chrome.runtime.sendMessage(a).catch(e=>{})}r.debug(`[Background] start executing subtask,strategy:`,h,`failedstrategy:`,_,`maxretry:`,v,`count:`,m.length);let C=h===`dependency`?Gt(m):m,w=await Kt(C,i);async function T(){r.debug(`[Background] start rollback completed subtask`);for(let e=x.length-1;e>=0;e--){let{subtask:n,result:i}=x[e];if(typeof n.rollback==`function`)try{r.debug(`[Background] rollback subtask: ${n.name}`),await n.rollback(i),c.push({id:crypto.randomUUID(),iteration:0,timestamp:new Date().toISOString(),status:`rolledback`,nodeType:`subtask`,nodeName:t(`reactLoop.subtaskRolledBack`,{name:n.name}),subtaskId:n.id,subtaskName:n.name}),S(t(`reactLoop.subtaskRolledBack`,{name:n.name}),`rolledback`,c)}catch(e){r.error(`[Background] rollback failed:`,e.message),c.push({id:crypto.randomUUID(),iteration:0,timestamp:new Date().toISOString(),status:`rollback_failed`,nodeType:`subtask`,nodeName:t(`reactLoop.subtaskRollbackFailed`,{name:n.name}),subtaskId:n.id,subtaskName:n.name,error:e.message})}}}async function E(e,i,f){let p=crypto.randomUUID(),m=`subtask_group_${f}`,h=s?`${s}_subtask_${f}`:null;c.push({id:p,iteration:0,timestamp:new Date().toISOString(),status:`processing`,nodeType:`subtask`,nodeName:t(`reactLoop.subtaskNode`,{index:f+1,name:e.name}),subtaskId:e.id,subtaskName:e.name,subtaskIndex:f,taskGroup:m,taskGroupIndex:f+1,taskGroupName:e.name,isSubtask:!0}),S(t(`reactLoop.subtaskNode`,{index:f+1,name:e.name}),`processing`,c,{taskGroup:m,subtaskIndex:f,subtaskTotal:C.length,subtaskName:e.name});for(let _=0;_<=v;_++){if(B(a)||s&&B(s))throw r.debug(`[Background] subtaskretryby usercancel`),Lt(t(`bg.reactCancelled`),c);try{r.debug(`[Background] execute subtask ${f+1}/${C.length}: ${e.name} (attempt ${_+1}/${v+1})`);let y=[{role:`system`,content:`You are executing a subtask. Focus on completing this task and do not ask the user any questions.\n\nTask context: ${g}\n\nCurrent subtask: ${e.description}\n\nYou may use all available tools to complete the task. Choose the appropriate tools based on the actual situation.`},{role:`user`,content:e.description}],b=await Ht(y,n,i,a,o,h,{subtaskId:e.id,subtaskName:e.name},n=>{let r=[...c];n.forEach(t=>{r.push({...t,subtaskId:e.id,subtaskName:e.name,subtaskIndex:f,taskGroup:m,taskGroupIndex:f+1,taskGroupName:e.name,isSubtask:!0})}),S(t(`reactLoop.subtaskNode`,{index:f+1,name:e.name}),`processing`,r,{taskGroup:m,subtaskIndex:f,subtaskTotal:C.length,subtaskName:e.name})},l);b.executionLog&&b.executionLog.length>0&&b.executionLog.forEach(t=>{c.push({...t,subtaskId:e.id,subtaskName:e.name,subtaskIndex:f,taskGroup:m,taskGroupIndex:f+1,taskGroupName:e.name,isSubtask:!0})});let w=c.findIndex(e=>e.id===p);w!==-1&&(c[w]={...c[w],status:`success`,duration:Date.now()-new Date(c[w].timestamp).getTime(),result:b.content.substring(0,200)+(b.content.length>200?`...`:``)}),S(t(`reactLoop.subtaskCompleted`,{index:f+1,name:e.name}),`success`,c,{taskGroup:m,subtaskIndex:f,subtaskTotal:C.length,subtaskName:e.name}),x.push({subtask:e,result:b});let T=b.content,E=null;if(u?.enabled&&u?.subtaskReflection?.enabled){let t=u.subtaskReflection,i=e.complexity===`complex`||b.content.length>500||b.executionLog&&b.executionLog.length>3;if((!t.onlyForComplexSubtasks||i)&&t.maxRounds>0){r.debug(`[Background] subtask ${e.name} trigger reflection,complexity: ${i?`repmisc`:`normal`}`);let o=await Mt(y,b.content,b.executionLog||[],n,d,t,a,e.name,c,s);o.refinedContent&&(T=o.refinedContent,r.debug(`[Background] subtask ${e.name} after reflectionrevise`)),E=o.score,o.reflectionLog&&o.reflectionLog.forEach(t=>{c.push({...t,subtaskId:e.id,subtaskName:e.name,subtaskIndex:f,taskGroup:m,taskGroupIndex:f+1,taskGroupName:e.name,isSubtask:!0})})}}return{success:!0,subtaskId:e.id,subtaskName:e.name,result:T,executionLog:b.executionLog||[],retryCount:_,reflectionScore:E}}catch(n){if(r.warn(`[Background] subtask ${e.name} attempt ${_+1} failed:`,n.message),_>=v){n.executionLog&&n.executionLog.length>0&&n.executionLog.forEach(t=>{c.push({...t,subtaskId:e.id,subtaskName:e.name,subtaskIndex:f,taskGroup:m,taskGroupIndex:f+1,taskGroupName:e.name,isSubtask:!0})});let r=c.findIndex(e=>e.id===p);return r!==-1&&(c[r]={...c[r],status:`failed`,duration:Date.now()-new Date(c[r].timestamp).getTime(),error:n.message,retryCount:_+1}),S(t(`reactLoop.subtaskFailed`,{index:f+1,name:e.name}),`failed`,c,{taskGroup:m,subtaskIndex:f,subtaskTotal:C.length,subtaskName:e.name}),{success:!1,subtaskId:e.id,subtaskName:e.name,result:n.message,executionLog:n.executionLog||[],retryCount:_+1,error:n}}await new Promise(e=>setTimeout(e,1e3*2**_))}}}if(h===`sequential`||h===`dependency`)for(let e=0;e<C.length;e++){if(B(a)||s&&B(s))return r.debug(`[Background] subtaskexec by usercancel`),b;let t=C[e],n=await E(t,w[t.id]||[],e);if(b.push(n),!n.success&&(r.debug(`[Background] subtask ${t.name} failed,failedstrategy: ${_}`),_===`stop`))return r.debug(`[Background] execute rollback`),await T(),b;if(B(a)||s&&B(s))return r.debug(`[Background] subtaskexec by usercancel`),b}else if(h===`parallel`){r.debug(`[Background] parallel executing subtask,max concurrency:`,y);let e=[],t=new Map;for(let n=0;n<C.length;n++){if(B(a)||s&&B(s))return r.debug(`[Background] subtaskparallel execby usercancel`),b;if(e.length>=y){let t=await Promise.race(e),n=e.indexOf(t);n>-1&&e.splice(n,1)}let i=C[n],o=E(i,w[i.id]||[],n).then(e=>(t.set(i.id,e),e));e.push(o)}await Promise.all(e);let n=!1;C.forEach(e=>{let r=t.get(e.id);r&&(b.push(r),r.success||(n=!0))}),n&&_===`stop`&&(r.debug(`[Background] parallel execoccurred failed,execute rollback`),await T())}else return r.warn(`[Background] not knownexec strategy: ${h},downgraded to sequentialexec `),Wt({...e,strategy:`sequential`},n,i,a,o,s,c,l,u,d,f,p);return b}function Gt(e){let t=[],n=new Set,r=new Set;function i(a){if(r.has(a.id))throw Error(`检测到子任务依赖循环`);n.has(a.id)||(r.add(a.id),(a.dependencies||[]).forEach(t=>{let n=e.find(e=>e.id===t);n&&i(n)}),r.delete(a.id),n.add(a.id),t.push(a))}return e.forEach(e=>{n.has(e.id)||i(e)}),t}async function Kt(e,t=null){let n=t||await In(),i=await V().then(e=>e.reactConfig||{}),a=i.enableToolPreselect===!0,o=i.preselectMinToolCount||10,s={},c=[`plan_task`],l=n.filter(e=>!c.includes(e.id));if(l.length<=o)return r.debug(`[Background] subtasktoolfilter:tool count ${l.length} <= ${o},full count inherit (excluded plan_task)`),e.forEach(e=>{s[e.id]=[...l]}),s;let u=[`clarify_question`];return e.forEach(e=>{if(a&&Array.isArray(e.requiredTools)&&e.requiredTools.length>0){let t=l.filter(t=>e.requiredTools.includes(t.id)),n=l.filter(e=>u.includes(e.id));s[e.id]=[...t,...n],r.debug(`[Background] subtask ${e.name} filter tools: ${t.length}/${l.length} (pre-filter mode)`)}else s[e.id]=[...l],r.debug(`[Background] subtask ${e.name} inherit parent task ${l.length} tool (excluded plan_task)`)}),s}async function qt(e,n,i,a,o,s=null){let l=e.function?.name||e.name;if(l===`clarify_question`)return r.debug(`[Background] clarificationtooldirectly execute, no outertimeout (overall looptimeoutpaused)`),rr(e,n,s);let u=c[l],d=u?Math.min(u,i):i;r.debug(`[Background] tool ${l} usingtimeout: ${d}ms${u?` (custom: ${u}ms, globallimit: ${i}ms)`:``}`);let f=xe(s);return new Promise((r,i)=>{let a=setTimeout(()=>{i(Error(t(`reactLoop.toolTimeout`,{timeout:d,tool:l})))},d),o=()=>{clearTimeout(a),i(Error(t(`reactLoop.toolAborted`,{tool:l})))};f&&!f.signal.aborted&&f.signal.addEventListener(`abort`,o,{once:!0}),rr(e,n,s).then(e=>{clearTimeout(a),f&&(f.signal.removeEventListener(`abort`,o),Ce(s)),r(e)}).catch(e=>{clearTimeout(a),f&&(f.signal.removeEventListener(`abort`,o),Ce(s)),i(e)})})}function Jt(e,n,i={},a=null,o={},s=null){return V().then(c=>{i.imageApiBase&&(c.apiBase=i.imageApiBase),i.imageApiKey&&(c.apiKey=i.imageApiKey);let l=(a?he(a):null)?.signal,u=`${c.apiBase}/chat/completions`,d=O(e),f=c.streamConfig?.streamEnabled!==!1;r.debug(`[Background] send API request to :`,u,`streaming:`,f);let p={model:n||c.modelName,messages:b(d),stream:f};return i.temperature!==void 0&&(p.temperature=i.temperature),i.top_p!==void 0&&(p.top_p=i.top_p),f&&a&&(chrome.runtime.sendMessage({type:`STREAM_START`,sessionId:a,callId:s}).catch(()=>{}),r.debug(`[Background] STREAM_START sent (API call with before )`)),ur(u,{method:`POST`,headers:{Authorization:`Bearer ${c.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify(p),signal:l},c.reactConfig.apiTimeout,c.reactConfig.apiRetryCount,c.reactConfig.apiRetryBaseDelay).then(async e=>{if(!e.ok){let t=await e.text();throw r.error(`[Background] API response error:`,e.status,t),Error(`HTTP error! status: ${e.status}, message: ${t.substring(0,500)}`)}if(f&&e.body){let t=new ct(a,c.streamConfig,{...o,callId:s,preStarted:!0}),n=await lt(e.body.getReader(),t,l);return r.debug(`[Background] streaming API responsecomplete,content length:`,n.content.length,`usage:`,n.usage),{content:n.content,usage:n.usage,reasoningContent:n.reasoningContent}}let n=await e.text();r.debug(`[Background] non-streaming API responsestate:`,e.status,`text length:`,n.length,`preview:`,n.substring(0,200));try{let e=JSON.parse(n);return r.debug(`[Background] API response:`,JSON.stringify(e).substring(0,200)),{content:e.choices?.[0]?.message?.content||``,usage:e.usage||null}}catch(i){throw r.error(`[Background] JSON parse failed,originalresponse:`,n.substring(0,500)),Error(t(`reactLoop.jsonParseFailed`,{status:e.status,error:i.message,preview:n.substring(0,100)}))}}).catch(e=>{throw e.name===`AbortError`?r.debug(`[Background] API call with by usercancel`):r.error(`[Background] API call with failed:`,e.message||e),e})})}async function Yt(e){return P.find(t=>t.id===e)||((await chrome.storage.local.get([`customAgents`])).customAgents||[]).find(t=>t.id===e)||null}async function Xt(e,t){let n=e.systemPrompt||``;n.trim()||(n=`You are an AI assistant. Please complete the following task.`);try{let t=``;e.skillIds!=null&&Array.isArray(e.skillIds)&&e.skillIds.length>0?t=(await $e(e.skillIds)).prompts||``:e.skillIds??(t=(await Qe()).prompts||``),t&&(n+=`
98
+ `);if(b.push({role:`system`,content:`The following are the execution results of the decomposed subtasks. Please summarize them:\n\n${f}`}),await M(),s.has(x)){if(D.size>=30){let e=D.keys().next().value;D.delete(e)}D.set(k,{planTaskHandled:!0,toolName:x,toolCallId:O,timestamp:Date.now()})}return{planTaskHandled:!0}}b.push({role:`tool`,content:a,tool_call_id:O,subtaskId:null,subtaskName:P?.subtasks[null]?.name||null}),await M(),r.debug(`[Background] toolexec result length:`,a.length,`content preview:`,a.substring(0,200));let oe=y.findIndex(e=>e.id===ne);if(oe!==-1){let e={...y[oe],duration:Date.now()-w,status:l?`success`:`failed`,nodeName:t(`reactLoop.toolExec`,{name:x}),action:{name:x,params:E},observation:l?a.length>500?a.substring(0,500)+`...`:a:void 0,prototypeId:A?.prototypeId||null};!l&&A?.error&&(e.error=A.error),y[oe]=e}if(s.has(x)){if(D.size>=30){let e=D.keys().next().value;D.delete(e)}D.set(k,{planTaskHandled:!1,toolResultStr:a,toolName:x,toolCallId:O,toolResult:A,timestamp:Date.now()})}return{planTaskHandled:!1,toolResultStr:a,toolName:x,toolCallId:O,toolResult:A}}catch(e){r.warn(`[Background] toolexecution failed (ReAct loop continue):`,e.message),x===`clarify_question`&&(Ae(),chrome.runtime.sendMessage({type:`CLARIFY_END`,..._?{sessionId:_}:{}}).catch(e=>{r.debug(`[Background] send CLARIFY_END message failed:`,e.message)}));let n=JSON.stringify({success:!1,error:e.message||`Tool execution error`});b.push({role:`tool`,content:n,tool_call_id:O,subtaskId:null,subtaskName:P?.subtasks[null]?.name||null}),await M();let i=y.findIndex(e=>e.id===ne);return i!==-1&&(y[i]={...y[i],duration:Date.now()-w,status:`failed`,nodeName:t(`reactLoop.toolExec`,{name:x}),action:{name:x,params:E},error:e.message}),r.warn(`[Background] tool ${x} execution failed,ReAct loop continue:`,e.message),U(t(`reactLoop.toolExec`,{name:x}),`failed`),be||chrome.runtime.sendMessage({type:`STREAM_TOOL_RESULT`,sessionId:_,result:{toolCallId:O,toolName:x,success:!1,content:t(`reactLoop.toolError`,{message:e.message}),truncated:!1,duration:Date.now()-w}}).catch(()=>{}),{error:e.message,toolName:x,toolCallId:O,toolResult:{success:!1,error:e.message},toolResultStr:JSON.stringify({success:!1,error:e.message})}}}async function _(){if(d.length===0)return;if(v>=10){r.warn(`[Background] reflectiontotal roundsreached limit,skip toolreflection`);return}d.sort((e,t)=>t.priority-e.priority);let e=f?.toolReflection?.maxPerIteration||2;for(let i of d.slice(0,e)){if(v>=10)break;v++;let e=await jt(i.toolName,i.toolResultStr,i.toolCallParams,R,n,f,N,g,u);if(e){let n={id:crypto.randomUUID(),iteration:g,timestamp:new Date().toISOString(),status:e.useful?`success`:`failed`,nodeType:`reflection`,nodeName:t(`reactLoop.toolReflection`,{name:i.toolName}),reflectionType:`tool`,useful:e.useful,reasoning:e.reasoning,suggestion:e.suggestion};if(N.push(n),r.debug(`[Background] toolreflection: ${i.toolName} - ${e.useful?` has with `:`invalid`} - ${e.reasoning}`),!e.useful&&e.suggestion){let t=`\n\n[Reflection Notice] The result returned by tool "${i.toolName}" was assessed as unhelpful (${e.reasoning}). Suggestion: ${e.suggestion}. Please consider adjusting your strategy in subsequent steps.`;for(let e=T.length-1;e>=0;e--)if(T[e].role===`tool`&&T[e].tool_call_id===i.toolCallId){T[e]={...T[e],content:T[e].content+t};break}}}}}if(q.tool_calls.every(e=>s.has(e.function?.name||e.name))&&q.tool_calls.length>1){r.debug(`[Background] parallel exectool call:`,q.tool_calls.map(e=>e.function?.name||e.name));let e=T.length,t=q.tool_calls.map(e=>m(e,o,ve,ge,ye,u,g,N,T).catch(e=>({error:e.message}))),n=await Promise.all(t),i=T.splice(e),a=new Map(q.tool_calls.map((e,t)=>[e.id,t])),s=i.filter(e=>e.role===`tool`),c=i.filter(e=>e.role!==`tool`);s.sort((e,t)=>(a.get(e.tool_call_id)??999)-(a.get(t.tool_call_id)??999)),T.push(...c,...s);let l=!1;for(let e=0;e<q.tool_calls.length;e++){let t=n[e];t.error&&r.warn(`[Background] parallel toolsexecution failed: ${q.tool_calls[e].function?.name||q.tool_calls[e].name} - ${t.error}`),t.planTaskHandled&&(l=!0)}if(await _(),l){await I(`plan_task_completed`);continue}}else{let e=!1;for(let t=0;t<q.tool_calls.length;t++){let n=q.tool_calls[t];if((await m(n,o,ve,ge,ye,u,g,N,T)).planTaskHandled){e=!0,await _();break}}if(await _(),e){await I(`plan_task_completed`);continue}}let y=[];for(let e=T.length-1;e>=0;e--){let t=T[e];if(t.role===`tool`)y.unshift(t.content);else if(t.role===`assistant`&&t.tool_calls)break}let b=JSON.stringify(q.tool_calls.map((e,t)=>({name:e.function?.name||e.name,args:typeof e.function?.arguments==`string`?(()=>{try{return JSON.parse(e.function.arguments)}catch{return e.function.arguments}})():e.function?.arguments||{},result:y[t]||``})));if(b===ee){k++;let e=q.tool_calls.map(e=>e.function?.name||e.name).join(`, `);if(r.warn(`[Background] detected infiniteloop:input and outputidentical (${k} consecutive repeats): ${e}`),k>=8)throw Lt(t(`reactLoop.infiniteLoopDetected`,{count:k}),N);if(k>=5){let e={role:`user`,content:`[System Notice] You have called the exact same tool with the same parameters ${k} times in a row and received identical results, which indicates the current strategy is making no progress. Please switch to a different strategy or tool immediately and do not repeat this operation. If the current tool cannot obtain the required data, try alternative approaches, or directly provide a conclusion based on the information already available.`};T.push(e),r.debug(`[Background] inject infinite loopwarningmessage`)}}else ee=b,k=1;await I(`tools_completed`);continue}let Pe=q?.content||``,Fe=q?.reasoning_content||null;r.debug(`[Background] ReAct loop complete,finalcontent length:`,Pe.length),await I(`final_answer`),await zt(u);let Ie=z.reflection;if(Ie?.enabled&&Ie?.postReflection?.enabled&&Tt(N,d)){r.debug(`[Background] triggered post-reflection...`);let e=await At(T,Pe,N,n,R,Ie,o,U,p,d,u,v);return e.reflectionLog&&e.reflectionLog.length>0&&N.push(...e.reflectionLog),U(t(`reactLoop.executionDone`),`success`),{content:e.content,executionLog:N,reflectionScore:e.overallScore,wasRevised:e.wasRevised,reasoningContent:Fe}}return U(t(`reactLoop.executionDone`),`success`),{content:Pe,executionLog:N,reasoningContent:Fe}}let e=Error(t(`reactLoop.maxIterationsExceeded`,{maxIterations:ue}));throw e.executionLog=N,e}catch(e){throw await I(e.name===`AbortError`||e.message===`请求已被用户取消`||e.message===`ReAct 循环已被用户取消`?`user_cancelled`:`error`,!0),e}finally{u&&(Nt.delete(u),Pt.delete(u))}}var Ut={DEFAULT_FAILURE_STRATEGY:`continue`,DEFAULT_MAX_RETRIES:1,DEFAULT_MAX_PARALLEL:3};async function Wt(e,n,i,a,o,s,c,l={value:0},u=null,d=null,f=new Map,p=null){let{subtasks:m=[],strategy:h=`sequential`,taskDescription:g,failureStrategy:_=Ut.DEFAULT_FAILURE_STRATEGY,maxRetries:v=Ut.DEFAULT_MAX_RETRIES,maxParallel:y=Ut.DEFAULT_MAX_PARALLEL}=e,b=[],x=[];function S(e,t,n,r={}){let i=[];for(let e of n){let t=f.get(e.id);(!t||t.status!==e.status||t.nodeName!==e.nodeName)&&(i.push(e),f.set(e.id,{status:e.status,nodeName:e.nodeName}))}if(i.length===0)return;let a={type:`EXECUTION_STATUS_UPDATE`,nodeName:e,status:t,executionLog:i,...s?{sessionId:s}:{},...p?{callId:p}:{},...r};r.subtaskTotal!=null&&(a.subtaskTotal=r.subtaskTotal,a.subtaskIndex=r.subtaskIndex,a.subtaskName=r.subtaskName),chrome.runtime.sendMessage(a).catch(e=>{})}r.debug(`[Background] start executing subtask,strategy:`,h,`failedstrategy:`,_,`maxretry:`,v,`count:`,m.length);let C=h===`dependency`?Gt(m):m,w=await Kt(C,i);async function T(){r.debug(`[Background] start rollback completed subtask`);for(let e=x.length-1;e>=0;e--){let{subtask:n,result:i}=x[e];if(typeof n.rollback==`function`)try{r.debug(`[Background] rollback subtask: ${n.name}`),await n.rollback(i),c.push({id:crypto.randomUUID(),iteration:0,timestamp:new Date().toISOString(),status:`rolledback`,nodeType:`subtask`,nodeName:t(`reactLoop.subtaskRolledBack`,{name:n.name}),subtaskId:n.id,subtaskName:n.name}),S(t(`reactLoop.subtaskRolledBack`,{name:n.name}),`rolledback`,c)}catch(e){r.error(`[Background] rollback failed:`,e.message),c.push({id:crypto.randomUUID(),iteration:0,timestamp:new Date().toISOString(),status:`rollback_failed`,nodeType:`subtask`,nodeName:t(`reactLoop.subtaskRollbackFailed`,{name:n.name}),subtaskId:n.id,subtaskName:n.name,error:e.message})}}}async function E(e,i,f){let p=crypto.randomUUID(),m=`subtask_group_${f}`,h=s?`${s}_subtask_${f}`:null;c.push({id:p,iteration:0,timestamp:new Date().toISOString(),status:`processing`,nodeType:`subtask`,nodeName:t(`reactLoop.subtaskNode`,{index:f+1,name:e.name}),subtaskId:e.id,subtaskName:e.name,subtaskIndex:f,taskGroup:m,taskGroupIndex:f+1,taskGroupName:e.name,isSubtask:!0}),S(t(`reactLoop.subtaskNode`,{index:f+1,name:e.name}),`processing`,c,{taskGroup:m,subtaskIndex:f,subtaskTotal:C.length,subtaskName:e.name});for(let _=0;_<=v;_++){if(B(a)||s&&B(s))throw r.debug(`[Background] subtaskretryby usercancel`),Lt(t(`bg.reactCancelled`),c);try{r.debug(`[Background] execute subtask ${f+1}/${C.length}: ${e.name} (attempt ${_+1}/${v+1})`);let y=[{role:`system`,content:`You are executing a subtask. Focus on completing this task and do not ask the user any questions.\n\nTask context: ${g}\n\nCurrent subtask: ${e.description}\n\nYou may use all available tools to complete the task. Choose the appropriate tools based on the actual situation.`},{role:`user`,content:e.description}],b=await Ht(y,n,i,a,o,h,{subtaskId:e.id,subtaskName:e.name},n=>{let r=[...c];n.forEach(t=>{r.push({...t,subtaskId:e.id,subtaskName:e.name,subtaskIndex:f,taskGroup:m,taskGroupIndex:f+1,taskGroupName:e.name,isSubtask:!0})}),S(t(`reactLoop.subtaskNode`,{index:f+1,name:e.name}),`processing`,r,{taskGroup:m,subtaskIndex:f,subtaskTotal:C.length,subtaskName:e.name})},l);b.executionLog&&b.executionLog.length>0&&b.executionLog.forEach(t=>{c.push({...t,subtaskId:e.id,subtaskName:e.name,subtaskIndex:f,taskGroup:m,taskGroupIndex:f+1,taskGroupName:e.name,isSubtask:!0})});let w=c.findIndex(e=>e.id===p);w!==-1&&(c[w]={...c[w],status:`success`,duration:Date.now()-new Date(c[w].timestamp).getTime(),result:b.content.substring(0,200)+(b.content.length>200?`...`:``)}),S(t(`reactLoop.subtaskCompleted`,{index:f+1,name:e.name}),`success`,c,{taskGroup:m,subtaskIndex:f,subtaskTotal:C.length,subtaskName:e.name}),x.push({subtask:e,result:b});let T=b.content,E=null;if(u?.enabled&&u?.subtaskReflection?.enabled){let t=u.subtaskReflection,i=e.complexity===`complex`||b.content.length>500||b.executionLog&&b.executionLog.length>3;if((!t.onlyForComplexSubtasks||i)&&t.maxRounds>0){r.debug(`[Background] subtask ${e.name} trigger reflection,complexity: ${i?`repmisc`:`normal`}`);let o=await Mt(y,b.content,b.executionLog||[],n,d,t,a,e.name,c,s);o.refinedContent&&(T=o.refinedContent,r.debug(`[Background] subtask ${e.name} after reflectionrevise`)),E=o.score,o.reflectionLog&&o.reflectionLog.forEach(t=>{c.push({...t,subtaskId:e.id,subtaskName:e.name,subtaskIndex:f,taskGroup:m,taskGroupIndex:f+1,taskGroupName:e.name,isSubtask:!0})})}}return{success:!0,subtaskId:e.id,subtaskName:e.name,result:T,executionLog:b.executionLog||[],retryCount:_,reflectionScore:E}}catch(n){if(r.warn(`[Background] subtask ${e.name} attempt ${_+1} failed:`,n.message),_>=v){n.executionLog&&n.executionLog.length>0&&n.executionLog.forEach(t=>{c.push({...t,subtaskId:e.id,subtaskName:e.name,subtaskIndex:f,taskGroup:m,taskGroupIndex:f+1,taskGroupName:e.name,isSubtask:!0})});let r=c.findIndex(e=>e.id===p);return r!==-1&&(c[r]={...c[r],status:`failed`,duration:Date.now()-new Date(c[r].timestamp).getTime(),error:n.message,retryCount:_+1}),S(t(`reactLoop.subtaskFailed`,{index:f+1,name:e.name}),`failed`,c,{taskGroup:m,subtaskIndex:f,subtaskTotal:C.length,subtaskName:e.name}),{success:!1,subtaskId:e.id,subtaskName:e.name,result:n.message,executionLog:n.executionLog||[],retryCount:_+1,error:n}}await new Promise(e=>setTimeout(e,1e3*2**_))}}}if(h===`sequential`||h===`dependency`)for(let e=0;e<C.length;e++){if(B(a)||s&&B(s))return r.debug(`[Background] subtaskexec by usercancel`),b;let t=C[e],n=await E(t,w[t.id]||[],e);if(b.push(n),!n.success&&(r.debug(`[Background] subtask ${t.name} failed,failedstrategy: ${_}`),_===`stop`))return r.debug(`[Background] execute rollback`),await T(),b;if(B(a)||s&&B(s))return r.debug(`[Background] subtaskexec by usercancel`),b}else if(h===`parallel`){r.debug(`[Background] parallel executing subtask,max concurrency:`,y);let e=[],t=new Map;for(let n=0;n<C.length;n++){if(B(a)||s&&B(s))return r.debug(`[Background] subtaskparallel execby usercancel`),b;if(e.length>=y){let t=await Promise.race(e),n=e.indexOf(t);n>-1&&e.splice(n,1)}let i=C[n],o=E(i,w[i.id]||[],n).then(e=>(t.set(i.id,e),e));e.push(o)}await Promise.all(e);let n=!1;C.forEach(e=>{let r=t.get(e.id);r&&(b.push(r),r.success||(n=!0))}),n&&_===`stop`&&(r.debug(`[Background] parallel execoccurred failed,execute rollback`),await T())}else return r.warn(`[Background] not knownexec strategy: ${h},downgraded to sequentialexec `),Wt({...e,strategy:`sequential`},n,i,a,o,s,c,l,u,d,f,p);return b}function Gt(e){let t=[],n=new Set,r=new Set;function i(a){if(r.has(a.id))throw Error(`检测到子任务依赖循环`);n.has(a.id)||(r.add(a.id),(a.dependencies||[]).forEach(t=>{let n=e.find(e=>e.id===t);n&&i(n)}),r.delete(a.id),n.add(a.id),t.push(a))}return e.forEach(e=>{n.has(e.id)||i(e)}),t}async function Kt(e,t=null){let n=t||await In(),i=await V().then(e=>e.reactConfig||{}),a=i.enableToolPreselect===!0,o=i.preselectMinToolCount||10,s={},c=[`plan_task`],l=n.filter(e=>!c.includes(e.id));if(l.length<=o)return r.debug(`[Background] subtasktoolfilter:tool count ${l.length} <= ${o},full count inherit (excluded plan_task)`),e.forEach(e=>{s[e.id]=[...l]}),s;let u=[`clarify_question`];return e.forEach(e=>{if(a&&Array.isArray(e.requiredTools)&&e.requiredTools.length>0){let t=l.filter(t=>e.requiredTools.includes(t.id)),n=l.filter(e=>u.includes(e.id));s[e.id]=[...t,...n],r.debug(`[Background] subtask ${e.name} filter tools: ${t.length}/${l.length} (pre-filter mode)`)}else s[e.id]=[...l],r.debug(`[Background] subtask ${e.name} inherit parent task ${l.length} tool (excluded plan_task)`)}),s}async function qt(e,n,i,a,o,s=null){let l=e.function?.name||e.name;if(l===`clarify_question`)return r.debug(`[Background] clarificationtooldirectly execute, no outertimeout (overall looptimeoutpaused)`),rr(e,n,s);let u=c[l],d=u?Math.min(u,i):i;r.debug(`[Background] tool ${l} usingtimeout: ${d}ms${u?` (custom: ${u}ms, globallimit: ${i}ms)`:``}`);let f=xe(s);return new Promise((r,i)=>{let a=setTimeout(()=>{i(Error(t(`reactLoop.toolTimeout`,{timeout:d,tool:l})))},d),o=()=>{clearTimeout(a),i(Error(t(`reactLoop.toolAborted`,{tool:l})))};f&&!f.signal.aborted&&f.signal.addEventListener(`abort`,o,{once:!0}),rr(e,n,s).then(e=>{clearTimeout(a),f&&(f.signal.removeEventListener(`abort`,o),Ce(s)),r(e)}).catch(e=>{clearTimeout(a),f&&(f.signal.removeEventListener(`abort`,o),Ce(s)),i(e)})})}function Jt(e,n,i={},a=null,o={},s=null){return V().then(c=>{i.imageApiBase&&(c.apiBase=i.imageApiBase),i.imageApiKey&&(c.apiKey=i.imageApiKey);let l=(a?he(a):null)?.signal,u=`${c.apiBase}/chat/completions`,d=O(e),f=c.streamConfig?.streamEnabled!==!1;r.debug(`[Background] send API request to :`,u,`streaming:`,f);let p={model:n||c.modelName,messages:b(d),stream:f};return f&&(p.stream_options={include_usage:!0}),i.temperature!==void 0&&(p.temperature=i.temperature),i.top_p!==void 0&&(p.top_p=i.top_p),f&&a&&(chrome.runtime.sendMessage({type:`STREAM_START`,sessionId:a,callId:s}).catch(()=>{}),r.debug(`[Background] STREAM_START sent (API call with before )`)),ur(u,{method:`POST`,headers:{Authorization:`Bearer ${c.apiKey}`,"Content-Type":`application/json`},body:JSON.stringify(p),signal:l},c.reactConfig.apiTimeout,c.reactConfig.apiRetryCount,c.reactConfig.apiRetryBaseDelay).then(async e=>{if(!e.ok){let t=await e.text();throw r.error(`[Background] API response error:`,e.status,t),Error(`HTTP error! status: ${e.status}, message: ${t.substring(0,500)}`)}if(f&&e.body){let t=new ct(a,c.streamConfig,{...o,callId:s,preStarted:!0}),n=await lt(e.body.getReader(),t,l);return r.debug(`[Background] streaming API responsecomplete,content length:`,n.content.length,`usage:`,n.usage),{content:n.content,usage:n.usage,reasoningContent:n.reasoningContent}}let n=await e.text();r.debug(`[Background] non-streaming API responsestate:`,e.status,`text length:`,n.length,`preview:`,n.substring(0,200));try{let e=JSON.parse(n);return r.debug(`[Background] API response:`,JSON.stringify(e).substring(0,200)),{content:e.choices?.[0]?.message?.content||``,usage:e.usage||null}}catch(i){throw r.error(`[Background] JSON parse failed,originalresponse:`,n.substring(0,500)),Error(t(`reactLoop.jsonParseFailed`,{status:e.status,error:i.message,preview:n.substring(0,100)}))}}).catch(e=>{throw e.name===`AbortError`?r.debug(`[Background] API call with by usercancel`):r.error(`[Background] API call with failed:`,e.message||e),e})})}async function Yt(e){return P.find(t=>t.id===e)||((await chrome.storage.local.get([`customAgents`])).customAgents||[]).find(t=>t.id===e)||null}async function Xt(e,t){let n=e.systemPrompt||``;n.trim()||(n=`You are an AI assistant. Please complete the following task.`);try{let t=``;e.skillIds!=null&&Array.isArray(e.skillIds)&&e.skillIds.length>0?t=(await $e(e.skillIds)).prompts||``:e.skillIds??(t=(await Qe()).prompts||``),t&&(n+=`
99
99
 
100
100
  `+t)}catch{}return`${n}
101
101
 
@@ -328,5 +328,5 @@ stderr:
328
328
 
329
329
  `+r+(u.total>30?t(`toolExec.matchListLimitHint`,{count:30}):``),tool_call_id:n}}return{success:!1,error:u.error,tool_call_id:n}}var Vr=null;async function Hr(){let e=chrome.runtime.getURL(`offscreen/offscreen.html`);if(!((await chrome.runtime.getContexts({contextTypes:[`OFFSCREEN_DOCUMENT`],documentUrls:[e]})).length>0)){if(Vr){await Vr;return}Vr=chrome.offscreen.createDocument({url:`offscreen/offscreen.html`,reasons:[`CLIPBOARD`],justification:`用于读写系统剪贴板内容`});try{await Vr}finally{Vr=null}}}async function Ur(e,n,r,i){let{format:a=`text`,selector:o,maxLength:s=15e3,tabId:c}=e,l={text:`GET_PAGE_TEXT`,html:`GET_FULL_HTML`}[a];if(!l)return{success:!1,error:`不支持的格式: ${a},可选: text, html`,tool_call_id:n};try{let e=r?be(r):null,i=c||e||await Gn();return i?await Kn(i,{type:l,selector:o,maxLength:s},n):{success:!1,error:t(`toolExec.noTabAvailable`),tool_call_id:n}}catch(e){return{success:!1,error:e.message,tool_call_id:n}}}async function Wr(e,n,r,i){let{dataType:a,selector:o,filterType:s=`all`,includeHeaders:c=!0,format:l=`json`,includeImages:u=!1,minWidth:d=0,minHeight:f=0,maxResults:p=100,tabId:m}=e;if(!a)return{success:!1,error:t(`toolExec.missingDataType`),tool_call_id:n};let h={table:`EXTRACT_TABLE`,metadata:`EXTRACT_METADATA`,links:`EXTRACT_LINKS`,forms:`EXTRACT_FORMS`,images:`EXTRACT_IMAGES`}[a];if(!h)return{success:!1,error:`不支持的数据类型: ${a},可选: table, metadata, links, forms, images`,tool_call_id:n};try{let e=r?be(r):null,i=m||e||await Gn();return i?await Kn(i,{type:h,selector:o,filterType:s,includeHeaders:c,format:l,includeImages:u,minWidth:d,minHeight:f,maxResults:p},n):{success:!1,error:t(`toolExec.noTabAvailable`),tool_call_id:n}}catch(e){return{success:!1,error:e.message,tool_call_id:n}}}async function Gr(e,n){let{action:r,text:i,format:a=`text`}=e;if(!r)return{success:!1,error:t(`toolExec.missingAction`),tool_call_id:n};if(r===`copy`)return Kr({text:i},n);if(r===`paste`)return qr({},n);if(r===`get_selected`)try{let e=await Gn();return e?await Kn(e,{type:`GET_SELECTED_CONTENT`,format:a},n):{success:!1,error:t(`toolExec.noTabAvailable`),tool_call_id:n}}catch(e){return{success:!1,error:e.message,tool_call_id:n}}return{success:!1,error:`不支持的操作: ${r},可选: copy, paste, get_selected`,tool_call_id:n}}async function Kr(e,n){let{text:r}=e;if(r==null)return{success:!1,error:t(`toolExec.missingText`),tool_call_id:n};try{await Hr();let e=await chrome.runtime.sendMessage({type:`COPY_TO_CLIPBOARD`,text:r});return e?.success?{success:!0,message:e.message||t(`toolExec.copiedToClipboard`),tool_call_id:n}:{success:!1,error:e?.error||t(`toolExec.copyFailed`),tool_call_id:n}}catch(e){return{success:!1,error:e.message,tool_call_id:n}}}async function qr(e,t){try{await Hr();let e=await chrome.runtime.sendMessage({type:`PASTE_FROM_CLIPBOARD`});return e?.success?{success:!0,text:e.text,tool_call_id:t}:{success:!1,error:e?.error||`粘贴失败`,tool_call_id:t}}catch(e){return{success:!1,error:e.message,tool_call_id:t}}}async function Jr(e,t=`kill`){console.log(`[Background] cancelrunning Agent command,sessionId:`,e,`mode:`,t),_n.add(e);let n=X.get(e);if(!n){console.warn(`[Background] runningAgentCommands not found entry:`,e),setTimeout(()=>{_n.delete(e)},3e3);return}let{execId:r,ws:i,resolve:a,toolCallId:o}=n;console.log(`[Background] find to runningcommand,execId:`,r),X.delete(e),J(e,r,o,-1),a&&(a(),console.log(`[Background] Promise direct resolve,task continuesexec `));try{i.close()}catch{}t===`kill`?Ve(r).then(()=>{console.log(`[Background] stopped Agent command process:`,r)}).catch(e=>{console.warn(`[Background] stop Agent command process failed:`,e.message)}):console.log(`[Background] only disconnect WebSocket,command process continuesrun :`,r),setTimeout(()=>{_n.delete(e)},3e3)}async function Yr(e,n){try{let e=await Oe(),r=await ke(),i=[];for(let t of e){let e=Te(t.id);i.push({id:t.id,name:t.name,url:t.url,reachable:e,disabled:t.disabled||!1,isActive:r?.id===t.id})}return{success:!0,content:t(`toolExec.agentListContent`,{summary:i.map(e=>{let n=e.disabled?t(`toolExec.agentStatusDisabled`):e.reachable===!0?t(`toolExec.agentStatusOnline`):e.reachable===!1?t(`toolExec.agentStatusOffline`):t(`toolExec.agentStatusUnknown`),r=e.isActive?t(`toolExec.agentStatusActive`):``;return`- ${e.name} (${e.id}): ${n}${r}`}).join(`
330
330
  `),data:JSON.stringify(i,null,2)}),agents:i,activeAgentId:r?.id||null,tool_call_id:n}}catch(e){return{success:!1,error:t(`toolExec.agentListFailed`,{error:e.message}),tool_call_id:n}}}async function Xr(e,n){let{agentId:r,agentName:i}=e;if(!r&&!i)return{success:!1,error:t(`toolExec.missingAgentId`),tool_call_id:n};try{let e=await Oe(),a;if(r&&(a=e.find(e=>e.id===r)),!a&&i&&(a=e.find(e=>e.name===i),a||=e.find(e=>e.name&&e.name.toLowerCase().includes(i.toLowerCase()))),!a){let a=e.map(e=>`- ${e.name} (${e.id})`).join(`
331
- `);return{success:!1,error:t(`toolExec.agentNotFound`,{id:r||i,list:a}),tool_call_id:n}}if(a.disabled)return{success:!1,error:t(`toolExec.agentDisabled`,{name:a.name}),tool_call_id:n};if(!await Ae(a.id))return{success:!1,error:t(`toolExec.agentSwitchFailedSimple`,{name:a.name}),tool_call_id:n};let o=Te(a.id),s=o===!0?``:t(`toolExec.agentOfflineWarning`);return{success:!0,content:t(`toolExec.agentSwitchSuccess`,{name:a.name,id:a.id,warning:s}),agentId:a.id,agentName:a.name,offline:o!==!0,tool_call_id:n}}catch(e){return{success:!1,error:t(`toolExec.agentSwitchFailed`,{error:e.message}),tool_call_id:n}}}e(`zh`,{bg:{missingSessionId:`缺少 sessionId`,resumingFromCheckpoint:`从 checkpoint 恢复中...`,checkpointNotFound:`未找到可恢复的任务 checkpoint,可能已过期或被清理。请检查 Service Worker 控制台中的诊断日志(搜索 "checkpoint" 关键字)。`,resumeFailed:`恢复失败`,missingSkillName:`缺少技能名称`,fetchFailed:`获取失败`,preparing:`准备中...`,toolPreselect:`工具预筛选`,requestCancelled:`请求已被用户取消`,reactCancelled:`ReAct 循环已被用户取消`,apiCallFailed:`API 调用失败`}}),e(`en`,{bg:{missingSessionId:`Missing sessionId`,resumingFromCheckpoint:`Resuming from checkpoint...`,checkpointNotFound:`No checkpoint found for resumption. It may have expired or been cleaned. Check Service Worker console logs (search "checkpoint").`,resumeFailed:`Resume failed`,missingSkillName:`Missing skill name`,fetchFailed:`Fetch failed`,preparing:`Preparing...`,toolPreselect:`Tool Pre-filter`,requestCancelled:`Request was cancelled by user`,reactCancelled:`ReAct loop was cancelled by user`}}),n(),Promise.all([j().then(()=>F()),De()]).then(([e,t])=>{r.debug(`[Background] DB self-check passed,current has ${e.length} checkpoint`+(t?`,completedoldformat Agent migrate`:``))}).catch(e=>{r.warn(`[Background] cleanup expired checkpoint or DB self-check failed:`,e)});var Zr=1e3,$=null,Qr=null,$r=new Map;chrome.runtime.onConnect.addListener(async e=>{if(e.name?.startsWith(`keepalive-`)){let t=e.name.replace(`keepalive-`,``),n=$r.has(t);if($r.set(t,e),r.debug(`[Background] keepalive portconnected, sessionId:`,t,n?`(reconnect)`:`(first times)`),n&&!Nt.has(t)){r.warn(`[Background] ⚠️ detected SW re started,sessionId`,t,` API call lost`);let n=null;try{let e=await I(t);e&&(n={iteration:e.iteration,interruptedReason:e.interruptedReason,updatedAt:e.updatedAt,messageCount:e.currentMessages?.length||0,subtaskPlan:e.subtaskPlan?{subtaskCount:e.subtaskPlan.subtasks?.length||0}:null},r.debug(`[Background] detected recoverable checkpoint:`,n))}catch(e){r.warn(`[Background] read checkpoint failed:`,e.message)}try{e.postMessage({type:`SW_RESTARTED`,sessionId:t,checkpoint:n})}catch(e){r.warn(`[Background] send SW_RESTARTED message failed:`,e.message)}}e.onDisconnect.addListener(()=>{$r.delete(t),r.debug(`[Background] keepalive port disconnected, sessionId:`,t)})}}),chrome.sidePanel?.setPanelBehavior?.({openPanelOnActionClick:!0}),chrome.tabs.onUpdated.addListener((e,t,n)=>{t.status===`complete`&&n.url?.startsWith(`http`)&&chrome.sidePanel?.setOptions?.({enabled:!0})}),chrome.commands?.onCommand?.addListener(e=>{if(e===`_toggle_sidepanel`)try{chrome.extension.getViews({type:`side_panel`}).length>0?chrome.runtime.sendMessage({type:`CLOSE_SIDEPANEL`}).catch(e=>{r.warn(`[Background] send CLOSE_SIDEPANEL failed:`,e?.message)}):chrome.sidePanel?.open?.().catch(e=>{r.warn(`[Background] open sidePanel failed:`,e?.message)})}catch(e){r.warn(`[Background] toggle sidePanel exception:`,e?.message)}}),chrome.runtime.onMessage.addListener((e,n,i)=>{if(e.type===`IFRAME_SELECTION`){let t=n.tab?.id;return t&&chrome.tabs.sendMessage(t,{type:`IFRAME_SELECTION`,text:e.text,x:e.x,y:e.y},{frameId:0}).catch(()=>{}),!1}if(e.type===`IFRAME_CLICK_DISMISS`){let e=n.tab?.id;return e&&chrome.tabs.sendMessage(e,{type:`IFRAME_CLICK_DISMISS`}).catch(()=>{}),!1}if(e.type===`IFRAME_SELECTION_CLEAR`){let e=n.tab?.id;return e&&chrome.tabs.sendMessage(e,{type:`IFRAME_SELECTION_CLEAR`}).catch(()=>{}),!1}if(e.type===`CANCEL_REACT`){let{tabId:t,sessionId:n}=e;return n?(pe(n),Jr(n)):pe(t),!1}if(e.type===`GET_CHECKPOINT`){let{sessionId:t}=e;return t?(I(t).then(e=>{if(!e){i({exists:!1});return}i({exists:!0,checkpoint:{iteration:e.iteration,interruptedReason:e.interruptedReason,updatedAt:e.updatedAt,messageCount:e.currentMessages?.length||0,subtaskPlan:e.subtaskPlan?{subtaskCount:e.subtaskPlan.subtasks?.length||0}:null}})}).catch(e=>{r.warn(`[Background] GET_CHECKPOINT query failed:`,e),i({exists:!1})}),!0):(i({exists:!1}),!1)}if(e.type===`DELETE_CHECKPOINT`){let{sessionId:t}=e;return t?ie(t).then(e=>{i({success:e})}).catch(e=>{r.warn(`[Background] DELETE_CHECKPOINT failed:`,e),i({success:!1})}):i({success:!1}),!0}if(e.type===`RESUME_REACT`){let{sessionId:n,callId:a,userGuidance:o=``}=e;if(!n)return i({error:t(`bg.missingSessionId`)}),!1;r.debug(`[Background] recei to RESUME_REACT,sessionId:`,n,`userGuidance:`,o?`"${o.substring(0,50)}..."`:`( no )`);let s=Nt.has(n),c=()=>{ue(n);let e={type:`EXECUTION_STATUS_UPDATE`,nodeName:t(`bg.resumingFromCheckpoint`),status:`processing`,executionLog:[],sessionId:n};a&&(e.callId=a),chrome.runtime.sendMessage(e).catch(()=>{}),Vt(n,o,a).then(e=>{if(!e){r.warn(`[Background] RESUME_REACT: not found checkpoint or restore failed`),I(n).then(e=>{r.warn(`[Background] RESUME_REACT: re-query checkpoint result:`,e?`exists`:`not found`)}).catch(()=>{}),chrome.runtime.sendMessage({type:`API_ERROR`,sessionId:n,callId:a,error:t(`bg.checkpointNotFound`),executionLog:[],resumed:!0}).catch(()=>{});return}r.debug(`[Background] RESUME_REACT complete,content length:`,e.content?.length);let i=(e.executionLog||[]).length>Zr?e.executionLog.slice(-1e3):e.executionLog||[];chrome.runtime.sendMessage({type:`API_COMPLETE`,sessionId:n,callId:a,content:e.content||``,executionLog:i,reflectionScore:e.reflectionScore,reasoningContent:e.reasoningContent||null,wasRevised:e.wasRevised||!1,resumed:!0}).catch(e=>{r.warn(`[Background] send RESUME completemessage failed:`,e)})}).catch(e=>{let i=e.name===`AbortError`||e.message===t(`bg.requestCancelled`)||e.message===t(`bg.reactCancelled`);r.debug(`[Background] RESUME_REACT failed:`,i?`(usercancel)`:e.message);let o=e.executionLog||[],s=o.length>Zr?o.slice(-1e3):o;chrome.runtime.sendMessage({type:`API_ERROR`,sessionId:n,callId:a,error:e.message||t(`bg.resumeFailed`),executionLog:s,resumed:!0}).catch(()=>{})})};return s?(r.debug(`[Background] RESUME_REACT: detectedoldtaskstill running , first cancel`),pe(n),Jr(n),setTimeout(c,300)):c(),!1}if(e.type===`TERMINATE_COMMAND`){let{sessionId:t,mode:n}=e;return t&&Jr(t,n||`kill`),!1}if(e.type===`ABORT_CURRENT_TOOL`){let{sessionId:t}=e;return i({success:Se(t)}),!1}if(e.type===`RELOAD_MCP_TOOLS`)return $=null,En().then(e=>{i({success:!0,count:e})}).catch(e=>{i({success:!1,error:e.message})}),!0;if(e.type===`GET_MCP_TOOLS`){let e=Date.now();return $&&e-$.loadedAt<3e4?(r.debug(`[Background] GET_MCP_TOOLS usingcache (${$.tools.length} tool,${Math.round((e-$.loadedAt)/1e3)}s before )`),i({success:!0,tools:$.tools}),!0):(En().then(e=>{let t=f.filter(e=>e.id.startsWith(`mcp_`)).map(e=>({id:e.id,name:e.function?.name||e.id,description:e.function?.description||``,category:e.category||`mcp`,execution:e.execution||`background`,parallelizable:e.parallelizable!==!1,requiresConfirmation:e.requiresConfirmation||!1,enabled:!0}));$={tools:t,loadedAt:Date.now()},r.debug(`[Background] GET_MCP_TOOLS return ${t.length} tool ( reloads ${e} )`),i({success:!0,tools:t})}).catch(e=>{i({success:!1,error:e.message})}),!0)}if(e.type===`GET_AGENT_SKILL_PROMPTS`){let t=Date.now(),n=e.skillNames||null;return!n&&Qr&&t-Qr.loadedAt<6e4?(i({success:!0,prompts:Qr.prompts}),!0):((n&&n.length>0?$e(n):Qe()).then(e=>{let t=e.success&&e.prompts||``;n||(Qr={prompts:t,loadedAt:Date.now()}),i({success:!0,prompts:t})}).catch(e=>{i({success:!1,error:e.message})}),!0)}if(e.type===`GET_AGENT_SKILL_PROMPT`){let n=e.name;return n?(et(n).then(e=>{i(e)}).catch(e=>{i({success:!1,error:e.message})}),!0):(i({success:!1,error:t(`bg.missingSkillName`)}),!0)}if(e.type===`GET_SKILL_LIST`)return Ke().then(e=>{e?.success?i({success:!0,skills:e.skills||[]}):i({success:!1,skills:[],error:e?.error||t(`bg.fetchFailed`)})}).catch(e=>{i({success:!1,skills:[],error:e.message})}),!0;if(e.type===`CAPTURE_TAB`)return chrome.tabs.captureVisibleTab(null,{format:`jpeg`,quality:100},e=>{chrome.runtime.lastError?(r.error(`[Background] screenshot failed:`,chrome.runtime.lastError.message),i({error:chrome.runtime.lastError.message})):i({dataUrl:e})}),!0;if(e.type===`CAPTURE_TAB_FROM_PAGE`)return chrome.tabs.captureVisibleTab(null,{format:`jpeg`,quality:100},e=>{chrome.runtime.lastError?r.error(`[Background] pageshortcutscreenshot failed:`,chrome.runtime.lastError.message):chrome.runtime.sendMessage({type:`SCREENSHOT_RESULT`,dataUrl:e,mode:`full`}).catch(()=>{})}),!0;if(e.type===`CAPTURE_REGION_FROM_PAGE`){let e=n.tab?.id;return e?(chrome.tabs.sendMessage(e,{type:`START_REGION_SELECTION`},e=>{e&&chrome.tabs.captureVisibleTab(null,{format:`png`},t=>{chrome.runtime.lastError?r.error(`[Background] region screenshot failed:`,chrome.runtime.lastError.message):chrome.runtime.sendMessage({type:`SCREENSHOT_RESULT`,dataUrl:t,mode:`region`,rect:e}).catch(()=>{})})}),!0):!1}if(e.type===`CALL_API`){let{messages:n,model:i,useTools:a,tabId:o,apiParams:s,sessionId:c,imageApiBase:l,imageApiKey:u,agentId:d,agentToolIds:f,agentSkillIds:p,callId:m}=e;l&&(s.imageApiBase=l),u&&(s.imageApiKey=u),ue(c);let h={type:`EXECUTION_STATUS_UPDATE`,nodeName:t(`bg.preparing`),status:`processing`,executionLog:[]};return c&&(h.sessionId=c),m&&(h.callId=m),chrome.runtime.sendMessage(h).catch(()=>{}),r.debug(`[Background] recei to CALL_API message,sessionId:`,c,`useTools:`,a,`tabId:`,o,`apiParams:`,s),(a?(async()=>{let e=await In(f,d,p);if(e.length===0)return r.debug(`[Background] no available tools, skip pre-filter, direct normal conversation`),Jt(n,i,s,c,{},m);r.debug(`[Background] get to ${e.length} tool`);let a=(await V()).reactConfig.enableToolPreselect,l;if(a?l=await vt(n,i,e,s):(r.debug(`[Background] toolpre-filterclosed,using alltool`),l={type:`tools`,tools:e,executionLog:[]}),l.executionLog.length>0){let e={type:`EXECUTION_STATUS_UPDATE`,nodeName:t(`bg.toolPreselect`),status:`success`,executionLog:l.executionLog};c&&(e.sessionId=c),m&&(e.callId=m),r.debug(`[Background] sendpre-filterstateupdate:`,e),chrome.runtime.sendMessage(e).then(()=>{r.debug(`[Background] pre-filterstateupdatesend successful`)}).catch(e=>{r.error(`[Background] pre-filterstateupdatesend failed:`,e)})}if(l.type===`answer`)return r.debug(`[Background] pre-filtermodeldirect answer,skip mainmodelcall with `),{content:l.content,executionLog:l.executionLog};let{tools:u,executionLog:h}=l;r.debug(`[Background] after pre-filter ${u.length} tool`),r.debug(`[Background] pre-filter executionlog:`,JSON.stringify(h).substring(0,500)),h.length>0&&chrome.runtime.sendMessage({type:`STREAM_PRESELECT`,sessionId:c,callId:m,preselectLog:h}).catch(()=>{});let g=await Ht(n,i,u,o,s,c,null,null,{value:1},h,m);return r.debug(`[Background] ReAct complete,executionLog total:`,g.executionLog?.length),{content:g.content===void 0?g:g.content,executionLog:g.executionLog||h,reflectionScore:g.reflectionScore,wasRevised:g.wasRevised||!1,reasoningContent:g.reasoningContent||null}})():Jt(n,i,s,c)).then(e=>{let t=e.content===void 0?e:e.content,n=e.executionLog||[],o=e.reflectionScore,s=e.wasRevised||!1,l=e.reasoningContent||null;e.usage&&yt({sessionId:c,model:i||``,usage:e.usage,callType:`non_stream`}).catch(()=>{}),r.debug(`[Background] API call complete,content length:`,t.length,`execution logcount:`,n.length),console.log(`[Background API_COMPLETE] useTools:`,a,`| executionLog entries:`,n.length,`| agent_file entries:`,n.filter(e=>e.nodeType===`tool_exec`&&e.action?.name===`agent_file`).length,`| first few types:`,n.slice(0,5).map(e=>`${e.nodeType}${e.action?`(${e.action.name})`:``}`));let u=n.length>Zr?n.slice(-1e3):n;chrome.runtime.sendMessage({type:`API_COMPLETE`,sessionId:c,callId:m,content:t,executionLog:u,reflectionScore:o,reasoningContent:l,wasRevised:s}).catch(e=>{r.warn(`[Background] send backmessage failed:`,e)})}).catch(e=>{e.name===`AbortError`||e.message===t(`bg.requestCancelled`)||e.message===t(`bg.reactCancelled`)?r.debug(`[Background] API call with by usercancel`):r.error(`[Background] API call with failed:`,e.message||e);let n=e.executionLog||[],i=n.length>Zr?n.slice(-1e3):n;chrome.runtime.sendMessage({type:`API_ERROR`,sessionId:c,callId:m,error:e.message||t(`bg.apiCallFailed`),executionLog:i}).catch(e=>{r.warn(`[Background] send errormessage failed:`,e)})}),!1}if(e.type===`GET_SESSION`)return V().then(e=>{i({modelName:e.modelName})}),!0;if(e.type===`GET_CHAT_CONFIG`)return we().then(e=>{i(e)}),!0;if(e.type===`GET_PERMANENT_NOTES`)return on().then(e=>{if(!e.success){i({success:!1,facts:[],error:e.error});return}i({success:!0,facts:(e.data.facts||[]).sort((e,t)=>(t.importance||0)-(e.importance||0))})}).catch(e=>{i({success:!1,facts:[],error:e.message})}),!0;if(e.type===`OPEN_OPTIONS_PAGE`){let t=e.hash||``;return chrome.runtime.openOptionsPage(()=>{t&&chrome.tabs.query({url:chrome.runtime.getURL(`options.html`)+`*`},e=>{e.length>0&&chrome.tabs.update(e[0].id,{url:chrome.runtime.getURL(`options.html`)+`#`+t})})}),!1}if(e.type===`SELECTION_TOOLBAR_ACTION`){let{prompt:i,action:a,text:o,systemPrompt:s}=e,c=n.tab?.id,l=n.frameId;if(r.debug(`[Background] received selected text toolbar operation:`,a,`tabId:`,c),a===`ai-search`)return c&&chrome.sidePanel.open({tabId:c}).catch(e=>{r.warn(`[Background] open Side Panel failed:`,e?.message||e)}),ei(i,o,c),!1;let u=[{role:`system`,content:s||{explain:`你正在处理用户在网页上选中的内容。用1-3句简洁解释选中内容,必要时补充一个简短示例。不要展开长篇论述。`,translate:`你正在处理用户在网页上选中的内容。自动检测语言:中文→英文,英文→中文,其他语言→同时给出中英文。只输出翻译结果,不添加额外说明。`,summary:`你正在处理用户在网页上选中的内容。用3-5个要点总结选中内容,每条要点一句话,提炼核心信息即可。`}[a]||`你正在处理用户在网页上选中的内容,请用简洁的语言回答用户的问题。`},{role:`user`,content:i}];return ue(),V().then(async e=>{try{if(e.streamConfig?.streamEnabled!==!1&&c){let t=`toolbar_${c}_${Date.now()}`,n=await Jt(u,e.modelName,{},t,{sendFn:e=>chrome.tabs.sendMessage(c,e,{frameId:l}).catch(()=>{}),typePrefix:`SELECTION_TOOLBAR_`}),i=n.content===void 0?n:n.content;n.usage&&yt({sessionId:`selection_toolbar`,model:e.modelName,usage:n.usage,callType:`stream`}).catch(()=>{}),r.debug(`[Background] selected texttoolbarstreaming API complete,content length:`,i.length)}else{let t=await Jt(u,e.modelName,{}),n=t.content===void 0?t:t.content;t.usage&&yt({sessionId:`selection_toolbar`,model:e.modelName,usage:t.usage,callType:`non_stream`}).catch(()=>{}),r.debug(`[Background] selected texttoolbar API complete,content length:`,n.length),c&&chrome.tabs.sendMessage(c,{type:`SELECTION_TOOLBAR_RESULT`,content:n},{frameId:l}).catch(()=>{r.warn(`[Background] send SELECTION_TOOLBAR_RESULT to tab failed`)})}}catch(e){r.error(`[Background] selected texttoolbar API failed:`,e),c&&chrome.tabs.sendMessage(c,{type:`SELECTION_TOOLBAR_RESULT`,error:e.message||t(`bg.apiCallFailed`)},{frameId:l}).catch(()=>{})}}),!1}if(e.type===`FILL_SIDEPANEL_INPUT`){let t=n.tab?.id,i=e.text;return r.debug(`[Background] received follow-upfillrequested :`,i?.substring(0,50)),t&&chrome.sidePanel.open({tabId:t}).catch(e=>{r.warn(`[Background] open Side Panel failed:`,e?.message||e)}),chrome.storage.session.set({pendingFillInput:{text:i,timestamp:Date.now()}}).catch(()=>{}),chrome.runtime.sendMessage({type:`FILL_SIDEPANEL_INPUT`,text:i}).catch(()=>{r.debug(`[Background] Side Panel not open,fillcontentstorage,waiting Side Panel load`)}),!1}if(e.type===`DIRECT_SEND`){let t=n.tab?.id,i=e.text,a=e.selectedText||``;return r.debug(`[Background] received directsendrequested :`,i?.substring(0,50)),t&&chrome.sidePanel.open({tabId:t}).catch(e=>{r.warn(`[Background] open Side Panel failed:`,e?.message||e)}),chrome.storage.session.set({pendingDirectSend:{text:i,selectedText:a,timestamp:Date.now()}}).catch(()=>{}),chrome.runtime.sendMessage({type:`DIRECT_SEND`,text:i,selectedText:a}).catch(()=>{r.debug(`[Background] Side Panel not open,sendcontentstorage,waiting Side Panel load`)}),!1}if(e.type===`TRIGGER_AGENT_HEALTH_CHECK`)return ii.clear(),si(),!1;if(e.type===`OPTIONS_PAGE_OPEN`)return ri=!0,ii.clear(),si(),!1;if(e.type===`OPTIONS_PAGE_CLOSED`)return ri=!1,!1;if(e.type===`AGENT_CONNECTION_CHANGED`)return chrome.runtime.sendMessage({type:`AGENT_CONNECTION_CHANGED`,connected:e.connected,agentId:e.agentId}).catch(()=>{}),e.connected&&e.agentId?(Xe(),Qr=null,$=null,Er(),ii.clear(),Pn(),U(e.agentId,!0),ui(),En().then(e=>{e>0&&r.debug(`[Background] switchagent after loaded: ${e} MCP tool`)}).catch(()=>{}),setTimeout(()=>{si()},3e3)):e.connected||(ui(),$=null,Qr=null,Er(),si()),!1;if(e.type===`CHECK_FILES_EXIST`){let t=e.paths||[];return t.length===0?(i({success:!0,results:{}}),!1):((async()=>{let e=await Promise.allSettled(t.map(e=>Me(e))),n={};e.forEach((e,r)=>{e.status===`fulfilled`&&e.value.success?n[t[r]]=e.value.exists:n[t[r]]=!0}),i({success:!0,results:n})})(),!0)}if(e.type===`AGENT_RESTART`)return(async()=>{i(await tt())})(),!0;if(e.type===`AGENT_UPDATE`)return(async()=>{i(await nt())})(),!0;if(e.type===`AGENT_STOP`)return(async()=>{i(await rt())})(),!0;if(e.type===`OPEN_LOCAL_PROTOTYPE`)return(async()=>{i(await Ne(e.path))})(),!0;if(e.type===`DELETE_LOCAL_PROTOTYPE`)return(async()=>{try{let t=e.path.replace(/[\\/][^\\/]+\.html$/,``),n=await Fe(t);n.success?r.debug(`[Background] local prototypefile deleted:`,t):r.warn(`[Background] local prototypefiledelete failed:`,n.error),i(n)}catch(e){r.warn(`[Background] local prototypefiledelete failed:`,e.message),i({success:!1,error:e.message})}})(),!0;if(e.type===`QUERY_AUDIT_LOGS`)return it({category:e.category,limit:e.limit}).then(e=>{i(e)}).catch(e=>{i({success:!1,error:e.message})}),!0});async function ei(e,t,n){r.debug(`[Background] processselected text AI search:`,e.substring(0,50)+`...`),await chrome.storage.session.set({pendingSelectionSearch:{prompt:e,selectedText:t,timestamp:Date.now()}}),chrome.runtime.sendMessage({type:`SELECTION_AI_SEARCH`,prompt:e,selectedText:t}).catch(()=>{r.debug(`[Background] Side Panel not open,searchcontentstorage,waiting Side Panel load`)})}var ti=null,ni=null,ri=!1,ii=new Map,ai=new Map;async function oi(e){let t=!1,n=5e3;try{let r=new AbortController,i=setTimeout(()=>r.abort(),n),a=await fetch(`${e.url}/api/status`,{signal:r.signal,cache:`no-cache`});clearTimeout(i),t=a.ok}catch{t=!1}if(!t){await new Promise(e=>setTimeout(e,500));try{let r=new AbortController,i=setTimeout(()=>r.abort(),n),a=await fetch(`${e.url}/api/status`,{signal:r.signal,cache:`no-cache`});clearTimeout(i),t=a.ok}catch{t=!1}}return t}async function si(){try{let e=await Oe();if(e.length===0){ii.size>0&&(ii.clear(),Pn(),U(`__global__`,!1),fi(!1,`未配对`));return}let t=await ke(),n=e.filter(e=>!e.disabled),i=ri?n:t&&!t.disabled?[t]:[];if(i.length===0)return;let a=(await Promise.allSettled(i.map(async e=>{let t=await oi(e);return ii.get(e.id)===t?{agentId:e.id,name:e.name,connected:t,changed:!1}:(ii.set(e.id,t),U(e.id,t),r.debug(`[Background] agent ${e.name} status change: ${t?`online`:`offline`}`),{agentId:e.id,name:e.name,connected:t,changed:!0})}))).filter(e=>e.status===`fulfilled`&&e.value.changed).map(e=>e.value);if(a.length>0){Pn();let e=a.find(e=>e.agentId===t?.id);e&&(fi(e.connected,e.connected?`在线`:`离线`,e.agentId),e.connected?(li(e.agentId),En().then(e=>{e>0&&r.debug(`[Background] Agent after reconnect loaded: ${e} MCP tool`)}).catch(()=>{})):(await On(),$=null,r.debug(`[Background] Agent disconnect,cleaned MCP tool`),ci(t)))}}catch(e){r.warn(`[Background] agenthealth checkexception:`,e.message)}}function ci(e){if(!e||e.disabled||ai.get(e.id))return;let t=n=>{if(n>=20){ai.delete(e.id),r.debug(`[Background] agent ${e.name} auto reconnectabandoned (exceed maxretry times)`);return}let i=setTimeout(async()=>{let i=(await Oe()).find(t=>t.id===e.id);if(!i||i.disabled){ai.delete(e.id),r.debug(`[Background] agent ${e.name} ${i?.disabled?`disable`:`delete`},stopauto reconnect`);return}r.debug(`[Background] agent ${e.name} auto reconnectattempt ${n+1}/20`),await oi(e)?(ai.delete(e.id),ii.set(e.id,!0),U(e.id,!0),Pn(),fi(!0,`在线`,e.id),di(e.id),En().then(t=>{t>0&&r.debug(`[Background] Agent ${e.name} reconnect successful,loaded: ${t} MCP tool`)}).catch(()=>{}),r.debug(`[Background] agent ${e.name} auto reconnect successful`)):t(n+1)},15e3);ai.set(e.id,{timer:i,retries:n})};t(0)}function li(e){let t=ai.get(e);t&&(clearTimeout(t.timer),ai.delete(e))}function ui(){for(let[e,t]of ai)clearTimeout(t.timer);ai.clear()}async function di(e){try{let t=await ke();t&&t.id===e&&En().then(e=>{e>0&&r.debug(`[Background] active agentafter reconnect loaded: ${e} MCP tool`)}).catch(()=>{})}catch(e){r.warn(`[Background] refreshactive agentstate failed:`,e.message)}}function fi(e,t,n){chrome.runtime.sendMessage({type:`AGENT_STATUS_CHANGE`,connected:e,status:t,agentId:n}).catch(()=>{})}function pi(){mi(),r.debug(`[Background] start Agent health check (30s interval)`),si(),ti=setInterval(si,3e4),gi()}function mi(){ti&&(clearInterval(ti),ti=null,ii.clear()),_i()}async function hi(){try{let e=await ke();if(!e||e.disabled)return;let t=new AbortController,n=setTimeout(()=>t.abort(),5e3);try{await fetch(`${e.url}/api/heartbeat`,{headers:{Authorization:`Bearer ${e.token}`},signal:t.signal,cache:`no-cache`})}finally{clearTimeout(n)}}catch{}}function gi(){_i(),hi(),ni=setInterval(hi,60*1e3)}function _i(){ni&&=(clearInterval(ni),null)}pi();
332
- //# sourceMappingURL=background-YXfCL0Dx.js.map
331
+ `);return{success:!1,error:t(`toolExec.agentNotFound`,{id:r||i,list:a}),tool_call_id:n}}if(a.disabled)return{success:!1,error:t(`toolExec.agentDisabled`,{name:a.name}),tool_call_id:n};if(!await Ae(a.id))return{success:!1,error:t(`toolExec.agentSwitchFailedSimple`,{name:a.name}),tool_call_id:n};let o=Te(a.id),s=o===!0?``:t(`toolExec.agentOfflineWarning`);return{success:!0,content:t(`toolExec.agentSwitchSuccess`,{name:a.name,id:a.id,warning:s}),agentId:a.id,agentName:a.name,offline:o!==!0,tool_call_id:n}}catch(e){return{success:!1,error:t(`toolExec.agentSwitchFailed`,{error:e.message}),tool_call_id:n}}}e(`zh`,{bg:{missingSessionId:`缺少 sessionId`,resumingFromCheckpoint:`从 checkpoint 恢复中...`,checkpointNotFound:`未找到可恢复的任务 checkpoint,可能已过期或被清理。请检查 Service Worker 控制台中的诊断日志(搜索 "checkpoint" 关键字)。`,resumeFailed:`恢复失败`,missingSkillName:`缺少技能名称`,fetchFailed:`获取失败`,preparing:`准备中...`,toolPreselect:`工具预筛选`,requestCancelled:`请求已被用户取消`,reactCancelled:`ReAct 循环已被用户取消`,apiCallFailed:`API 调用失败`}}),e(`en`,{bg:{missingSessionId:`Missing sessionId`,resumingFromCheckpoint:`Resuming from checkpoint...`,checkpointNotFound:`No checkpoint found for resumption. It may have expired or been cleaned. Check Service Worker console logs (search "checkpoint").`,resumeFailed:`Resume failed`,missingSkillName:`Missing skill name`,fetchFailed:`Fetch failed`,preparing:`Preparing...`,toolPreselect:`Tool Pre-filter`,requestCancelled:`Request was cancelled by user`,reactCancelled:`ReAct loop was cancelled by user`}}),n(),Promise.all([j().then(()=>F()),De()]).then(([e,t])=>{r.debug(`[Background] DB self-check passed,current has ${e.length} checkpoint`+(t?`,completedoldformat Agent migrate`:``))}).catch(e=>{r.warn(`[Background] cleanup expired checkpoint or DB self-check failed:`,e)});var Zr=1e3,$=null,Qr=null,$r=new Map;chrome.runtime.onConnect.addListener(async e=>{if(e.name?.startsWith(`keepalive-`)){let t=e.name.replace(`keepalive-`,``),n=$r.has(t);if($r.set(t,e),r.debug(`[Background] keepalive portconnected, sessionId:`,t,n?`(reconnect)`:`(first times)`),n&&!Nt.has(t)){r.warn(`[Background] ⚠️ detected SW re started,sessionId`,t,` API call lost`);let n=null;try{let e=await I(t);e&&(n={iteration:e.iteration,interruptedReason:e.interruptedReason,updatedAt:e.updatedAt,messageCount:e.currentMessages?.length||0,subtaskPlan:e.subtaskPlan?{subtaskCount:e.subtaskPlan.subtasks?.length||0}:null},r.debug(`[Background] detected recoverable checkpoint:`,n))}catch(e){r.warn(`[Background] read checkpoint failed:`,e.message)}try{e.postMessage({type:`SW_RESTARTED`,sessionId:t,checkpoint:n})}catch(e){r.warn(`[Background] send SW_RESTARTED message failed:`,e.message)}}e.onDisconnect.addListener(()=>{$r.delete(t),r.debug(`[Background] keepalive port disconnected, sessionId:`,t)})}}),chrome.sidePanel?.setPanelBehavior?.({openPanelOnActionClick:!0}),chrome.tabs.onUpdated.addListener((e,t,n)=>{t.status===`complete`&&n.url?.startsWith(`http`)&&chrome.sidePanel?.setOptions?.({enabled:!0})}),chrome.commands?.onCommand?.addListener(e=>{if(e===`_toggle_sidepanel`)try{chrome.extension.getViews({type:`side_panel`}).length>0?chrome.runtime.sendMessage({type:`CLOSE_SIDEPANEL`}).catch(e=>{r.warn(`[Background] send CLOSE_SIDEPANEL failed:`,e?.message)}):chrome.sidePanel?.open?.().catch(e=>{r.warn(`[Background] open sidePanel failed:`,e?.message)})}catch(e){r.warn(`[Background] toggle sidePanel exception:`,e?.message)}}),chrome.runtime.onMessage.addListener((e,n,i)=>{if(e.type===`IFRAME_SELECTION`){let t=n.tab?.id;return t&&chrome.tabs.sendMessage(t,{type:`IFRAME_SELECTION`,text:e.text,x:e.x,y:e.y},{frameId:0}).catch(()=>{}),!1}if(e.type===`IFRAME_CLICK_DISMISS`){let e=n.tab?.id;return e&&chrome.tabs.sendMessage(e,{type:`IFRAME_CLICK_DISMISS`}).catch(()=>{}),!1}if(e.type===`IFRAME_SELECTION_CLEAR`){let e=n.tab?.id;return e&&chrome.tabs.sendMessage(e,{type:`IFRAME_SELECTION_CLEAR`}).catch(()=>{}),!1}if(e.type===`CANCEL_REACT`){let{tabId:t,sessionId:n}=e;return n?(pe(n),Jr(n)):pe(t),!1}if(e.type===`GET_CHECKPOINT`){let{sessionId:t}=e;return t?(I(t).then(e=>{if(!e){i({exists:!1});return}i({exists:!0,checkpoint:{iteration:e.iteration,interruptedReason:e.interruptedReason,updatedAt:e.updatedAt,messageCount:e.currentMessages?.length||0,subtaskPlan:e.subtaskPlan?{subtaskCount:e.subtaskPlan.subtasks?.length||0}:null}})}).catch(e=>{r.warn(`[Background] GET_CHECKPOINT query failed:`,e),i({exists:!1})}),!0):(i({exists:!1}),!1)}if(e.type===`DELETE_CHECKPOINT`){let{sessionId:t}=e;return t?ie(t).then(e=>{i({success:e})}).catch(e=>{r.warn(`[Background] DELETE_CHECKPOINT failed:`,e),i({success:!1})}):i({success:!1}),!0}if(e.type===`RESUME_REACT`){let{sessionId:n,callId:a,userGuidance:o=``}=e;if(!n)return i({error:t(`bg.missingSessionId`)}),!1;r.debug(`[Background] recei to RESUME_REACT,sessionId:`,n,`userGuidance:`,o?`"${o.substring(0,50)}..."`:`( no )`);let s=Nt.has(n),c=()=>{ue(n);let e={type:`EXECUTION_STATUS_UPDATE`,nodeName:t(`bg.resumingFromCheckpoint`),status:`processing`,executionLog:[],sessionId:n};a&&(e.callId=a),chrome.runtime.sendMessage(e).catch(()=>{}),Vt(n,o,a).then(e=>{if(!e){r.warn(`[Background] RESUME_REACT: not found checkpoint or restore failed`),I(n).then(e=>{r.warn(`[Background] RESUME_REACT: re-query checkpoint result:`,e?`exists`:`not found`)}).catch(()=>{}),chrome.runtime.sendMessage({type:`API_ERROR`,sessionId:n,callId:a,error:t(`bg.checkpointNotFound`),executionLog:[],resumed:!0}).catch(()=>{});return}r.debug(`[Background] RESUME_REACT complete,content length:`,e.content?.length);let i=(e.executionLog||[]).length>Zr?e.executionLog.slice(-1e3):e.executionLog||[];chrome.runtime.sendMessage({type:`API_COMPLETE`,sessionId:n,callId:a,content:e.content||``,executionLog:i,reflectionScore:e.reflectionScore,reasoningContent:e.reasoningContent||null,wasRevised:e.wasRevised||!1,resumed:!0}).catch(e=>{r.warn(`[Background] send RESUME completemessage failed:`,e)})}).catch(e=>{let i=e.name===`AbortError`||e.message===t(`bg.requestCancelled`)||e.message===t(`bg.reactCancelled`);r.debug(`[Background] RESUME_REACT failed:`,i?`(usercancel)`:e.message);let o=e.executionLog||[],s=o.length>Zr?o.slice(-1e3):o;chrome.runtime.sendMessage({type:`API_ERROR`,sessionId:n,callId:a,error:e.message||t(`bg.resumeFailed`),executionLog:s,resumed:!0}).catch(()=>{})})};return s?(r.debug(`[Background] RESUME_REACT: detectedoldtaskstill running , first cancel`),pe(n),Jr(n),setTimeout(c,300)):c(),!1}if(e.type===`TERMINATE_COMMAND`){let{sessionId:t,mode:n}=e;return t&&Jr(t,n||`kill`),!1}if(e.type===`ABORT_CURRENT_TOOL`){let{sessionId:t}=e;return i({success:Se(t)}),!1}if(e.type===`RELOAD_MCP_TOOLS`)return $=null,En().then(e=>{i({success:!0,count:e})}).catch(e=>{i({success:!1,error:e.message})}),!0;if(e.type===`GET_MCP_TOOLS`){let e=Date.now();return $&&e-$.loadedAt<3e4?(r.debug(`[Background] GET_MCP_TOOLS usingcache (${$.tools.length} tool,${Math.round((e-$.loadedAt)/1e3)}s before )`),i({success:!0,tools:$.tools}),!0):(En().then(e=>{let t=f.filter(e=>e.id.startsWith(`mcp_`)).map(e=>({id:e.id,name:e.function?.name||e.id,description:e.function?.description||``,category:e.category||`mcp`,execution:e.execution||`background`,parallelizable:e.parallelizable!==!1,requiresConfirmation:e.requiresConfirmation||!1,enabled:!0}));$={tools:t,loadedAt:Date.now()},r.debug(`[Background] GET_MCP_TOOLS return ${t.length} tool ( reloads ${e} )`),i({success:!0,tools:t})}).catch(e=>{i({success:!1,error:e.message})}),!0)}if(e.type===`GET_AGENT_SKILL_PROMPTS`){let t=Date.now(),n=e.skillNames||null;return!n&&Qr&&t-Qr.loadedAt<6e4?(i({success:!0,prompts:Qr.prompts}),!0):((n&&n.length>0?$e(n):Qe()).then(e=>{let t=e.success&&e.prompts||``;n||(Qr={prompts:t,loadedAt:Date.now()}),i({success:!0,prompts:t})}).catch(e=>{i({success:!1,error:e.message})}),!0)}if(e.type===`GET_AGENT_SKILL_PROMPT`){let n=e.name;return n?(et(n).then(e=>{i(e)}).catch(e=>{i({success:!1,error:e.message})}),!0):(i({success:!1,error:t(`bg.missingSkillName`)}),!0)}if(e.type===`GET_SKILL_LIST`)return Ke().then(e=>{e?.success?i({success:!0,skills:e.skills||[]}):i({success:!1,skills:[],error:e?.error||t(`bg.fetchFailed`)})}).catch(e=>{i({success:!1,skills:[],error:e.message})}),!0;if(e.type===`CAPTURE_TAB`)return chrome.tabs.captureVisibleTab(null,{format:`jpeg`,quality:100},e=>{chrome.runtime.lastError?(r.error(`[Background] screenshot failed:`,chrome.runtime.lastError.message),i({error:chrome.runtime.lastError.message})):i({dataUrl:e})}),!0;if(e.type===`CAPTURE_TAB_FROM_PAGE`)return chrome.tabs.captureVisibleTab(null,{format:`jpeg`,quality:100},e=>{chrome.runtime.lastError?r.error(`[Background] pageshortcutscreenshot failed:`,chrome.runtime.lastError.message):chrome.runtime.sendMessage({type:`SCREENSHOT_RESULT`,dataUrl:e,mode:`full`}).catch(()=>{})}),!0;if(e.type===`CAPTURE_REGION_FROM_PAGE`){let e=n.tab?.id;return e?(chrome.tabs.sendMessage(e,{type:`START_REGION_SELECTION`},e=>{e&&chrome.tabs.captureVisibleTab(null,{format:`png`},t=>{chrome.runtime.lastError?r.error(`[Background] region screenshot failed:`,chrome.runtime.lastError.message):chrome.runtime.sendMessage({type:`SCREENSHOT_RESULT`,dataUrl:t,mode:`region`,rect:e}).catch(()=>{})})}),!0):!1}if(e.type===`CALL_API`){let{messages:n,model:i,useTools:a,tabId:o,apiParams:s,sessionId:c,imageApiBase:l,imageApiKey:u,agentId:d,agentToolIds:f,agentSkillIds:p,callId:m}=e;l&&(s.imageApiBase=l),u&&(s.imageApiKey=u),ue(c);let h={type:`EXECUTION_STATUS_UPDATE`,nodeName:t(`bg.preparing`),status:`processing`,executionLog:[]};return c&&(h.sessionId=c),m&&(h.callId=m),chrome.runtime.sendMessage(h).catch(()=>{}),r.debug(`[Background] recei to CALL_API message,sessionId:`,c,`useTools:`,a,`tabId:`,o,`apiParams:`,s),(a?(async()=>{let e=await In(f,d,p);if(e.length===0)return r.debug(`[Background] no available tools, skip pre-filter, direct normal conversation`),Jt(n,i,s,c,{},m);r.debug(`[Background] get to ${e.length} tool`);let a=(await V()).reactConfig.enableToolPreselect,l;if(a?l=await vt(n,i,e,s):(r.debug(`[Background] toolpre-filterclosed,using alltool`),l={type:`tools`,tools:e,executionLog:[]}),l.executionLog.length>0){let e={type:`EXECUTION_STATUS_UPDATE`,nodeName:t(`bg.toolPreselect`),status:`success`,executionLog:l.executionLog};c&&(e.sessionId=c),m&&(e.callId=m),r.debug(`[Background] sendpre-filterstateupdate:`,e),chrome.runtime.sendMessage(e).then(()=>{r.debug(`[Background] pre-filterstateupdatesend successful`)}).catch(e=>{r.error(`[Background] pre-filterstateupdatesend failed:`,e)})}if(l.type===`answer`)return r.debug(`[Background] pre-filtermodeldirect answer,skip mainmodelcall with `),{content:l.content,executionLog:l.executionLog};let{tools:u,executionLog:h}=l;r.debug(`[Background] after pre-filter ${u.length} tool`),r.debug(`[Background] pre-filter executionlog:`,JSON.stringify(h).substring(0,500)),h.length>0&&chrome.runtime.sendMessage({type:`STREAM_PRESELECT`,sessionId:c,callId:m,preselectLog:h}).catch(()=>{});let g=await Ht(n,i,u,o,s,c,null,null,{value:1},h,m);return r.debug(`[Background] ReAct complete,executionLog total:`,g.executionLog?.length),{content:g.content===void 0?g:g.content,executionLog:g.executionLog||h,reflectionScore:g.reflectionScore,wasRevised:g.wasRevised||!1,reasoningContent:g.reasoningContent||null}})():Jt(n,i,s,c)).then(e=>{let t=e.content===void 0?e:e.content,n=e.executionLog||[],o=e.reflectionScore,s=e.wasRevised||!1,l=e.reasoningContent||null;e.usage&&(yt({sessionId:c,model:i||``,usage:e.usage,callType:`non_stream`}).catch(()=>{}),n.length===0&&(n=[{nodeType:`api_call`,nodeName:`API Call`,status:`success`,timestamp:new Date().toISOString(),apiResponse:{tokenUsage:e.usage}}])),r.debug(`[Background] API call complete,content length:`,t.length,`execution logcount:`,n.length),console.log(`[Background API_COMPLETE] useTools:`,a,`| executionLog entries:`,n.length,`| agent_file entries:`,n.filter(e=>e.nodeType===`tool_exec`&&e.action?.name===`agent_file`).length,`| first few types:`,n.slice(0,5).map(e=>`${e.nodeType}${e.action?`(${e.action.name})`:``}`));let u=n.length>Zr?n.slice(-1e3):n;chrome.runtime.sendMessage({type:`API_COMPLETE`,sessionId:c,callId:m,content:t,executionLog:u,reflectionScore:o,reasoningContent:l,wasRevised:s}).catch(e=>{r.warn(`[Background] send backmessage failed:`,e)})}).catch(e=>{e.name===`AbortError`||e.message===t(`bg.requestCancelled`)||e.message===t(`bg.reactCancelled`)?r.debug(`[Background] API call with by usercancel`):r.error(`[Background] API call with failed:`,e.message||e);let n=e.executionLog||[],i=n.length>Zr?n.slice(-1e3):n;chrome.runtime.sendMessage({type:`API_ERROR`,sessionId:c,callId:m,error:e.message||t(`bg.apiCallFailed`),executionLog:i}).catch(e=>{r.warn(`[Background] send errormessage failed:`,e)})}),!1}if(e.type===`GET_SESSION`)return V().then(e=>{i({modelName:e.modelName})}),!0;if(e.type===`GET_CHAT_CONFIG`)return we().then(e=>{i(e)}),!0;if(e.type===`GET_PERMANENT_NOTES`)return on().then(e=>{if(!e.success){i({success:!1,facts:[],error:e.error});return}i({success:!0,facts:(e.data.facts||[]).sort((e,t)=>(t.importance||0)-(e.importance||0))})}).catch(e=>{i({success:!1,facts:[],error:e.message})}),!0;if(e.type===`OPEN_OPTIONS_PAGE`){let t=e.hash||``;return chrome.runtime.openOptionsPage(()=>{t&&chrome.tabs.query({url:chrome.runtime.getURL(`options.html`)+`*`},e=>{e.length>0&&chrome.tabs.update(e[0].id,{url:chrome.runtime.getURL(`options.html`)+`#`+t})})}),!1}if(e.type===`SELECTION_TOOLBAR_ACTION`){let{prompt:i,action:a,text:o,systemPrompt:s}=e,c=n.tab?.id,l=n.frameId;if(r.debug(`[Background] received selected text toolbar operation:`,a,`tabId:`,c),a===`ai-search`)return c&&chrome.sidePanel.open({tabId:c}).catch(e=>{r.warn(`[Background] open Side Panel failed:`,e?.message||e)}),ei(i,o,c),!1;let u=[{role:`system`,content:s||{explain:`你正在处理用户在网页上选中的内容。用1-3句简洁解释选中内容,必要时补充一个简短示例。不要展开长篇论述。`,translate:`你正在处理用户在网页上选中的内容。自动检测语言:中文→英文,英文→中文,其他语言→同时给出中英文。只输出翻译结果,不添加额外说明。`,summary:`你正在处理用户在网页上选中的内容。用3-5个要点总结选中内容,每条要点一句话,提炼核心信息即可。`}[a]||`你正在处理用户在网页上选中的内容,请用简洁的语言回答用户的问题。`},{role:`user`,content:i}];return ue(),V().then(async e=>{try{if(e.streamConfig?.streamEnabled!==!1&&c){let t=`toolbar_${c}_${Date.now()}`,n=await Jt(u,e.modelName,{},t,{sendFn:e=>chrome.tabs.sendMessage(c,e,{frameId:l}).catch(()=>{}),typePrefix:`SELECTION_TOOLBAR_`}),i=n.content===void 0?n:n.content;n.usage&&yt({sessionId:`selection_toolbar`,model:e.modelName,usage:n.usage,callType:`stream`}).catch(()=>{}),r.debug(`[Background] selected texttoolbarstreaming API complete,content length:`,i.length)}else{let t=await Jt(u,e.modelName,{}),n=t.content===void 0?t:t.content;t.usage&&yt({sessionId:`selection_toolbar`,model:e.modelName,usage:t.usage,callType:`non_stream`}).catch(()=>{}),r.debug(`[Background] selected texttoolbar API complete,content length:`,n.length),c&&chrome.tabs.sendMessage(c,{type:`SELECTION_TOOLBAR_RESULT`,content:n},{frameId:l}).catch(()=>{r.warn(`[Background] send SELECTION_TOOLBAR_RESULT to tab failed`)})}}catch(e){r.error(`[Background] selected texttoolbar API failed:`,e),c&&chrome.tabs.sendMessage(c,{type:`SELECTION_TOOLBAR_RESULT`,error:e.message||t(`bg.apiCallFailed`)},{frameId:l}).catch(()=>{})}}),!1}if(e.type===`FILL_SIDEPANEL_INPUT`){let t=n.tab?.id,i=e.text;return r.debug(`[Background] received follow-upfillrequested :`,i?.substring(0,50)),t&&chrome.sidePanel.open({tabId:t}).catch(e=>{r.warn(`[Background] open Side Panel failed:`,e?.message||e)}),chrome.storage.session.set({pendingFillInput:{text:i,timestamp:Date.now()}}).catch(()=>{}),chrome.runtime.sendMessage({type:`FILL_SIDEPANEL_INPUT`,text:i}).catch(()=>{r.debug(`[Background] Side Panel not open,fillcontentstorage,waiting Side Panel load`)}),!1}if(e.type===`DIRECT_SEND`){let t=n.tab?.id,i=e.text,a=e.selectedText||``;return r.debug(`[Background] received directsendrequested :`,i?.substring(0,50)),t&&chrome.sidePanel.open({tabId:t}).catch(e=>{r.warn(`[Background] open Side Panel failed:`,e?.message||e)}),chrome.storage.session.set({pendingDirectSend:{text:i,selectedText:a,timestamp:Date.now()}}).catch(()=>{}),chrome.runtime.sendMessage({type:`DIRECT_SEND`,text:i,selectedText:a}).catch(()=>{r.debug(`[Background] Side Panel not open,sendcontentstorage,waiting Side Panel load`)}),!1}if(e.type===`TRIGGER_AGENT_HEALTH_CHECK`)return ii.clear(),si(),!1;if(e.type===`OPTIONS_PAGE_OPEN`)return ri=!0,ii.clear(),si(),!1;if(e.type===`OPTIONS_PAGE_CLOSED`)return ri=!1,!1;if(e.type===`AGENT_CONNECTION_CHANGED`)return chrome.runtime.sendMessage({type:`AGENT_CONNECTION_CHANGED`,connected:e.connected,agentId:e.agentId}).catch(()=>{}),e.connected&&e.agentId?(Xe(),Qr=null,$=null,Er(),ii.clear(),Pn(),U(e.agentId,!0),ui(),En().then(e=>{e>0&&r.debug(`[Background] switchagent after loaded: ${e} MCP tool`)}).catch(()=>{}),setTimeout(()=>{si()},3e3)):e.connected||(ui(),$=null,Qr=null,Er(),si()),!1;if(e.type===`CHECK_FILES_EXIST`){let t=e.paths||[];return t.length===0?(i({success:!0,results:{}}),!1):((async()=>{let e=await Promise.allSettled(t.map(e=>Me(e))),n={};e.forEach((e,r)=>{e.status===`fulfilled`&&e.value.success?n[t[r]]=e.value.exists:n[t[r]]=!0}),i({success:!0,results:n})})(),!0)}if(e.type===`AGENT_RESTART`)return(async()=>{i(await tt())})(),!0;if(e.type===`AGENT_UPDATE`)return(async()=>{i(await nt())})(),!0;if(e.type===`AGENT_STOP`)return(async()=>{i(await rt())})(),!0;if(e.type===`OPEN_LOCAL_PROTOTYPE`)return(async()=>{i(await Ne(e.path))})(),!0;if(e.type===`DELETE_LOCAL_PROTOTYPE`)return(async()=>{try{let t=e.path.replace(/[\\/][^\\/]+\.html$/,``),n=await Fe(t);n.success?r.debug(`[Background] local prototypefile deleted:`,t):r.warn(`[Background] local prototypefiledelete failed:`,n.error),i(n)}catch(e){r.warn(`[Background] local prototypefiledelete failed:`,e.message),i({success:!1,error:e.message})}})(),!0;if(e.type===`QUERY_AUDIT_LOGS`)return it({category:e.category,limit:e.limit}).then(e=>{i(e)}).catch(e=>{i({success:!1,error:e.message})}),!0});async function ei(e,t,n){r.debug(`[Background] processselected text AI search:`,e.substring(0,50)+`...`),await chrome.storage.session.set({pendingSelectionSearch:{prompt:e,selectedText:t,timestamp:Date.now()}}),chrome.runtime.sendMessage({type:`SELECTION_AI_SEARCH`,prompt:e,selectedText:t}).catch(()=>{r.debug(`[Background] Side Panel not open,searchcontentstorage,waiting Side Panel load`)})}var ti=null,ni=null,ri=!1,ii=new Map,ai=new Map;async function oi(e){let t=!1,n=5e3;try{let r=new AbortController,i=setTimeout(()=>r.abort(),n),a=await fetch(`${e.url}/api/status`,{signal:r.signal,cache:`no-cache`});clearTimeout(i),t=a.ok}catch{t=!1}if(!t){await new Promise(e=>setTimeout(e,500));try{let r=new AbortController,i=setTimeout(()=>r.abort(),n),a=await fetch(`${e.url}/api/status`,{signal:r.signal,cache:`no-cache`});clearTimeout(i),t=a.ok}catch{t=!1}}return t}async function si(){try{let e=await Oe();if(e.length===0){ii.size>0&&(ii.clear(),Pn(),U(`__global__`,!1),fi(!1,`未配对`));return}let t=await ke(),n=e.filter(e=>!e.disabled),i=ri?n:t&&!t.disabled?[t]:[];if(i.length===0)return;let a=(await Promise.allSettled(i.map(async e=>{let t=await oi(e);return ii.get(e.id)===t?{agentId:e.id,name:e.name,connected:t,changed:!1}:(ii.set(e.id,t),U(e.id,t),r.debug(`[Background] agent ${e.name} status change: ${t?`online`:`offline`}`),{agentId:e.id,name:e.name,connected:t,changed:!0})}))).filter(e=>e.status===`fulfilled`&&e.value.changed).map(e=>e.value);if(a.length>0){Pn();let e=a.find(e=>e.agentId===t?.id);e&&(fi(e.connected,e.connected?`在线`:`离线`,e.agentId),e.connected?(li(e.agentId),En().then(e=>{e>0&&r.debug(`[Background] Agent after reconnect loaded: ${e} MCP tool`)}).catch(()=>{})):(await On(),$=null,r.debug(`[Background] Agent disconnect,cleaned MCP tool`),ci(t)))}}catch(e){r.warn(`[Background] agenthealth checkexception:`,e.message)}}function ci(e){if(!e||e.disabled||ai.get(e.id))return;let t=n=>{if(n>=20){ai.delete(e.id),r.debug(`[Background] agent ${e.name} auto reconnectabandoned (exceed maxretry times)`);return}let i=setTimeout(async()=>{let i=(await Oe()).find(t=>t.id===e.id);if(!i||i.disabled){ai.delete(e.id),r.debug(`[Background] agent ${e.name} ${i?.disabled?`disable`:`delete`},stopauto reconnect`);return}r.debug(`[Background] agent ${e.name} auto reconnectattempt ${n+1}/20`),await oi(e)?(ai.delete(e.id),ii.set(e.id,!0),U(e.id,!0),Pn(),fi(!0,`在线`,e.id),di(e.id),En().then(t=>{t>0&&r.debug(`[Background] Agent ${e.name} reconnect successful,loaded: ${t} MCP tool`)}).catch(()=>{}),r.debug(`[Background] agent ${e.name} auto reconnect successful`)):t(n+1)},15e3);ai.set(e.id,{timer:i,retries:n})};t(0)}function li(e){let t=ai.get(e);t&&(clearTimeout(t.timer),ai.delete(e))}function ui(){for(let[e,t]of ai)clearTimeout(t.timer);ai.clear()}async function di(e){try{let t=await ke();t&&t.id===e&&En().then(e=>{e>0&&r.debug(`[Background] active agentafter reconnect loaded: ${e} MCP tool`)}).catch(()=>{})}catch(e){r.warn(`[Background] refreshactive agentstate failed:`,e.message)}}function fi(e,t,n){chrome.runtime.sendMessage({type:`AGENT_STATUS_CHANGE`,connected:e,status:t,agentId:n}).catch(()=>{})}function pi(){mi(),r.debug(`[Background] start Agent health check (30s interval)`),si(),ti=setInterval(si,3e4),gi()}function mi(){ti&&(clearInterval(ti),ti=null,ii.clear()),_i()}async function hi(){try{let e=await ke();if(!e||e.disabled)return;let t=new AbortController,n=setTimeout(()=>t.abort(),5e3);try{await fetch(`${e.url}/api/heartbeat`,{headers:{Authorization:`Bearer ${e.token}`},signal:t.signal,cache:`no-cache`})}finally{clearTimeout(n)}}catch{}}function gi(){_i(),hi(),ni=setInterval(hi,60*1e3)}function _i(){ni&&=(clearInterval(ni),null)}pi();
332
+ //# sourceMappingURL=background-F7Vr55Au.js.map