aitu-app 0.5.14
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/.DS_Store +0 -0
- package/README.md +47 -0
- package/_headers +84 -0
- package/_redirects +2 -0
- package/assets/ChatMessagesArea-CkUX81uB.js +251 -0
- package/assets/ChatMessagesArea-Di0Z80Zh.css +1 -0
- package/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
- package/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
- package/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
- package/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
- package/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
- package/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
- package/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
- package/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
- package/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
- package/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
- package/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
- package/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
- package/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
- package/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
- package/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
- package/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
- package/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
- package/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
- package/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
- package/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
- package/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
- package/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
- package/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
- package/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
- package/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
- package/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
- package/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
- package/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
- package/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
- package/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
- package/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
- package/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
- package/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
- package/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
- package/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
- package/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
- package/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
- package/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
- package/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
- package/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
- package/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
- package/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
- package/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
- package/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
- package/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
- package/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
- package/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
- package/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
- package/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
- package/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
- package/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
- package/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
- package/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
- package/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
- package/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
- package/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
- package/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
- package/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
- package/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
- package/assets/Tableau10-B-NsZVaP.js +1 -0
- package/assets/Tableau10-Dnlau_Wv.js +1 -0
- package/assets/ToolboxDrawer-By1XMh8B.js +87 -0
- package/assets/ToolboxDrawer-fPqvDLQE.css +1 -0
- package/assets/__vite-browser-external-BIHI7g3E.js +1 -0
- package/assets/ai-analyze-Db-iXol6.js +1 -0
- package/assets/arc-BZXVqUcI.js +1 -0
- package/assets/arc-ajYHRRnk.js +1 -0
- package/assets/array-B5oSNiGi.js +1 -0
- package/assets/array-BKyUJesY.js +1 -0
- package/assets/batch-image-generation-Baqb01Lm.js +6 -0
- package/assets/batch-image-generation-CbLMWmjk.css +1 -0
- package/assets/blockDiagram-38ab4fdb-BT3H_WVv.js +118 -0
- package/assets/blockDiagram-38ab4fdb-u0xYP3Lt.js +118 -0
- package/assets/c4Diagram-3d4e48cf-CBvM6zjM.js +10 -0
- package/assets/c4Diagram-3d4e48cf-WOIEVidH.js +10 -0
- package/assets/channel-BP25wTsw.js +1 -0
- package/assets/channel-HzrLNFUg.js +1 -0
- package/assets/classDiagram-70f12bd4-BMutcvFi.js +2 -0
- package/assets/classDiagram-70f12bd4-Cl9U1r5F.js +2 -0
- package/assets/classDiagram-v2-f2320105-C0agtbR4.js +2 -0
- package/assets/classDiagram-v2-f2320105-tCBzATK6.js +2 -0
- package/assets/clone-B69pF7Y_.js +1 -0
- package/assets/clone-oX7o-l4R.js +1 -0
- package/assets/createText-2e5e7dd3-CZ9_fscE.js +5 -0
- package/assets/createText-2e5e7dd3-idrqgJjU.js +7 -0
- package/assets/edges-e0da2a9e-C-RyePMV.js +4 -0
- package/assets/edges-e0da2a9e-DJXAjJSL.js +4 -0
- package/assets/erDiagram-9861fffd-DWJR_3zL.js +51 -0
- package/assets/erDiagram-9861fffd-x2Kcy95-.js +51 -0
- package/assets/flowDb-956e92f1-BgKjOIdz.js +10 -0
- package/assets/flowDb-956e92f1-CF6y18Tn.js +10 -0
- package/assets/flowDiagram-66a62f08-BPPw0wPU.js +4 -0
- package/assets/flowDiagram-66a62f08-CSAllSFf.js +4 -0
- package/assets/flowDiagram-v2-96b9c2cf-B-UGyXRi.js +1 -0
- package/assets/flowDiagram-v2-96b9c2cf-Cm596kxZ.js +1 -0
- package/assets/flowchart-elk-definition-4a651766-9XSRJbsr.js +139 -0
- package/assets/flowchart-elk-definition-4a651766-DWFN9DN3.js +139 -0
- package/assets/ganttDiagram-c361ad54-D9tbz9tQ.js +257 -0
- package/assets/ganttDiagram-c361ad54-ot5pUYpT.js +257 -0
- package/assets/gitGraphDiagram-72cf32ee-BFV3Mt8C.js +70 -0
- package/assets/gitGraphDiagram-72cf32ee-C6qFzgGh.js +70 -0
- package/assets/graph-BxwlF7JS.js +1 -0
- package/assets/graph-D-2Ldvxg.js +1 -0
- package/assets/grid-image-cM9AmYC8.js +1 -0
- package/assets/has-CgdIPiQG.js +1 -0
- package/assets/hasIn-4iY02rGN.js +1 -0
- package/assets/index-3862675e-CVZnpwDN.js +1 -0
- package/assets/index-3862675e-DqdI9cab.js +1 -0
- package/assets/index-B2dvADz8.css +1 -0
- package/assets/index-BicRPzXC.js +1 -0
- package/assets/index-Bs7-jmv6.css +1 -0
- package/assets/index-BwSGXyRr.js +99 -0
- package/assets/index-C1XdOOAn.css +1 -0
- package/assets/index-C4AKKbpQ.css +1 -0
- package/assets/index-CkpXFt8n.js +1 -0
- package/assets/index-CrxF9gFe.js +42 -0
- package/assets/index-DBWqXBIQ.js +93 -0
- package/assets/index-DI_5V2-m.js +3 -0
- package/assets/index-DWUAFoZG.js +2064 -0
- package/assets/index-Dn0YtZ2R.js +3 -0
- package/assets/index-e05Rs4M6.js +12 -0
- package/assets/index.dom-C3-224fz.js +1 -0
- package/assets/infoDiagram-f8f76790-CnrpwoOt.js +7 -0
- package/assets/infoDiagram-f8f76790-FKC1Sy9Y.js +7 -0
- package/assets/init-A0kIFD9x.js +1 -0
- package/assets/init-Gi6I4Gst.js +1 -0
- package/assets/inspiration-board-B_-BBBHt.js +1 -0
- package/assets/isEmpty-Dj2GV0v-.js +1 -0
- package/assets/journeyDiagram-49397b02-B7fP21sU.js +139 -0
- package/assets/journeyDiagram-49397b02-Dp3X9XWq.js +139 -0
- package/assets/katex-BbEIqZs1.js +261 -0
- package/assets/katex-Cu_Erd72.js +261 -0
- package/assets/layout-BD3yCK_X.js +1 -0
- package/assets/layout-DHHYqX7p.js +1 -0
- package/assets/line-B3bNrkzn.js +1 -0
- package/assets/line-B86HLuqu.js +1 -0
- package/assets/linear-DU2Ciymb.js +1 -0
- package/assets/linear-wCAlMhOS.js +1 -0
- package/assets/mermaid.core-DfVvnpgz.js +91 -0
- package/assets/mindmap-definition-fc14e90a-D1sxE3xG.js +425 -0
- package/assets/mindmap-definition-fc14e90a-YuSOJC7P.js +425 -0
- package/assets/ordinal-BRr1uYdk.js +1 -0
- package/assets/ordinal-Cboi1Yqb.js +1 -0
- package/assets/path-CY0bYimO.js +1 -0
- package/assets/path-CbwjOpE9.js +1 -0
- package/assets/photo-wall-splitter-BVU2e0aS.js +1 -0
- package/assets/pick-Cvlwra4g.js +1 -0
- package/assets/pieDiagram-8a3498a8-B6mJUqro.js +35 -0
- package/assets/pieDiagram-8a3498a8-B91bWgo_.js +35 -0
- package/assets/quadrantDiagram-120e2f19-BxS8fQEz.js +7 -0
- package/assets/quadrantDiagram-120e2f19-DwudONqx.js +7 -0
- package/assets/requirementDiagram-deff3bca-DygaMIoy.js +52 -0
- package/assets/requirementDiagram-deff3bca-v9xlgfS8.js +52 -0
- package/assets/sankeyDiagram-04a897e0-BV23dp4l.js +8 -0
- package/assets/sankeyDiagram-04a897e0-BXCiXiyw.js +8 -0
- package/assets/sequenceDiagram-704730f1-CObRpNi4.js +122 -0
- package/assets/sequenceDiagram-704730f1-Ck69A6wI.js +122 -0
- package/assets/settings-dialog-BlCO49C4.js +1 -0
- package/assets/settings-dialog-QUxXj54T.css +1 -0
- package/assets/stateDiagram-587899a1-J_G6I0oo.js +1 -0
- package/assets/stateDiagram-587899a1-z-tKclr3.js +1 -0
- package/assets/stateDiagram-v2-d93cdb3a-DsThtOzP.js +1 -0
- package/assets/stateDiagram-v2-d93cdb3a-XIvq5t8a.js +1 -0
- package/assets/styles-6aaf32cf-1fjuNMUk.js +207 -0
- package/assets/styles-6aaf32cf-DT2rVNfQ.js +207 -0
- package/assets/styles-9a916d00-fLeUSina.js +160 -0
- package/assets/styles-9a916d00-q64Umkis.js +160 -0
- package/assets/styles-c10674c1-BWlxVc3Q.js +116 -0
- package/assets/styles-c10674c1-CtYpjMYU.js +116 -0
- package/assets/svgDrawCommon-08f97a94-C_DhKfny.js +1 -0
- package/assets/svgDrawCommon-08f97a94-DSBqmUv2.js +1 -0
- package/assets/timeline-definition-85554ec2-AKpzwLPN.js +61 -0
- package/assets/timeline-definition-85554ec2-dTkYwoLF.js +61 -0
- package/assets/ttd-dialog-CxiaIUuJ.js +47 -0
- package/assets/ttd-dialog-DCapefb6.css +1 -0
- package/assets/upload-4sxUU7q_.js +1 -0
- package/assets/video-recovery-service-BckHbSyK.js +1 -0
- package/assets/web-vitals-DcvjKPr-.js +1 -0
- package/assets/winbox.bundle.min-CoRPjCs5.js +1 -0
- package/assets/xlsx-CkFp8p6R.js +105 -0
- package/assets/xychartDiagram-e933f94c-DCmvL0ag.js +7 -0
- package/assets/xychartDiagram-e933f94c-aqOiXp_u.js +7 -0
- package/batch-image.html +1616 -0
- package/favicon.ico +0 -0
- package/icons/README.md +55 -0
- package/icons/aitu10.png +0 -0
- package/icons/android-chrome-192x192.png +0 -0
- package/icons/android-chrome-512x512.png +0 -0
- package/icons/apple-touch-icon.png +0 -0
- package/icons/favicon-16x16.png +0 -0
- package/icons/favicon-16x16.svg +539 -0
- package/icons/favicon-32x32.png +0 -0
- package/icons/favicon-32x32.svg +539 -0
- package/icons/favicon-new.svg +539 -0
- package/icons/favicon-new.svg.png +0 -0
- package/icons/icon-192x192.svg +539 -0
- package/icons/icon-512x512.svg +539 -0
- package/icons/icon-96x96.png +0 -0
- package/icons/icon-96x96.svg +539 -0
- package/iframe-test.html +340 -0
- package/index.html +105 -0
- package/init.json +6 -0
- package/logo/cardid.jpg +0 -0
- package/logo/group-qr.png +0 -0
- package/logo/logo_drawnix_h.svg +539 -0
- package/logo/logo_drawnix_h_dark.svg +539 -0
- package/logo/logo_drawnix_new.svg +539 -0
- package/manifest.json +52 -0
- package/package.json +31 -0
- package/product_showcase/aitu-01.png +0 -0
- package/product_showcase/aitu-02.png +0 -0
- package/product_showcase/aitu-03.png +0 -0
- package/product_showcase/aitu-04.png +0 -0
- package/product_showcase/aitu-05.png +0 -0
- package/product_showcase/aitu-06.png +0 -0
- package/product_showcase/case-1.png +0 -0
- package/product_showcase/case-2.png +0 -0
- package/robots.txt +13 -0
- package/sitemap.xml +29 -0
- package/sw-debug/app.js +3069 -0
- package/sw-debug/console-entry.js +80 -0
- package/sw-debug/log-entry.js +452 -0
- package/sw-debug/log-panel.js +309 -0
- package/sw-debug/postmessage-entry.js +117 -0
- package/sw-debug/status-panel.js +125 -0
- package/sw-debug/styles.css +2103 -0
- package/sw-debug/sw-communication.js +208 -0
- package/sw-debug/utils.js +112 -0
- package/sw-debug.html +685 -0
- package/sw.js +58 -0
- package/version.json +10 -0
package/sw.js
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
(function(){"use strict";var b=(s=>(s.PENDING="pending",s.PROCESSING="processing",s.COMPLETED="completed",s.FAILED="failed",s.CANCELLED="cancelled",s))(b||{}),D=(s=>(s.IMAGE="image",s.VIDEO="video",s.CHARACTER="character",s.INSPIRATION_BOARD="inspiration_board",s.CHAT="chat",s))(D||{}),W=(s=>(s.SUBMITTING="submitting",s.POLLING="polling",s.DOWNLOADING="downloading",s))(W||{});const cs={timeouts:{image:600*1e3,video:1200*1e3,character:600*1e3,inspiration_board:600*1e3,chat:600*1e3}},qe="sw-task-queue",lt=2,I="tasks",z="config",B="workflows",N="chat-workflows",U="pending-tool-requests",ls=[I,z,B,N,U];function ds(){return new Promise(s=>{const e=indexedDB.open(qe);e.onsuccess=()=>{const t=e.result,o=t.version;t.close(),s(Math.max(o,lt))},e.onerror=()=>{s(lt)}})}function us(s){const e=[];for(const t of ls)s.objectStoreNames.contains(t)||e.push(t);return e}function hs(s){return new Promise((e,t)=>{const o=s+1;console.log(`[SWStorage] Repairing database: upgrading from v${s} to v${o}`);const n=indexedDB.open(qe,o);n.onerror=()=>{console.error("[SWStorage] Failed to repair DB:",n.error),t(n.error)},n.onsuccess=()=>{e(n.result)},n.onupgradeneeded=r=>{const a=r.target.result;dt(a)}})}function dt(s){if(!s.objectStoreNames.contains(I)){const e=s.createObjectStore(I,{keyPath:"id"});e.createIndex("status","status",{unique:!1}),e.createIndex("type","type",{unique:!1}),e.createIndex("createdAt","createdAt",{unique:!1})}if(s.objectStoreNames.contains(z)||s.createObjectStore(z,{keyPath:"key"}),!s.objectStoreNames.contains(B)){const e=s.createObjectStore(B,{keyPath:"id"});e.createIndex("status","status",{unique:!1}),e.createIndex("createdAt","createdAt",{unique:!1})}if(!s.objectStoreNames.contains(N)){const e=s.createObjectStore(N,{keyPath:"id"});e.createIndex("status","status",{unique:!1}),e.createIndex("createdAt","createdAt",{unique:!1})}s.objectStoreNames.contains(U)||s.createObjectStore(U,{keyPath:"requestId"}).createIndex("workflowId","workflowId",{unique:!1})}async function fs(){const s=await ds();return new Promise((e,t)=>{const o=indexedDB.open(qe,s);o.onerror=()=>{console.error("[SWStorage] Failed to open DB:",o.error),t(o.error)},o.onsuccess=()=>{const n=o.result,r=us(n);if(r.length>0){console.warn(`[SWStorage] Missing object stores: ${r.join(", ")}. Repairing...`),n.close(),hs(n.version).then(e).catch(t);return}e(n)},o.onupgradeneeded=n=>{const r=n.target.result;dt(r)}})}class gs{constructor(){this.dbPromise=null,this.pendingTaskSaves=new Map,this.batchSaveTimer=null,this.batchSavePromises=new Map,this.BATCH_SAVE_DELAY=50}async getDB(){return this.dbPromise||(this.dbPromise=fs()),this.dbPromise}async flushPendingTaskSaves(){this.batchSaveTimer&&(clearTimeout(this.batchSaveTimer),this.batchSaveTimer=null);const e=Array.from(this.pendingTaskSaves.values()),t=new Map(this.batchSavePromises);if(this.pendingTaskSaves.clear(),this.batchSavePromises.clear(),e.length!==0)try{const o=await this.getDB();await new Promise((n,r)=>{const a=o.transaction(I,"readwrite"),i=a.objectStore(I);for(const c of e)i.put(c);a.oncomplete=()=>{t.forEach(({resolve:c})=>c()),n()},a.onerror=()=>{const c=a.error;t.forEach(({reject:l})=>l(c)),r(c)}})}catch(o){console.error("[SWStorage] Failed to batch save tasks:",o),t.forEach(({reject:n})=>n(o))}}async saveTask(e){return new Promise((t,o)=>{this.pendingTaskSaves.set(e.id,e),this.batchSavePromises.set(e.id,{resolve:t,reject:o}),this.batchSaveTimer||(this.batchSaveTimer=setTimeout(()=>{this.flushPendingTaskSaves()},this.BATCH_SAVE_DELAY))})}async saveTaskImmediate(e){this.pendingTaskSaves.delete(e.id);const t=this.batchSavePromises.get(e.id);t&&this.batchSavePromises.delete(e.id);try{const o=await this.getDB();await new Promise((n,r)=>{const c=o.transaction(I,"readwrite").objectStore(I).put(e);c.onerror=()=>r(c.error),c.onsuccess=()=>n()}),t&&t.resolve()}catch(o){throw console.error("[SWStorage] Failed to save task:",o),t&&t.reject(o),o}}async getTask(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(I,"readonly").objectStore(I).get(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o(i.result||null)})}catch(t){return console.error("[SWStorage] Failed to get task:",t),null}}async getAllTasks(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(I,"readonly").objectStore(I).getAll();a.onerror=()=>o(a.error),a.onsuccess=()=>t(a.result||[])})}catch(e){return console.error("[SWStorage] Failed to get all tasks:",e),[]}}async getTasksByStatus(e){try{const t=await this.getDB();return new Promise((o,n)=>{const c=t.transaction(I,"readonly").objectStore(I).index("status").getAll(e);c.onerror=()=>n(c.error),c.onsuccess=()=>o(c.result||[])})}catch(t){return console.error("[SWStorage] Failed to get tasks by status:",t),[]}}async getTasksPaginated(e){const{offset:t,limit:o,status:n,type:r,sortOrder:a="desc"}=e;try{const i=await this.getDB();return new Promise((c,l)=>{const m=i.transaction(I,"readonly").objectStore(I),S=m.index("createdAt"),w=m.count();let g=0;w.onsuccess=()=>{g=w.result};const d=a==="desc"?"prev":"next",u=S.openCursor(null,d),f=[];let p=0,E=0;u.onerror=()=>l(u.error),u.onsuccess=T=>{const _=T.target.result;if(!_){c({tasks:f,total:E,hasMore:E>t+f.length});return}const C=_.value,R=!n||C.status===n,x=!r||C.type===r;R&&x&&(E++,p<t?p++:f.length<o&&f.push(C)),_.continue()}})}catch(i){return console.error("[SWStorage] Failed to get paginated tasks:",i),{tasks:[],total:0,hasMore:!1}}}async deleteTask(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(I,"readwrite").objectStore(I).delete(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to delete task:",t)}}async saveConfig(e,t){try{const o=await this.getDB();return new Promise((n,r)=>{const a=o.transaction(z,"readwrite"),i=a.objectStore(z);e&&i.put({key:"gemini",...e}),t&&i.put({key:"video",...t}),a.oncomplete=()=>n(),a.onerror=()=>r(a.error)})}catch(o){console.error("[SWStorage] Failed to save config:",o)}}async loadConfig(){try{const e=await this.getDB();return new Promise((t,o)=>{const n=e.transaction(z,"readonly"),r=n.objectStore(z),a=r.get("gemini"),i=r.get("video");n.oncomplete=()=>{const c=a.result,l=i.result;t({geminiConfig:c?{apiKey:c.apiKey,baseUrl:c.baseUrl,modelName:c.modelName}:null,videoConfig:l?{baseUrl:l.baseUrl,apiKey:l.apiKey}:null})},n.onerror=()=>o(n.error)})}catch(e){return console.error("[SWStorage] Failed to load config:",e),{geminiConfig:null,videoConfig:null}}}async cleanupOldTasks(e=1440*60*1e3){console.warn("[SWStorage] cleanupOldTasks is deprecated and disabled")}async saveSystemPrompt(e){try{const t=await this.getDB();return new Promise((o,n)=>{const r=t.transaction(z,"readwrite");r.objectStore(z).put({key:"systemPrompt",value:e,updatedAt:Date.now()}),r.oncomplete=()=>o(),r.onerror=()=>n(r.error)})}catch(t){console.error("[SWStorage] Failed to save system prompt:",t)}}async getSystemPrompt(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(z,"readonly").objectStore(z).get("systemPrompt");a.onsuccess=()=>{const i=a.result;t((i==null?void 0:i.value)||null)},a.onerror=()=>o(a.error)})}catch(e){return console.error("[SWStorage] Failed to get system prompt:",e),null}}async saveWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(B,"readwrite").objectStore(B).put(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to save workflow:",t)}}async getWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(B,"readonly").objectStore(B).get(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o(i.result||null)})}catch(t){return console.error("[SWStorage] Failed to get workflow:",t),null}}async getAllWorkflows(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(B,"readonly").objectStore(B).getAll();a.onerror=()=>o(a.error),a.onsuccess=()=>t(a.result||[])})}catch(e){return console.error("[SWStorage] Failed to get all workflows:",e),[]}}async getWorkflowsByStatus(e){try{const t=await this.getDB();return new Promise((o,n)=>{const c=t.transaction(B,"readonly").objectStore(B).index("status").getAll(e);c.onerror=()=>n(c.error),c.onsuccess=()=>o(c.result||[])})}catch(t){return console.error("[SWStorage] Failed to get workflows by status:",t),[]}}async deleteWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(B,"readwrite").objectStore(B).delete(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to delete workflow:",t)}}async cleanupOldWorkflows(e=1440*60*1e3){console.warn("[SWStorage] cleanupOldWorkflows is deprecated and disabled")}async saveChatWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(N,"readwrite").objectStore(N).put(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to save chat workflow:",t)}}async getChatWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(N,"readonly").objectStore(N).get(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o(i.result||null)})}catch(t){return console.error("[SWStorage] Failed to get chat workflow:",t),null}}async getAllChatWorkflows(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(N,"readonly").objectStore(N).getAll();a.onerror=()=>o(a.error),a.onsuccess=()=>t(a.result||[])})}catch(e){return console.error("[SWStorage] Failed to get all chat workflows:",e),[]}}async getChatWorkflowsByStatus(e){try{const t=await this.getDB();return new Promise((o,n)=>{const c=t.transaction(N,"readonly").objectStore(N).index("status").getAll(e);c.onerror=()=>n(c.error),c.onsuccess=()=>o(c.result||[])})}catch(t){return console.error("[SWStorage] Failed to get chat workflows by status:",t),[]}}async deleteChatWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(N,"readwrite").objectStore(N).delete(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to delete chat workflow:",t)}}async cleanupOldChatWorkflows(e=1440*60*1e3){console.warn("[SWStorage] cleanupOldChatWorkflows is deprecated and disabled")}async savePendingToolRequest(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(U,"readwrite").objectStore(U).put(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to save pending tool request:",t)}}async getAllPendingToolRequests(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(U,"readonly").objectStore(U).getAll();a.onerror=()=>o(a.error),a.onsuccess=()=>t(a.result||[])})}catch(e){return console.error("[SWStorage] Failed to get all pending tool requests:",e),[]}}async getPendingToolRequestsByWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const c=t.transaction(U,"readonly").objectStore(U).index("workflowId").getAll(e);c.onerror=()=>n(c.error),c.onsuccess=()=>o(c.result||[])})}catch(t){return console.error("[SWStorage] Failed to get pending tool requests by workflow:",t),[]}}async getPendingToolRequest(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(U,"readonly").objectStore(U).get(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o(i.result||null)})}catch(t){return console.error("[SWStorage] Failed to get pending tool request:",t),null}}async deletePendingToolRequest(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(U,"readwrite").objectStore(U).delete(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to delete pending tool request:",t)}}async deletePendingToolRequestsByWorkflow(e){try{const t=await this.getPendingToolRequestsByWorkflow(e);for(const o of t)await this.deletePendingToolRequest(o.requestId)}catch(t){console.error("[SWStorage] Failed to delete pending tool requests by workflow:",t)}}}const y=new gs;let We=!1;const ps=500,X=[];let De=0;function ms(){return We}const ws=["SW_DEBUG_ENABLE","SW_DEBUG_DISABLE","SW_DEBUG_GET_STATUS","SW_DEBUG_CLEAR_LOGS","SW_DEBUG_CLEAR_CONSOLE_LOGS","SW_DEBUG_GET_CONSOLE_LOGS","SW_DEBUG_EXPORT_LOGS","SW_DEBUG_HEARTBEAT","SW_DEBUG_STATUS","SW_DEBUG_ENABLED","SW_DEBUG_DISABLED","SW_DEBUG_LOG","SW_DEBUG_LOGS","SW_DEBUG_LOGS_CLEARED","SW_CONSOLE_LOG","SW_DEBUG_CONSOLE_LOGS","SW_DEBUG_CONSOLE_LOGS_CLEARED","SW_POSTMESSAGE_LOG","SW_DEBUG_POSTMESSAGE_LOGS","SW_DEBUG_POSTMESSAGE_LOGS_CLEARED"],ye=new Map;function ut(s){const e=We;We=s,!s&&e&&(X.length=0,ye.clear(),De=0)}function Ge(){return We}function ht(s){return ms()?!ws.includes(s):!1}function Ss(s,e,t){if(!ht(s))return"";const o=`pm-recv-${Date.now()}-${++De}`,n={id:o,timestamp:Date.now(),direction:"receive",messageType:s,data:Fe(e),clientId:t};if(gt(n),Ts(s)){const r=pt(e);r&&ye.set(r,{entry:n,startTime:Date.now()})}return o}function ft(s,e,t){if(!ht(s))return"";const o=`pm-send-${Date.now()}-${++De}`,n={id:o,timestamp:Date.now(),direction:"send",messageType:s,data:Fe(e),clientId:t};if(Es(s)){const r=pt(e);if(r){const a=ye.get(r);a&&(n.duration=Date.now()-a.startTime,a.entry.response=Fe(e),a.entry.duration=n.duration,ye.delete(r))}}return gt(n),o}function gt(s){X.unshift(s),X.length>ps&&X.pop()}function Te(){return[...X]}function ys(){X.length=0,ye.clear(),De=0}function Ts(s){return["TASK_SUBMIT","TASK_CANCEL","TASK_RETRY","TASK_DELETE","TASK_GET_","WORKFLOW_SUBMIT","WORKFLOW_CANCEL","WORKFLOW_GET_","CHAT_START","MCP_TOOL_EXECUTE","MAIN_THREAD_TOOL_REQUEST"].some(t=>s.includes(t))}function Es(s){return["TASK_QUEUE_INITIALIZED","TASK_STATUS","TASK_COMPLETED","TASK_FAILED","TASK_CREATED","TASK_CANCELLED","TASK_DELETED","TASK_ALL_RESPONSE","TASK_PAGINATED_RESPONSE","WORKFLOW_STATUS","WORKFLOW_STEP_STATUS","WORKFLOW_COMPLETED","WORKFLOW_FAILED","CHAT_CHUNK","CHAT_DONE","CHAT_ERROR","MCP_TOOL_RESULT","MAIN_THREAD_TOOL_RESPONSE"].some(t=>s.includes(t))}function pt(s){if(!s||typeof s!="object")return null;const e=s;return e.requestId||e.taskId||e.workflowId||e.chatId||null}function Fe(s){if(!s)return s;try{const e=JSON.parse(JSON.stringify(s));return mt(e),e}catch{return"[Non-serializable data]"}}function mt(s){if(!s||typeof s!="object")return;const e=["apiKey","password","token","secret","key"],t=s;for(const o in t)e.some(n=>o.toLowerCase().includes(n))?t[o]="[REDACTED]":typeof t[o]=="object"&&mt(t[o])}function Cs(){const s={total:X.length,sent:0,received:0,byType:{}};for(const e of X)e.direction==="send"?s.sent++:s.received++,s.byType[e.messageType]||(s.byType[e.messageType]=0),s.byType[e.messageType]++;return s}let Le=!1,ae=null;function $e(s){Le=s,ut(s)}function _s(s){ae=s}function wt(s,e){if(!s){console.warn("[MessageBus] No client provided");return}let t="";if(Ge()){const o=(e==null?void 0:e.type)||"unknown";t=ft(o,e,s.id)}try{s.postMessage(e)}catch(o){console.warn("[MessageBus] Failed to postMessage to client:",s.id,o);return}if(t&&Le&&ae){const n=Te().find(r=>r.id===t);n&&ae(n)}}function St(s){const e=self,t=(s==null?void 0:s.type)||"unknown";e.clients.matchAll().then(o=>{o.forEach(n=>{let r="";if(Ge()&&(r=ft(t,s,n.id)),n.postMessage(s),r&&Le&&ae){const i=Te().find(c=>c.id===r);i&&ae(i)}})})}async function Ie(s,e){const t=self;if(!s)return console.warn("[MessageBus] No clientId provided"),!1;try{const o=await t.clients.get(s);return o?(wt(o,e),!0):(console.warn("[MessageBus] Client not found:",s),!1)}catch(o){return console.warn("[MessageBus] Failed to send to client:",s,o),!1}}function bs(s,e){Le=!1,ut(!1),ae=null}const As={"1x1":"1024x1024","16x9":"1792x1024","9x16":"1024x1792","4x3":"1536x1152","3x4":"1152x1536","3x2":"1536x1024","2x3":"1024x1536"};function Rs(s){return As[s]||s}function Ws(s){if(!s||!Array.isArray(s))return;const e=s.filter(t=>t&&typeof t=="object"&&typeof t.url=="string").map(t=>t.url);return e.length>0?e:void 0}function Ds(s){const e=[];if(Array.isArray(s.inputReferences))for(const t of s.inputReferences)t!=null&&t.url&&e.push(String(t.url));if(s.inputReference&&e.push(String(s.inputReference)),Array.isArray(s.uploadedImages))for(const t of s.uploadedImages)t&&typeof t=="object"&&t.url&&e.push(String(t.url));if(Array.isArray(s.referenceImages))for(const t of s.referenceImages)typeof t=="string"&&e.push(t);return e}class yt extends Error{constructor(e){super(e),this.name="VideoGenerationFailedError"}}async function Tt(s,e,t={}){var S,w;const{onProgress:o,signal:n,apiKey:r,interval:a=5e3,maxAttempts:i=1080}=t;let c=0,l=0;const h=10,{debugFetch:m}=await Promise.resolve().then(()=>P);for(;c<i;){if(n!=null&&n.aborted)throw new Error("Video generation cancelled");try{const g=await m(`${s}/videos/${e}`,{headers:r?{Authorization:`Bearer ${r}`}:{},signal:n},{label:`🔄 查询视频状态 #${c+1}`,logResponseBody:!0});if(!g.ok){if(l++,console.warn(`[VideoPolling] Status query failed (${g.status}), attempt ${l}/${h}, will retry with longer interval`),l>=h)throw new Error(`Failed to get video status after ${h} consecutive errors: ${g.status}`);const p=Math.min(a*Math.pow(1.5,l),6e4);await new Promise(E=>setTimeout(E,p)),c++;continue}l=0;const d=await g.json(),u=(S=d.status)==null?void 0:S.toLowerCase(),f=d.progress??Math.min(10+c*2,90);if(o==null||o(f,"polling"),u==="completed"||u==="succeeded")return o==null||o(100),d;if(u==="failed"||u==="error"){const p=typeof d.error=="string"?d.error:((w=d.error)==null?void 0:w.message)||d.message||"Video generation failed";throw new yt(p)}await new Promise(p=>setTimeout(p,a)),c++}catch(g){if(g instanceof yt)throw g;if(n!=null&&n.aborted)throw new Error("Video generation cancelled");if(l++,console.warn(`[VideoPolling] Network error during status query, attempt ${l}/${h}:`,g),l>=h)throw g;const d=Math.min(a*Math.pow(1.5,l),6e4);await new Promise(u=>setTimeout(u,d)),c++}}throw new Error("Video generation timed out")}const He="drawnix-images",Ls=720*60*1e3,Is="drawnix-unified-cache",ze="media";async function Os(s){return new Promise(e=>{try{const t=indexedDB.open(Is);t.onerror=()=>{console.warn("[MediaUtils] Failed to open IndexedDB:",t.error),e(null)},t.onsuccess=()=>{try{const o=t.result;if(!o.objectStoreNames.contains(ze)){o.close(),e(null);return}const a=o.transaction(ze,"readonly").objectStore(ze).get(s);a.onsuccess=()=>{const i=a.result;o.close(),i&&i.cachedAt?e(i.cachedAt):e(null)},a.onerror=()=>{o.close(),e(null)}}catch{e(null)}}}catch(t){console.warn("[MediaUtils] Error accessing IndexedDB:",t),e(null)}})}async function ks(s,e){try{if(s.startsWith("data:"))return Et(s);const t=await caches.open(He),o=await t.match(s);if(o)return await o.blob();const n=await fetch(s,{signal:e});if(n.ok){const r=await n.blob();try{const a=new Response(r.slice(),{headers:{"Content-Type":r.type||"image/png","sw-cache-date":Date.now().toString()}});await t.put(s,a)}catch(a){console.warn(`[MediaUtils] Failed to cache image: ${s.substring(0,50)}...`,a)}return r}return console.warn(`[MediaUtils] Network fetch failed: ${s.substring(0,50)}...`,n.status),null}catch(t){return console.warn(`[MediaUtils] Error in fetchImageWithCache: ${s.substring(0,50)}...`,t),null}}function Et(s){try{const[e,t]=s.split(",");if(!t)return null;const o=e.match(/data:([^;]+)/),n=o?o[1]:"image/png",r=atob(t),a=new Uint8Array(r.length);for(let i=0;i<r.length;i++)a[i]=r.charCodeAt(i);return new Blob([a],{type:n})}catch(e){return console.warn("[MediaUtils] Failed to convert data URL to Blob:",e),null}}async function xs(s){return new Promise((e,t)=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.onerror=t,o.readAsDataURL(s)})}const Ke=1024*1024,Oe=.1,ke=2048;async function Ms(s,e=Ke){if(s.size<=e)return s;try{const t=await createImageBitmap(s);let{width:o,height:n}=t;const r={width:o,height:n};if(o>ke||n>ke){const d=Math.min(ke/o,ke/n);o=Math.round(o*d),n=Math.round(n*d)}const a=new OffscreenCanvas(o,n),i=a.getContext("2d");if(!i)return console.warn("[MediaUtils] Failed to get 2d context from OffscreenCanvas"),s;i.drawImage(t,0,0,o,n),t.close();let c=Oe,l=.95,h=null,m=0;const S=8;for(let d=0;d<S;d++){const u=(c+l)/2,f=await a.convertToBlob({type:"image/jpeg",quality:u});if(f.size<=e?(h=f,m=u,c=u):l=u,l-c<.02)break}if(h)return h;let w=await a.convertToBlob({type:"image/jpeg",quality:Oe}),g=.8;for(;g>=.3&&w.size>e;){const d=Math.round(o*g),u=Math.round(n*g),f=new OffscreenCanvas(d,u),p=f.getContext("2d");if(!p)break;const E=await createImageBitmap(s);p.drawImage(E,0,0,d,u),E.close();let T=Oe,_=.95,C=null;for(let R=0;R<6;R++){const x=(T+_)/2,v=await f.convertToBlob({type:"image/jpeg",quality:x});if(v.size<=e?(C=v,T=x):_=x,_-T<.02)break}if(C)return C;w=await f.convertToBlob({type:"image/jpeg",quality:Oe}),g-=.1}return w}catch(t){return console.warn("[MediaUtils] Image compression failed, returning original:",t),s}}async function Ee(s,e=Ke){const t=await Ms(s,e);return xs(t)}async function Ps(s,e){if(s.startsWith("data:")){if((s.split(",")[1]||"").length*3/4>Ke){const n=Et(s);if(n){const r=await Ee(n);return{originalUrl:s,value:r,isBase64:!0}}}return{originalUrl:s,value:s,isBase64:!0}}try{const t=await caches.open(He);if(s.startsWith("/asset-library/")){const o=await t.match(s);if(o){const n=await o.blob(),r=await Ee(n);return{originalUrl:s,value:r,isBase64:!0}}return console.warn(`[MediaUtils] Asset library image not found in cache: ${s}`),{originalUrl:s,value:s,isBase64:!1}}if(s.startsWith("/__aitu_cache__/")){const o=`${self.location.origin}${s}`,n=await t.match(o);if(n){const r=await n.blob(),a=await Ee(r);return{originalUrl:s,value:a,isBase64:!0}}return console.warn(`[MediaUtils] Cache URL not found in cache: ${s}`),{originalUrl:s,value:s,isBase64:!1}}if(s.startsWith("http://")||s.startsWith("https://")){const o=await t.match(s,{ignoreVary:!0});if(o){const r=await Os(s),a=o.headers.get("sw-cache-date"),i=a?parseInt(a,10):0,c=r??i,l=Date.now(),h=c?l-c:1/0,m=h/(3600*1e3);if(c>0&&h<Ls)return{originalUrl:s,value:s,isBase64:!1};const S=await o.blob(),w=await Ee(S);return{originalUrl:s,value:w,isBase64:!0}}const n=await fetch(s,{signal:e});if(n.ok){const r=await n.blob();try{const i=new Response(r.slice(),{headers:{"Content-Type":r.type||"image/png","sw-cache-date":Date.now().toString()}});await t.put(s,i)}catch(i){console.warn(`[MediaUtils] Failed to cache image: ${s.substring(0,50)}...`,i)}const a=await Ee(r);return{originalUrl:s,value:a,isBase64:!0}}return console.warn(`[MediaUtils] Failed to fetch remote image: ${s.substring(0,50)}...`),{originalUrl:s,value:s,isBase64:!1}}return{originalUrl:s,value:s,isBase64:!1}}catch(t){return console.warn(`[MediaUtils] Error processing reference image: ${s.substring(0,50)}...`,t),{originalUrl:s,value:s,isBase64:!1}}}async function vs(s,e){return!s||s.length===0?[]:(await Promise.all(s.map(o=>Ps(o,e)))).map(o=>o.value)}function Ct(s,e="gemini-3-pro-image-preview-vip"){const t={model:s.model||e,prompt:s.prompt,n:s.n||1,response_format:"url"};return s.size&&(t.size=Rs(s.size)),s.quality&&(t.quality=s.quality),s.referenceImages&&s.referenceImages.length>0&&(t.image=s.referenceImages),s.isInspirationBoard&&s.inspirationBoardImageCount&&(t.n=s.inspirationBoardImageCount),t}function Bs(s){return s.startsWith("data:image/")&&s.includes(";base64,")}function Ns(s){const e=s.match(/^data:(image\/[^;]+);base64,(.+)$/);return e?{mimeType:e[1],base64:e[2]}:null}async function _t(s,e="image/png"){try{const t=atob(s),o=new Uint8Array(t.length);for(let h=0;h<t.length;h++)o[h]=t.charCodeAt(h);const n=new Blob([o],{type:e}),r=`img-${Date.now()}-${Math.random().toString(36).substring(2,10)}`,a=e.split("/")[1]||"png",i=`/__aitu_cache__/image/${r}.${a}`,c=await caches.open(He),l=new Response(n,{status:200,headers:{"Content-Type":e,"Content-Length":n.size.toString(),"Cache-Control":"max-age=31536000"}});return await c.put(i,l),i}catch(t){return console.error("[cacheBase64Image] Failed to cache image:",t),`data:${e};base64,${s}`}}async function bt(s,e){var i;if(!s.data||s.data.length===0)throw new Error("No image data in response");async function t(c,l){return c.url?c.url:c.b64_json?await _t(c.b64_json,"image/png"):null}const o=s.data[0],n=await t(o);if(!n)throw(i=o.revised_prompt)!=null&&i.includes("PROHIBITED_CONTENT")?new Error("内容被拒绝:包含违禁内容"):new Error("No image URL in response");const r=s.data.map((c,l)=>t(c)),a=(await Promise.all(r)).filter(Boolean);return{url:n,urls:a.length>1?a:void 0}}async function Us(s){if(!Bs(s))return{url:s,migrated:!1};const e=Ns(s);if(!e)return{url:s,migrated:!1};try{const t=await _t(e.base64,e.mimeType);return console.log(`[Migration] Converted Base64 (${Math.round(s.length/1024)}KB) -> ${t}`),{url:t,migrated:!0}}catch(t){return console.error("[Migration] Failed to migrate Base64 URL:",t),{url:s,migrated:!1}}}class qs{constructor(){this.abortControllers=new Map}async execute(e,t){const o=new AbortController;this.abortControllers.set(e.id,o);try{return t.onProgress(e.id,0,W.SUBMITTING),await this.generateImage(e,t,o.signal)}finally{this.abortControllers.delete(e.id)}}cancel(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e))}async generateImage(e,t,o){const{geminiConfig:n}=t,{params:r}=e,a=r.referenceImages||Ws(r.uploadedImages);let i;a&&a.length>0&&(i=await vs(a,o));const c=Ct({prompt:r.prompt,model:r.model,size:r.size,referenceImages:i,isInspirationBoard:r.isInspirationBoard,inspirationBoardImageCount:r.inspirationBoardImageCount},n.modelName);t.onProgress(e.id,10,W.SUBMITTING);const{debugFetch:l}=await Promise.resolve().then(()=>P),{startLLMApiLog:h,completeLLMApiLog:m,failLLMApiLog:S}=await Promise.resolve().then(()=>L),w=Date.now(),g=h({endpoint:"/images/generations",model:n.modelName||"unknown",taskType:"image",prompt:r.prompt,hasReferenceImages:!!i&&i.length>0,referenceImageCount:i==null?void 0:i.length,taskId:e.id}),d=await l(`${n.baseUrl}/images/generations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`},body:JSON.stringify(c),signal:o},{label:`🎨 生成图片 (${n.modelName})`,logRequestBody:!0,logResponseBody:!0});if(!d.ok){const E=await d.text();throw S(g,{httpStatus:d.status,duration:Date.now()-w,errorMessage:E,responseBody:E}),new Error(`Image generation failed: ${d.status} - ${E}`)}t.onProgress(e.id,80,W.DOWNLOADING);const u=await d.json(),f=JSON.stringify(u),{url:p}=await bt(u,e.id);return m(g,{httpStatus:d.status,duration:Date.now()-w,resultType:"image",resultCount:1,resultUrl:p,responseBody:f}),t.onProgress(e.id,100),{url:p,format:"png",size:0,width:r.width,height:r.height}}}class Gs{constructor(){this.abortControllers=new Map,this.pollingIntervals=new Map}async execute(e,t){const o=new AbortController;this.abortControllers.set(e.id,o);try{t.onProgress(e.id,0,W.SUBMITTING);const{response:n,logId:r}=await this.submitVideoGeneration(e,t,o.signal);return t.onRemoteId(e.id,n.id),t.onProgress(e.id,5,W.POLLING),await this.pollUntilComplete(n.id,e.id,t,o.signal,r)}finally{this.cleanup(e.id)}}async resume(e,t){var a,i;if(!e.remoteId)throw new Error("No remote ID for resume");const o=new AbortController;this.abortControllers.set(e.id,o);const{startLLMApiLog:n}=await Promise.resolve().then(()=>L),r=n({endpoint:`/videos/${e.remoteId} (resumed)`,model:((a=e.params)==null?void 0:a.model)||"veo3",taskType:"video",prompt:((i=e.params)==null?void 0:i.prompt)||"",taskId:e.id});try{return t.onProgress(e.id,e.progress||0,W.POLLING),await this.pollUntilComplete(e.remoteId,e.id,t,o.signal,r)}finally{this.cleanup(e.id)}}cancel(e){this.cleanup(e)}async submitVideoGeneration(e,t,o){const{videoConfig:n}=t,{params:r}=e,a=new FormData;a.append("model",r.model||"veo3"),a.append("prompt",r.prompt),r.duration&&a.append("seconds",String(r.duration)),r.size&&a.append("size",r.size);const i=Ds({referenceImages:r.referenceImages,uploadedImages:r.uploadedImages,inputReference:r.inputReference,inputReferences:r.inputReferences});if(i.length>0)for(let f=0;f<i.length;f++){const p=i[f];try{const E=await ks(p,o);E?a.append("input_reference",E,`reference-${f+1}.png`):(console.warn(`[VideoHandler] Failed to get reference image: ${p}`),a.append("input_reference",p))}catch(E){console.warn(`[VideoHandler] Error fetching reference image: ${p}`,E),a.append("input_reference",p)}}const{debugFetch:c}=await Promise.resolve().then(()=>P),{startLLMApiLog:l,completeLLMApiLog:h,failLLMApiLog:m}=await Promise.resolve().then(()=>L),S=Date.now(),w=r.model||"veo3",g=l({endpoint:"/videos",model:w,taskType:"video",prompt:r.prompt,hasReferenceImages:i.length>0,referenceImageCount:i.length,taskId:e.id}),d=await c(`${n.baseUrl}/videos`,{method:"POST",headers:n.apiKey?{Authorization:`Bearer ${n.apiKey}`}:void 0,body:a,signal:o},{label:`🎬 提交视频生成 (${w})`,logResponseBody:!0});if(!d.ok){const f=await d.text();throw m(g,{httpStatus:d.status,duration:Date.now()-S,errorMessage:f,responseBody:f}),new Error(`Video submission failed: ${d.status} - ${f}`)}return{response:await d.json(),logId:g}}async pollUntilComplete(e,t,o,n,r){const{videoConfig:a}=o,i=Date.now();try{const c=await Tt(a.baseUrl,e,{onProgress:(h,m)=>{o.onProgress(t,h,m)},signal:n,apiKey:a.apiKey,interval:5e3,maxAttempts:1080}),l=c.video_url||c.url;if(!l)throw new Error("No video URL in completed response");if(r){const{completeLLMApiLog:h}=await Promise.resolve().then(()=>L);h(r,{httpStatus:200,duration:Date.now()-i,resultType:"video",resultCount:1,resultUrl:l,responseBody:JSON.stringify(c)})}return{url:l,format:"mp4",size:0,width:c.width,height:c.height,duration:parseInt(c.seconds||"0")||0}}catch(c){if(r){const{failLLMApiLog:l}=await Promise.resolve().then(()=>L);l(r,{duration:Date.now()-i,errorMessage:c instanceof Error?c.message:String(c)})}throw c}}cleanup(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e));const o=this.pollingIntervals.get(e);o&&(clearTimeout(o),this.pollingIntervals.delete(e))}}class Fs{constructor(){this.abortControllers=new Map,this.pollingIntervals=new Map}async execute(e,t){const o=new AbortController;this.abortControllers.set(e.id,o);try{t.onProgress(e.id,0,W.SUBMITTING);const{response:n,logId:r}=await this.createCharacter(e,t,o.signal);return t.onRemoteId(e.id,n.id),t.onProgress(e.id,10,W.POLLING),await this.pollUntilComplete(n.id,e.id,t,o.signal,r)}finally{this.cleanup(e.id)}}async resume(e,t){var a;if(!e.remoteId)throw new Error("No remote ID for resume");const o=new AbortController;this.abortControllers.set(e.id,o);const{startLLMApiLog:n}=await Promise.resolve().then(()=>L),r=n({endpoint:`/characters/${e.remoteId} (resumed)`,model:"character-extractor",taskType:"character",prompt:((a=e.params)==null?void 0:a.videoUrl)||"",taskId:e.id});try{return t.onProgress(e.id,e.progress||0,W.POLLING),await this.pollUntilComplete(e.remoteId,e.id,t,o.signal,r)}finally{this.cleanup(e.id)}}cancel(e){this.cleanup(e)}async createCharacter(e,t,o){const{videoConfig:n}=t,{params:r}=e,a=this.getCharacterModel(r.model),i=new FormData;i.append("character_from_task",r.sourceVideoTaskId||""),i.append("model",a),r.characterTimestamps&&i.append("character_timestamps",r.characterTimestamps);const{debugFetch:c}=await Promise.resolve().then(()=>P),{startLLMApiLog:l,completeLLMApiLog:h,failLLMApiLog:m}=await Promise.resolve().then(()=>L),S=Date.now(),w=l({endpoint:"/videos",model:a,taskType:"character",prompt:`角色提取: ${r.sourceVideoTaskId}`,taskId:e.id}),g=await c(`${n.baseUrl}/videos`,{method:"POST",headers:{...n.apiKey?{Authorization:`Bearer ${n.apiKey}`}:{}},body:i,signal:o},{label:`👤 创建角色视频 (${a})`,logResponseBody:!0});if(!g.ok){const u=await g.text();throw m(w,{httpStatus:g.status,duration:Date.now()-S,errorMessage:u,responseBody:u}),new Error(`Character creation failed: ${g.status} - ${u}`)}return{response:await g.json(),logId:w}}async pollUntilComplete(e,t,o,n,r){const{videoConfig:a}=o,i=3e3,c=60,l=Date.now();let h=0;return new Promise((m,S)=>{const w=async()=>{if(n.aborted){if(r){const{failLLMApiLog:g}=await Promise.resolve().then(()=>L);g(r,{duration:Date.now()-l,errorMessage:"Task cancelled"})}S(new Error("Task cancelled"));return}if(h++,h>c){if(r){const{failLLMApiLog:g}=await Promise.resolve().then(()=>L);g(r,{duration:Date.now()-l,errorMessage:"Character creation timeout"})}S(new Error("Character creation timeout"));return}try{const g=await this.queryCharacter(e,a,n),d=Math.min(10+h/c*90,99);if(o.onProgress(t,d,W.POLLING),g.username){if(o.onProgress(t,100),r){const{completeLLMApiLog:f}=await Promise.resolve().then(()=>L);f(r,{httpStatus:200,duration:Date.now()-l,resultType:"character",resultCount:1,resultUrl:g.profile_picture_url,responseBody:JSON.stringify(g)})}m({url:g.profile_picture_url,format:"png",size:0,characterUsername:g.username,characterProfileUrl:g.profile_picture_url,characterPermalink:g.permalink});return}const u=setTimeout(w,i);this.pollingIntervals.set(t,u)}catch(g){if(g instanceof Error&&g.message.includes("404")){const d=setTimeout(w,i);this.pollingIntervals.set(t,d)}else if(h<c){const d=setTimeout(w,i);this.pollingIntervals.set(t,d)}else{if(r){const{failLLMApiLog:d}=await Promise.resolve().then(()=>L);d(r,{duration:Date.now()-l,errorMessage:g instanceof Error?g.message:String(g)})}S(g)}}};w()})}async queryCharacter(e,t,o){const{debugFetch:n}=await Promise.resolve().then(()=>P),r=await n(`${t.baseUrl}/videos/${e}`,{method:"GET",headers:t.apiKey?{Authorization:`Bearer ${t.apiKey}`}:void 0,signal:o},{label:"👤 查询角色状态",logResponseBody:!0});if(!r.ok)throw new Error(`Character query failed: ${r.status}`);return r.json()}getCharacterModel(e){return e==="sora-2-pro"?"sora-2-pro-character":"sora-2-character"}cleanup(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e));const o=this.pollingIntervals.get(e);o&&(clearTimeout(o),this.pollingIntervals.delete(e))}}class $s{constructor(){this.abortControllers=new Map}async execute(e,t){const o=e.params,n=new AbortController;this.abortControllers.set(e.id,n);try{const r=this.convertToGeminiMessages(o),a=await this.streamChat(r,t.geminiConfig,o.temporaryModel,o.systemPrompt,n.signal,void 0);return{url:"",format:"text",size:a.length,chatResponse:a,toolCalls:[]}}finally{this.abortControllers.delete(e.id)}}cancel(e){this.stop(e)}async stream(e,t,o,n){const r=new AbortController;this.abortControllers.set(e,r);try{const a=this.convertToGeminiMessages(t);return await this.streamChat(a,o,t.temporaryModel,t.systemPrompt,r.signal,n)}finally{this.abortControllers.delete(e)}}stop(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e))}convertToGeminiMessages(e){var o;const t=[];e.systemPrompt&&t.push({role:"system",content:[{type:"text",text:e.systemPrompt}]});for(const n of e.messages){const r=[];if(n.content&&r.push({type:"text",text:n.content}),n.attachments)for(const a of n.attachments)a.type==="image"&&r.push({type:"image_url",image_url:{url:`data:${a.mimeType};base64,${a.data}`}});t.push({role:n.role,content:r})}if(e.newContent||(o=e.attachments)!=null&&o.length){const n=[];if(e.newContent&&n.push({type:"text",text:e.newContent}),e.attachments)for(const r of e.attachments)r.type==="image"&&n.push({type:"image_url",image_url:{url:`data:${r.mimeType};base64,${r.data}`}});t.push({role:"user",content:n})}return t}async streamChat(e,t,o,n,r,a){var v,ee,Ae,Zt,es,ts,ss,os;const i=o||t.modelName||"gemini-2.5-flash",c={model:i,messages:e,stream:!0},{debugFetch:l}=await Promise.resolve().then(()=>P),{startLLMApiLog:h,completeLLMApiLog:m,failLLMApiLog:S}=await Promise.resolve().then(()=>L),w=Date.now(),g=e.filter(H=>H.role==="user").pop(),d=((ee=(v=g==null?void 0:g.content)==null?void 0:v[0])==null?void 0:ee.text)||"",u=h({endpoint:"/chat/completions",model:i,taskType:"chat",prompt:d,requestBody:JSON.stringify(c,null,2)}),f=await l(`${t.baseUrl}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`},body:JSON.stringify(c),signal:r},{label:`💬 对话请求 (${i})`,logRequestBody:!0,isStreaming:!0});if(!f.ok){const H=await f.text();throw S(u,{httpStatus:f.status,duration:Date.now()-w,errorMessage:H}),new Error(`Chat request failed: ${f.status} - ${H}`)}const p=w,E=u;if(!f.body)throw new Error("No response body");const T=f.body.getReader(),_=new TextDecoder;let C="",R="";try{for(;;){const{done:H,value:rs}=await T.read();if(H)break;R+=_.decode(rs,{stream:!0});const Re=R.split(`
|
|
2
|
+
`);R=Re.pop()||"";for(const ns of Re)if(ns.startsWith("data: ")){const as=ns.slice(6).trim();if(as==="[DONE]")continue;try{const is=(es=(Zt=(Ae=JSON.parse(as).choices)==null?void 0:Ae[0])==null?void 0:Zt.delta)==null?void 0:es.content;is&&(C+=is,a==null||a(C))}catch{}}}if(R.startsWith("data: ")){const H=R.slice(6).trim();if(H&&H!=="[DONE]")try{const Re=(os=(ss=(ts=JSON.parse(H).choices)==null?void 0:ts[0])==null?void 0:ss.delta)==null?void 0:os.content;Re&&(C+=Re,a==null||a(C))}catch{}}}finally{T.releaseLock()}if(f.__debugLogId&&C){const{updateLogResponseBody:H}=await Promise.resolve().then(()=>P);H(f.__debugLogId,C)}const{completeLLMApiLog:x}=await Promise.resolve().then(()=>L);return x(E,{httpStatus:f.status,duration:Date.now()-p,resultType:"text",resultCount:1,resultText:C}),C}}class Hs{constructor(e,t){this.tasks=new Map,this.runningTasks=new Set,this.geminiConfig=null,this.videoConfig=null,this.initialized=!1,this.chatResultCache=new Map,this.CHAT_CACHE_TTL=60*1e3,this.sw=e,this.config={...cs,...t},this.imageHandler=new qs,this.videoHandler=new Gs,this.characterHandler=new Fs,this.chatHandler=new $s,this.storageRestorePromise=this.restoreFromStorage()}setTaskStatusChangeCallback(e){this.onTaskStatusChange=e}getGeminiConfig(){return this.geminiConfig}getVideoConfig(){return this.videoConfig}getSW(){return this.sw}async restoreFromStorage(){var e;try{const{geminiConfig:t,videoConfig:o}=await y.loadConfig();t&&o&&(this.geminiConfig=t,this.videoConfig=o,this.initialized=!0);const n=await y.getAllTasks();let r=0;for(const a of n){if(a.status===b.COMPLETED&&((e=a.result)!=null&&e.url)&&a.result.url.startsWith("data:image/")){const{url:i,migrated:c}=await Us(a.result.url);c&&(a.result.url=i,await y.updateTask(a),r++)}if(this.tasks.set(a.id,a),a.type===D.CHAT&&a.status===b.PROCESSING){await this.markTaskFailed(a.id,{code:"INTERRUPTED",message:"Chat 请求被中断(页面刷新),请重试"});continue}this.shouldResumeTask(a)&&this.resumeTaskExecution(a)}r>0&&console.log(`[SWTaskQueue] Migrated ${r} Base64 URLs to cache`)}catch(t){console.error("[SWTaskQueue] Failed to restore from storage:",t)}}shouldResumeTask(e){return e.type===D.CHAT&&e.status===b.PROCESSING?!1:!!(e.status===b.PROCESSING||e.status===b.PENDING||(e.type===D.VIDEO||e.type===D.CHARACTER)&&e.status===b.FAILED&&e.remoteId&&this.isNetworkError(e))}isNetworkError(e){var i,c,l,h;const t=((i=e.error)==null?void 0:i.message)||"",o=((l=(c=e.error)==null?void 0:c.details)==null?void 0:l.originalError)||"",n=((h=e.error)==null?void 0:h.code)||"",r=`${t} ${o}`.toLowerCase();return r.includes("generation_failed")||r.includes("invalid_argument")||r.includes("prohibited")||r.includes("content policy")||r.includes("视频生成失败")||n.includes("generation_failed")||n.includes("INVALID")?!1:r.includes("failed to fetch")||r.includes("network")||r.includes("fetch")||r.includes("timeout")||r.includes("aborted")||r.includes("connection")||r.includes("status query failed")}async resumeTaskExecution(e){if(this.initialized){if(e.remoteId&&(e.type===D.VIDEO||e.type===D.CHARACTER))e.status===b.FAILED&&(e.status=b.PROCESSING,e.error=void 0,e.executionPhase=W.POLLING,e.updatedAt=Date.now(),this.tasks.set(e.id,e),await y.saveTask(e)),this.runningTasks.add(e.id),this.broadcastToClients({type:"TASK_STATUS",taskId:e.id,status:b.PROCESSING,progress:e.progress,phase:W.POLLING,updatedAt:e.updatedAt}),this.executeResume(e,e.remoteId);else if(e.status===b.PENDING)this.processQueue();else if((e.type===D.VIDEO||e.type===D.CHARACTER)&&e.status===b.PROCESSING&&!e.remoteId){const{findSuccessLogByTaskId:t}=await Promise.resolve().then(()=>L),o=await t(e.id);if(o&&o.resultUrl){let n,r,a;if(o.responseBody)try{const i=JSON.parse(o.responseBody);n=i.width,r=i.height,a=parseInt(i.seconds||"0")||0}catch{}await this.handleTaskSuccess(e.id,{url:o.resultUrl,format:e.type===D.VIDEO?"mp4":"png",size:0,width:n,height:r,duration:a});return}await this.handleTaskError(e.id,new Error("任务中断且无法恢复(未找到已完成的结果)"))}else if((e.type===D.IMAGE||e.type===D.INSPIRATION_BOARD)&&e.status===b.PROCESSING){const{findSuccessLogByTaskId:t}=await Promise.resolve().then(()=>L),o=await t(e.id);if(o&&o.resultUrl){await this.handleTaskSuccess(e.id,{url:o.resultUrl,format:"png",size:0});return}await this.handleTaskError(e.id,new Error("任务中断且无法恢复(未找到已完成的结果)"))}}}async initialize(e,t){await this.storageRestorePromise,this.geminiConfig=e,this.videoConfig=t,this.initialized=!0,await y.saveConfig(e,t),this.broadcastToClients({type:"TASK_QUEUE_INITIALIZED",success:!0}),this.syncTasksToClients();for(const o of this.tasks.values())this.shouldResumeTask(o)&&!this.runningTasks.has(o.id)&&this.resumeTaskExecution(o);this.processQueue()}async updateConfig(e,t){e&&this.geminiConfig&&(this.geminiConfig={...this.geminiConfig,...e}),t&&this.videoConfig&&(this.videoConfig={...this.videoConfig,...t}),await y.saveConfig(this.geminiConfig,this.videoConfig)}async submitTask(e,t,o,n){if(this.tasks.has(e)){console.warn(`[SWTaskQueue] Task ${e} already exists`);return}const r=Date.now(),a={id:e,type:t,status:b.PENDING,params:o,createdAt:r,updatedAt:r};this.tasks.set(e,a),await y.saveTask(a),this.broadcastToClients({type:"TASK_CREATED",task:a}),this.processQueue()}async cancelTask(e){var o;const t=this.tasks.get(e);t&&(this.runningTasks.has(e)&&((o=this.getHandler(t.type))==null||o.cancel(e),this.runningTasks.delete(e)),t.status=b.CANCELLED,t.updatedAt=Date.now(),this.tasks.set(e,t),await y.saveTask(t),this.broadcastToClients({type:"TASK_CANCELLED",taskId:e}))}async retryTask(e){const t=this.tasks.get(e);!t||t.status!==b.FAILED&&t.status!==b.CANCELLED||(t.status=b.PENDING,t.error=void 0,t.updatedAt=Date.now(),this.tasks.set(e,t),await y.saveTask(t),this.broadcastToClients({type:"TASK_STATUS",taskId:t.id,status:t.status,updatedAt:t.updatedAt}),this.processQueue())}async resumeTask(e,t,o,n){let r=this.tasks.get(e);if(!r){const a=Date.now();r={id:e,type:o,status:b.PROCESSING,params:{prompt:""},createdAt:a,updatedAt:a,remoteId:t,executionPhase:W.POLLING},this.tasks.set(e,r),await y.saveTask(r)}(o===D.VIDEO||o===D.CHARACTER)&&(this.runningTasks.add(e),this.executeResume(r,t))}getTask(e){return this.tasks.get(e)||null}getAllTasks(){return Array.from(this.tasks.values())}async deleteTask(e){var o;const t=this.tasks.get(e);t&&(this.runningTasks.has(e)&&((o=this.getHandler(t.type))==null||o.cancel(e),this.runningTasks.delete(e)),this.tasks.delete(e),await y.deleteTask(e),this.broadcastToClients({type:"TASK_DELETED",taskId:e}))}async markTaskInserted(e){const t=this.tasks.get(e);if(!t)return;const o={...t,insertedToCanvas:!0,updatedAt:Date.now()};this.tasks.set(e,o),await y.saveTask(o)}async restoreTasks(e){for(const t of e)t.status!==b.COMPLETED&&t.status!==b.CANCELLED&&(this.tasks.set(t.id,t),await y.saveTask(t));this.processQueue()}async startChat(e,t,o){if(!this.geminiConfig){this.broadcastToClients({type:"CHAT_ERROR",chatId:e,error:"Gemini config not initialized"});return}try{const n=await this.chatHandler.stream(e,t,this.geminiConfig,a=>{this.broadcastToClients({type:"CHAT_CHUNK",chatId:e,content:a})});this.chatResultCache.set(e,{chatId:e,fullContent:n,timestamp:Date.now(),delivered:!1}),this.broadcastToClients({type:"CHAT_DONE",chatId:e,fullContent:n});const r=this.chatResultCache.get(e);r&&(r.delivered=!0),this.cleanupChatCache()}catch(n){this.broadcastToClients({type:"CHAT_ERROR",chatId:e,error:n instanceof Error?n.message:String(n)})}}getCachedChatResult(e){return this.chatResultCache.get(e)}getAllCachedChatResults(){return Array.from(this.chatResultCache.values())}cleanupChatCache(){const e=Date.now();for(const[t,o]of this.chatResultCache.entries())e-o.timestamp>this.CHAT_CACHE_TTL&&this.chatResultCache.delete(t)}stopChat(e){this.chatHandler.stop(e)}syncTasksToClients(){const e=this.getAllTasks();this.broadcastToClients({type:"TASK_ALL_RESPONSE",tasks:e})}async getTasksPaginated(e){return y.getTasksPaginated(e)}async syncPaginatedTasksToClients(e){const t=await this.getTasksPaginated(e);this.broadcastToClients({type:"TASK_PAGINATED_RESPONSE",tasks:t.tasks,total:t.total,offset:e.offset,hasMore:t.hasMore})}processQueue(){if(!this.initialized){console.warn("[SWTaskQueue] Not initialized, skipping queue processing");return}const e=Array.from(this.tasks.values()).filter(t=>t.status===b.PENDING).sort((t,o)=>t.createdAt-o.createdAt);for(const t of e)this.executeTask(t)}async executeTask(e){if(!this.geminiConfig||!this.videoConfig){console.warn("[SWTaskQueue] Config not set, cannot execute task:",e.id);return}this.runningTasks.add(e.id),e.status=b.PROCESSING,e.startedAt=Date.now(),e.updatedAt=Date.now(),e.executionPhase=W.SUBMITTING,this.tasks.set(e.id,e),await y.saveTask(e),this.broadcastToClients({type:"TASK_STATUS",taskId:e.id,status:e.status,phase:e.executionPhase,updatedAt:e.updatedAt});const t={geminiConfig:this.geminiConfig,videoConfig:this.videoConfig,onProgress:async(o,n,r)=>{const a=this.tasks.get(o);if(a&&a.status!==b.COMPLETED&&a.status!==b.FAILED&&a.status!==b.CANCELLED){const i=a.status;a.progress=n,r&&(a.executionPhase=r),a.updatedAt=Date.now(),this.tasks.set(o,a),await y.saveTask(a);const c=this.tasks.get(o);c&&c.status===i&&this.broadcastToClients({type:"TASK_STATUS",taskId:o,status:i,progress:n,phase:r,updatedAt:a.updatedAt})}},onRemoteId:async(o,n)=>{const r=this.tasks.get(o);r&&(r.remoteId=n,r.executionPhase=W.POLLING,r.updatedAt=Date.now(),this.tasks.set(o,r),await y.saveTask(r),this.broadcastToClients({type:"TASK_SUBMITTED",taskId:o,remoteId:n}))}};try{const o=this.getHandler(e.type);if(!o)throw new Error(`No handler for task type: ${e.type}`);const n=this.config.timeouts[e.type]||600*1e3,r=await Promise.race([o.execute(e,t),new Promise((a,i)=>{setTimeout(()=>{var c;(c=o.cancel)==null||c.call(o,e.id),i(new Error(`Task timeout after ${Math.round(n/6e4)} minutes`))},n)})]);await this.handleTaskSuccess(e.id,r)}catch(o){await this.handleTaskError(e.id,o)}}async executeResume(e,t){if(!this.geminiConfig||!this.videoConfig)return;const o={geminiConfig:this.geminiConfig,videoConfig:this.videoConfig,onProgress:async(n,r,a)=>{const i=this.tasks.get(n);if(i&&i.status!==b.COMPLETED&&i.status!==b.FAILED&&i.status!==b.CANCELLED){const c=i.status;i.progress=r,a&&(i.executionPhase=a),i.updatedAt=Date.now(),this.tasks.set(n,i),await y.saveTask(i);const l=this.tasks.get(n);l&&l.status===c&&this.broadcastToClients({type:"TASK_STATUS",taskId:n,status:c,progress:r,phase:a,updatedAt:i.updatedAt})}},onRemoteId:()=>{}};try{const n=this.getHandler(e.type);if(!(n!=null&&n.resume))throw new Error(`Handler does not support resume: ${e.type}`);e.remoteId=t;const r=await n.resume(e,o);await this.handleTaskSuccess(e.id,r)}catch(n){console.error(`[SWTaskQueue] executeResume: 任务 ${e.id} 恢复失败`,n),await this.handleTaskError(e.id,n)}}async handleTaskSuccess(e,t){var n;const o=this.tasks.get(e);o&&(o.status=b.COMPLETED,o.result=t,o.completedAt=Date.now(),o.updatedAt=Date.now(),o.executionPhase=void 0,this.tasks.set(e,o),this.runningTasks.delete(e),await y.saveTask(o),this.broadcastToClients({type:"TASK_COMPLETED",taskId:e,result:t,completedAt:o.completedAt}),(n=this.onTaskStatusChange)==null||n.call(this,e,"completed",t),this.processQueue())}async handleTaskError(e,t){var r;const o=this.tasks.get(e);if(!o)return;this.runningTasks.delete(e);const n={code:"EXECUTION_ERROR",message:t instanceof Error?t.message:String(t),details:{originalError:t instanceof Error?t.stack:String(t),timestamp:Date.now()}};o.status=b.FAILED,o.error=n,o.updatedAt=Date.now(),this.tasks.set(e,o),await y.saveTask(o),this.broadcastToClients({type:"TASK_FAILED",taskId:e,error:n}),(r=this.onTaskStatusChange)==null||r.call(this,e,"failed",void 0,n.message),this.processQueue()}async markTaskFailed(e,t){const o=this.tasks.get(e);o&&(o.status=b.FAILED,o.error=t,o.updatedAt=Date.now(),this.tasks.set(e,o),await y.saveTask(o),this.broadcastToClients({type:"TASK_FAILED",taskId:e,error:t}))}getHandler(e){switch(e){case D.IMAGE:case D.INSPIRATION_BOARD:return this.imageHandler;case D.VIDEO:return this.videoHandler;case D.CHARACTER:return this.characterHandler;case D.CHAT:return this.chatHandler;default:return null}}async broadcastToClients(e){try{const t=await this.sw.clients.matchAll({type:"window"});for(const o of t)wt(o,e)}catch(t){console.error("[SWTaskQueue] Failed to broadcast:",t)}}}let xe=null;function zs(s,e){return xe||(xe=new Hs(s,e)),xe}function je(){return xe}function Ks(s,e){var o,n;const t=je();if(!t&&s.type!=="TASK_QUEUE_INIT"){console.warn("[SWTaskQueue] Queue not initialized");return}switch(s.type){case"TASK_QUEUE_INIT":t&&t.initialize(s.geminiConfig,s.videoConfig);break;case"TASK_QUEUE_UPDATE_CONFIG":t==null||t.updateConfig(s.geminiConfig,s.videoConfig);break;case"TASK_SUBMIT":t==null||t.submitTask(s.taskId,s.taskType,s.params,e);break;case"TASK_CANCEL":t==null||t.cancelTask(s.taskId);break;case"TASK_RETRY":t==null||t.retryTask(s.taskId);break;case"TASK_RESUME":t==null||t.resumeTask(s.taskId,s.remoteId,s.taskType,e);break;case"TASK_GET_STATUS":{t==null||t.syncTasksToClients();break}case"TASK_GET_ALL":{t==null||t.syncTasksToClients();break}case"TASK_GET_PAGINATED":{t==null||t.syncPaginatedTasksToClients({offset:s.offset,limit:s.limit,status:(o=s.filters)==null?void 0:o.status,type:(n=s.filters)==null?void 0:n.type,sortOrder:s.sortOrder});break}case"TASK_DELETE":t==null||t.deleteTask(s.taskId);break;case"TASK_MARK_INSERTED":t==null||t.markTaskInserted(s.taskId);break;case"CHAT_START":t==null||t.startChat(s.chatId,s.params,e);break;case"CHAT_STOP":t==null||t.stopChat(s.chatId);break;case"CHAT_GET_CACHED":{const r=t==null?void 0:t.getCachedChatResult(s.chatId);r?Ie(e,{type:"CHAT_CACHED_RESULT",chatId:s.chatId,fullContent:r.fullContent,found:!0}).then(a=>{a||console.warn("[SWTaskQueue] Failed to send CHAT_CACHED_RESULT to client:",e)}):Ie(e,{type:"CHAT_CACHED_RESULT",chatId:s.chatId,found:!1}).then(a=>{a||console.warn("[SWTaskQueue] Failed to send CHAT_CACHED_RESULT (not found) to client:",e)});break}case"TASK_RESTORE":t==null||t.restoreTasks(s.tasks);break;case"MCP_TOOL_EXECUTE":{Promise.resolve().then(()=>yr).then(({executeMCPTool:r})=>{const a=je(),i=a==null?void 0:a.getGeminiConfig(),c=a==null?void 0:a.getVideoConfig(),l=a==null?void 0:a.getSW();a&&i&&c&&l?r(s.requestId,s.toolName,s.args,i,c,e,l):l==null||l.clients.get(e).then(h=>{h&&h.postMessage({type:"MCP_TOOL_RESULT",requestId:s.requestId,success:!1,error:"Task queue not initialized",resultType:"error"})})});break}}}const js={name:"generate_image",description:"Generate images using AI",async execute(s,e){const{geminiConfig:t,onProgress:o,signal:n}=e,{prompt:r,size:a,referenceImages:i,quality:c,model:l,count:h=1}=s;if(!r)return{success:!1,error:"缺少必填参数 prompt",type:"error"};try{o==null||o(0,W.SUBMITTING);const m=Ct({prompt:r,model:l,size:a,referenceImages:i,quality:c,n:Math.min(Math.max(1,h),10)},t.modelName);o==null||o(10,W.SUBMITTING);const{debugFetch:S}=await Promise.resolve().then(()=>P),w=await S(`${t.baseUrl}/images/generations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`},body:JSON.stringify(m),signal:n},{label:`🎨 生成图片 (${t.modelName})`,logRequestBody:!0,logResponseBody:!0});if(!w.ok){const f=await w.text();throw console.error("[SW:generateImage] ✗ API error:",w.status,f.substring(0,200)),new Error(`Image generation failed: ${w.status} - ${f}`)}o==null||o(80,W.DOWNLOADING);const g=await w.json(),{url:d,urls:u}=await bt(g);return o==null||o(100),{success:!0,type:"image",data:{url:d,urls:u,format:"png",prompt:r,size:a||"1x1"}}}catch(m){return console.error("[SW:generateImage] Error:",m),{success:!1,error:m.message||"图片生成失败",type:"error"}}}},Vs={name:"generate_video",description:"Generate videos using AI",async execute(s,e){const{videoConfig:t,onProgress:o,onRemoteId:n,signal:r}=e,{prompt:a,model:i="veo3",seconds:c="8",size:l="1280x720",inputReference:h,inputReferences:m,referenceImages:S}=s;if(!a)return{success:!1,error:"缺少必填参数 prompt",type:"error"};try{o==null||o(0,W.SUBMITTING);const w={model:i,prompt:a,seconds:c,size:l},g=[];m&&m.length>0?m.forEach(T=>{const _=typeof T=="string"?T:T==null?void 0:T.url;_&&g.push(_)}):S&&S.length>0?g.push(...S):h&&g.push(h),g.length>0&&(g.length===1?w.input_reference=g[0]:w.input_references=g);const{debugFetch:d}=await Promise.resolve().then(()=>P),u=await d(`${t.baseUrl}/videos/generations`,{method:"POST",headers:{"Content-Type":"application/json",...t.apiKey?{Authorization:`Bearer ${t.apiKey}`}:{}},body:JSON.stringify(w),signal:r},{label:`🎬 提交视频生成 (${t.model||"default"})`,logRequestBody:!0,logResponseBody:!0});if(!u.ok){const T=await u.text();throw console.error("[SW:generateVideo] ✗ Submit failed:",u.status,T.substring(0,200)),new Error(`Video submission failed: ${u.status} - ${T}`)}const f=await u.json(),p=f.id||f.video_id;if(!p)throw console.error("[SW:generateVideo] ✗ No video ID in response:",f),new Error("No video ID in response");n==null||n(p),o==null||o(10,W.POLLING);const E=await Tt(t.baseUrl,p,{onProgress:o,signal:r,apiKey:t.apiKey});return{success:!0,type:"video",data:{url:E.video_url||E.url,format:"mp4",prompt:a,duration:parseInt(E.seconds||"")||parseInt(c)}}}catch(w){return console.error("[SW:generateVideo] ✗ Error:",w.message),{success:!1,error:w.message||"视频生成失败",type:"error"}}}},At=new Map([["generate_image",js],["generate_video",Vs]]);function Rt(s){return At.get(s)}async function Ve(s,e,t){const o=At.get(s);return o?o.execute(e,t):{success:!1,error:`Unknown tool: ${s}`,type:"error"}}function Qe(s){return["canvas_insert","insert_to_canvas","insert_mermaid","insert_mindmap","insert_svg","ai_analyze","generate_image","generate_video","generate_grid_image","generate_inspiration_board","split_image","generate_long_video"].includes(s)}class Qs{constructor(e){this.workflows=new Map,this.runningWorkflows=new Set,this.abortControllers=new Map,this.pendingToolRequests=new Map,this.config=e,this.restoreFromStorage()}async restoreFromStorage(){try{const e=await y.getAllWorkflows();for(const t of e){if(t.status==="completed"||t.status==="cancelled"||t.status==="failed"){this.workflows.set(t.id,t);continue}(t.status==="running"||t.status==="pending")&&await this.handleInterruptedWorkflow(t)}}catch(e){console.error("[WorkflowExecutor] Failed to restore from storage:",e)}}async handleInterruptedWorkflow(e){const t=e.steps.find(o=>o.status==="running");e.status="failed",e.error=t?`工作流在步骤 "${t.description||t.mcp}" 执行时中断,请重试`:"工作流执行时中断,请重试",e.updatedAt=Date.now(),t&&(t.status="failed",t.error="Service Worker 重启导致执行中断"),this.workflows.set(e.id,e),await y.saveWorkflow(e),await y.deletePendingToolRequestsByWorkflow(e.id)}updateConfig(e){this.config={...this.config,...e}}async handleMainThreadToolResponse(e){var o;console.log("[SW-WorkflowExecutor] ◀ Received tool response:",{requestId:e.requestId,success:e.success,hasPending:this.pendingToolRequests.has(e.requestId),hasAddSteps:!!((o=e.addSteps)!=null&&o.length),timestamp:new Date().toISOString()});const t=this.pendingToolRequests.get(e.requestId);if(t)console.log("[SW-WorkflowExecutor] ✓ Resolving pending tool request:",e.requestId),this.pendingToolRequests.delete(e.requestId),t.resolve(e);else{console.log("[SW-WorkflowExecutor] Tool response received after SW restart, attempting recovery:",e.requestId);const n=await y.getPendingToolRequest(e.requestId);if(!n){console.log("[SW-WorkflowExecutor] No stored request found for:",e.requestId);return}console.log("[SW-WorkflowExecutor] Found stored request:",{workflowId:n.workflowId,stepId:n.stepId,toolName:n.toolName});let r=this.workflows.get(n.workflowId);if(r||(r=await y.getWorkflow(n.workflowId),r&&this.workflows.set(r.id,r)),!r){console.log("[SW-WorkflowExecutor] Workflow not found:",n.workflowId),await y.deletePendingToolRequest(e.requestId);return}const a=r.steps.find(i=>i.id===n.stepId);if(!a){console.log("[SW-WorkflowExecutor] Step not found:",n.stepId),await y.deletePendingToolRequest(e.requestId);return}if(e.success){a.status="completed",a.result={success:!0,type:"text",data:e.result};const i=e.addSteps;if(i&&i.length>0){console.log("[SW-WorkflowExecutor] Adding",i.length,"new steps from recovered response");const c=[];for(const l of i)r.steps.find(h=>h.id===l.id)||(r.steps.push({id:l.id,mcp:l.mcp,args:l.args,description:l.description,status:l.status||"pending"}),c.push(l));c.length>0&&this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:r.id,steps:c})}await y.saveWorkflow(r),this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:r.id,stepId:a.id,status:"completed",result:a.result})}else{a.status="failed",a.error=e.error||"Unknown error",a.result={success:!1,type:"error",error:a.error},await y.saveWorkflow(r),this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:r.id,stepId:a.id,status:"failed",error:a.error}),this.config.broadcast({type:"WORKFLOW_FAILED",workflowId:r.id,error:a.error}),await y.deletePendingToolRequest(e.requestId);return}await y.deletePendingToolRequest(e.requestId),console.log("[SW-WorkflowExecutor] Continuing workflow execution after recovery:",r.id),await this.executeWorkflow(r)}}async updateWorkflowStepForTask(e,t,o,n){for(const r of this.workflows.values()){const a=r.steps.find(i=>{var l;const c=i.result;return(c==null?void 0:c.taskId)===e||((l=c==null?void 0:c.taskIds)==null?void 0:l.includes(e))});if(a){a.status=t,t==="completed"&&o?a.result={...a.result,success:!0,data:o}:t==="failed"&&(a.error=n,a.result={...a.result,success:!1,error:n}),a.updatedAt=Date.now(),r.updatedAt=Date.now(),await y.saveWorkflow(r),this.broadcastStepStatus(r.id,a),r.status==="running"&&this.executeWorkflow(r.id);return}}}broadcastRecoveredWorkflows(){for(const e of this.workflows.values())this.config.broadcast({type:"WORKFLOW_RECOVERED",workflowId:e.id,workflow:e})}resendPendingToolRequests(){if(this.pendingToolRequests.size===0)return;const e=[];console.log("[SW-WorkflowExecutor] resendPendingToolRequests:",{pendingCount:this.pendingToolRequests.size,pendingTools:Array.from(this.pendingToolRequests.values()).map(t=>({toolName:t.requestInfo.toolName,workflowId:t.requestInfo.workflowId})),timestamp:new Date().toISOString()});for(const[,t]of this.pendingToolRequests){const{requestInfo:o}=t;if(e.includes(o.toolName)){console.log("[SW-WorkflowExecutor] Skipping resend for tool (already in progress):",{toolName:o.toolName,workflowId:o.workflowId,requestId:o.requestId});continue}this.config.broadcast({type:"MAIN_THREAD_TOOL_REQUEST",requestId:o.requestId,workflowId:o.workflowId,stepId:o.stepId,toolName:o.toolName,args:o.args})}}cancelAllPendingToolRequests(){if(this.pendingToolRequests.size!==0){for(const[e,t]of this.pendingToolRequests)t.reject(new Error("页面刷新导致请求中断,请重试"));this.pendingToolRequests.clear()}}async submitWorkflow(e){var o,n;console.log("[SW-WorkflowExecutor] submitWorkflow:",{workflowId:e.id,existingWorkflowsCount:this.workflows.size,hasContext:!!e.context,referenceImagesCount:((n=(o=e.context)==null?void 0:o.referenceImages)==null?void 0:n.length)||0,timestamp:new Date().toISOString()});const t=this.workflows.get(e.id);if(t){if(t.status==="running"||t.status==="pending"){console.log(`[SW-WorkflowExecutor] Re-claiming active workflow ${e.id}, status: ${t.status}`),this.broadcastWorkflowStatus(t),t.steps.forEach(r=>this.broadcastStepStatus(t.id,r));return}console.warn(`[SW-WorkflowExecutor] Workflow ${e.id} already exists with terminal status ${t.status}, skipping`),this.broadcastWorkflowStatus(t);return}console.log("[SW-WorkflowExecutor] ✓ New workflow, starting execution:",e.id),e.status="pending",e.updatedAt=Date.now(),this.workflows.set(e.id,e),await y.saveWorkflow(e),this.executeWorkflow(e.id)}async cancelWorkflow(e){const t=this.workflows.get(e);if(!t)return;const o=this.abortControllers.get(e);o&&(o.abort(),this.abortControllers.delete(e)),t.status="cancelled",t.updatedAt=Date.now(),this.runningWorkflows.delete(e),await y.saveWorkflow(t),await y.deletePendingToolRequestsByWorkflow(e),this.broadcastWorkflowStatus(t)}getWorkflow(e){return this.workflows.get(e)}getAllWorkflows(){return Array.from(this.workflows.values())}async executeWorkflow(e){console.log("[SW-WorkflowExecutor] executeWorkflow called:",{workflowId:e,timestamp:new Date().toISOString()});const t=this.workflows.get(e);if(!t){console.error(`[WorkflowExecutor] ✗ Workflow ${e} not found`);return}if(this.runningWorkflows.has(e)){console.warn(`[SW-WorkflowExecutor] Workflow ${e} is already running, skipping duplicate execution`);return}this.runningWorkflows.add(e),console.log(`[SW-WorkflowExecutor] ▶ Starting workflow execution: ${e}`);const o=new AbortController;this.abortControllers.set(e,o),t.status="running",t.updatedAt=Date.now(),await y.saveWorkflow(t),this.broadcastWorkflowStatus(t);try{let n=0;for(;;){const a=t.steps.filter(c=>c.status==="completed"||c.status==="failed"||c.status==="skipped"||c.status==="running"?!1:c.dependsOn&&c.dependsOn.length>0?c.dependsOn.every(l=>{const h=t.steps.find(m=>m.id===l);return h&&(h.status==="completed"||h.status==="skipped")}):!0),i=t.steps.some(c=>c.status==="running");if(a.length===0){if(i||t.steps.every(l=>l.status==="completed"||l.status==="failed"||l.status==="skipped"))break;console.warn("[WorkflowExecutor] Workflow stuck: no executable steps and none running");break}for(const c of a){if(o.signal.aborted)throw new Error("Workflow cancelled");if(n++,await this.executeStep(t,c,o.signal),c.status==="failed")throw console.error(`[WorkflowExecutor] ✗ Step ${c.id} failed: ${c.error}`),new Error(`Step ${c.id} failed: ${c.error}`);c.status}}t.steps.every(a=>a.status==="completed"||a.status==="failed"||a.status==="skipped")?(t.status="completed",t.completedAt=Date.now(),t.updatedAt=Date.now(),await y.saveWorkflow(t),this.config.broadcast({type:"WORKFLOW_COMPLETED",workflowId:e,workflow:t})):await y.saveWorkflow(t)}catch(n){console.error(`[WorkflowExecutor] ✗ Workflow ${e} failed:`,n),t.status="failed",t.error=n.message,t.updatedAt=Date.now(),await y.saveWorkflow(t),this.config.broadcast({type:"WORKFLOW_FAILED",workflowId:e,error:n.message})}finally{this.runningWorkflows.delete(e),this.abortControllers.delete(e)}}replaceImagePlaceholders(e,t){if(!t||t.length===0)return e;const o=n=>{if(typeof n=="string"){let r=n.replace(/\[图片(\d+)\]/g,(a,i)=>{const c=parseInt(i,10)-1;return c>=0&&c<t.length?t[c]:a});return r=r.replace(/\[Image\s*(\d+)\]/gi,(a,i)=>{const c=parseInt(i,10)-1;return c>=0&&c<t.length?t[c]:a}),r}if(Array.isArray(n))return n.map(r=>o(r));if(n&&typeof n=="object"){const r={};for(const[a,i]of Object.entries(n))r[a]=o(i);return r}return n};return o(e)}async executeStep(e,t,o){var l,h,m,S,w,g;console.log("[SW-WorkflowExecutor] executeStep:",{workflowId:e.id,stepId:t.id,mcp:t.mcp,hasContext:!!e.context,referenceImagesCount:((h=(l=e.context)==null?void 0:l.referenceImages)==null?void 0:h.length)||0,timestamp:new Date().toISOString()});const n=Date.now(),r=((m=e.context)==null?void 0:m.referenceImages)||[];(t.mcp==="generate_image"||t.mcp==="generate_video")&&console.log("[SW-WorkflowExecutor] Image/Video step args before processing:",{stepId:t.id,referenceImagesInContext:r.length,referenceImagesValues:r.slice(0,2).map(d=>d.substring(0,50)+"..."),argsReferenceImages:t.args.referenceImages});const a=this.replaceImagePlaceholders(t.args,r),i=JSON.stringify(t.args),c=JSON.stringify(a);i!==c?(console.log("[SW-WorkflowExecutor] ✓ Replaced image placeholders:",{stepId:t.id,referenceImagesCount:r.length}),t.args=a):r.length>0&&(t.mcp==="generate_image"||t.mcp==="generate_video")&&console.log("[SW-WorkflowExecutor] No placeholders replaced (args unchanged):",{stepId:t.id,referenceImagesCount:r.length}),t.status="running",await y.saveWorkflow(e),this.broadcastStepStatus(e.id,t);try{if(Qe(t.mcp)||!Rt(t.mcp)){const d=await this.requestMainThreadTool(e.id,t.id,t.mcp,t.args);if(!d.success)throw new Error(d.error||"Main thread tool execution failed");if(d.addSteps&&d.addSteps.length>0){const f=[];for(const p of d.addSteps)e.steps.find(E=>E.id===p.id)||(e.steps.push({id:p.id,mcp:p.mcp,args:p.args,description:p.description,status:p.status}),f.push(p));f.length>0&&(await y.saveWorkflow(e),this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:e.id,steps:f}))}const u=d.result;if((t.mcp==="generate_image"||t.mcp==="generate_video")&&d.taskId){t.result={success:!0,type:t.mcp==="generate_image"?"image":"video",data:u,taskId:d.taskId,taskIds:d.taskIds},t.status="running",t.duration=Date.now()-n,this.broadcastStepStatus(e.id,t);return}t.result={success:!0,type:(u==null?void 0:u.type)||"text",data:u}}else{const d={geminiConfig:this.config.geminiConfig,videoConfig:this.config.videoConfig,signal:o,onProgress:(f,p)=>{},onRemoteId:f=>{}},u=await Ve(t.mcp,t.args,d);if(u.success&&u.type==="canvas"&&((S=u.data)!=null&&S.delegateToMainThread)){const f=await this.requestCanvasOperation(u.data.operation,u.data.args);if(!f.success)throw new Error(f.error||"Canvas operation failed");t.result={success:!0,type:"canvas",data:{completed:!0}}}else if(u.success&&u.type==="image"&&((w=u.data)!=null&&w.url)){const f=u.data,p=await this.requestCanvasOperation("canvas_insert",{items:[{type:"image",url:f.url}]});p.success||console.warn("[WorkflowExecutor] Failed to insert image to canvas:",p.error),t.result={success:!0,type:"image",data:u.data}}else if(u.success&&u.type==="video"&&((g=u.data)!=null&&g.url)){const f=u.data,p=await this.requestCanvasOperation("canvas_insert",{items:[{type:"video",url:f.url}]});p.success||console.warn("[WorkflowExecutor] Failed to insert video to canvas:",p.error),t.result={success:!0,type:"video",data:u.data}}else if(t.result={success:u.success,type:u.type||"text",data:u.data,error:u.error},!u.success)throw new Error(u.error||"Step execution failed");if(u.addSteps&&u.addSteps.length>0){console.log(`[SW-WorkflowExecutor] Adding ${u.addSteps.length} new steps from ${t.mcp}`);const f=[];for(const p of u.addSteps)e.steps.find(E=>E.id===p.id)||(e.steps.push({id:p.id,mcp:p.mcp,args:p.args,description:p.description,status:p.status}),f.push(p));f.length>0&&this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:e.id,steps:f})}}t.status="completed",t.duration=Date.now()-n}catch(d){t.status="failed",t.error=d.message,t.duration=Date.now()-n,t.result={success:!1,type:"error",error:d.message}}await y.saveWorkflow(e),this.broadcastStepStatus(e.id,t)}async requestMainThreadTool(e,t,o,n){if(this.config.requestMainThreadTool)return this.config.requestMainThreadTool(e,t,o,n);const r=`tool_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return new Promise((a,i)=>{const c=setTimeout(()=>{this.pendingToolRequests.delete(r),i(new Error(`Main thread tool request timed out: ${o}`))},3e5);this.pendingToolRequests.set(r,{resolve:l=>{clearTimeout(c),y.deletePendingToolRequest(r),a(l)},reject:l=>{clearTimeout(c),y.deletePendingToolRequest(r),i(l)},requestInfo:{requestId:r,workflowId:e,stepId:t,toolName:o,args:n},timeout:c}),y.savePendingToolRequest({requestId:r,workflowId:e,stepId:t,toolName:o,args:n,createdAt:Date.now()}),this.config.broadcast({type:"MAIN_THREAD_TOOL_REQUEST",requestId:r,workflowId:e,stepId:t,toolName:o,args:n})})}async requestCanvasOperation(e,t){if(this.config.requestCanvasOperation)return this.config.requestCanvasOperation(e,t);const o=`canvas_${Date.now()}_${Math.random().toString(36).substr(2,9)}`;return this.config.broadcast({type:"CANVAS_OPERATION_REQUEST",requestId:o,operation:e,params:t}),{success:!0}}broadcastWorkflowStatus(e){this.config.broadcast({type:"WORKFLOW_STATUS",workflowId:e.id,status:e.status,updatedAt:e.updatedAt})}broadcastStepStatus(e,t){this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:e,stepId:t.id,status:t.status,result:t.result,error:t.error,duration:t.duration})}}function Wt(s=0){return`tc_${Date.now()}_${s}_${Math.random().toString(36).substr(2,9)}`}function te(s){const e=s.trim();try{return JSON.parse(e)}catch{try{return JSON.parse(Zs(e))}catch{return null}}}function Dt(s){let e=s;return e=e.replace(/<think>[\s\S]*?<\/think>\s*/gi,""),e=e.replace(/```(?:json)?\s*\n?/gi,"").replace(/\n?```/gi,""),e.trim()}function Xs(s){const e=s.trim();if(!e.startsWith("{")||!e.endsWith("}")||!e.includes('"content"')||!e.includes('"next"'))return!1;let t=0,o=0,n=!1,r=!1;for(const a of e){if(r){r=!1;continue}if(a==="\\"){r=!0;continue}if(a==='"'){n=!n;continue}n||(a==="{"?t++:a==="}"?t--:a==="["?o++:a==="]"&&o--)}return t===0&&o===0}function Lt(s){const e=Dt(s);if(!Xs(e))return null;let t=te(e);if(!t){const r=e.match(/\{\s*"content"\s*:\s*"[^"]*"\s*,\s*"next"\s*:\s*\[[\s\S]*?\]\s*\}/);r&&(t=te(r[0]))}if(!t){const r=e.match(/\{[\s\S]*"content"[\s\S]*"next"[\s\S]*\}/);r&&(t=te(r[0]))}if(!t||typeof t.content!="string")return null;const n=(Array.isArray(t.next)?t.next:[]).filter(r=>typeof r=="object"&&r!==null&&typeof r.mcp=="string"&&typeof r.args=="object").map(r=>({mcp:r.mcp,args:r.args}));return{content:t.content,next:n}}function Js(s){const e=Lt(s);if(e&&e.next.length>0)return e.next.map((a,i)=>({id:Wt(i),name:a.mcp,arguments:a.args}));const t=[],o=a=>{if(!a.name||typeof a.name!="string")return null;const i=a.arguments||a.params||a.parameters||{};return{id:Wt(),name:a.name,arguments:typeof i=="object"&&i!==null?i:{}}},n=/```tool_call\s*\n?([\s\S]*?)\n?```/gi;let r;for(;(r=n.exec(s))!==null;){const a=te(r[1]);if(a){const i=o(a);i&&t.push(i)}}if(t.length===0){const a=/```(?:json)?\s*\n?([\s\S]*?)\n?```/gi;for(;(r=a.exec(s))!==null;){const i=te(r[1]);if(i){const c=o(i);c&&t.push(c)}}}if(t.length===0){const a=/<tool_call>([\s\S]*?)<\/tool_call>/gi;for(;(r=a.exec(s))!==null;){const i=te(r[1]);if(i){const c=o(i);c&&t.push(c)}}}if(t.length===0){const a=/\{[\s\S]*?"name"\s*:\s*"(?:generate_image|generate_video|generate_grid_image|generate_photo_wall)"[\s\S]*?\}/g;for(;(r=a.exec(s))!==null;){const i=te(r[0]);if(i){const c=o(i);if(c){t.push(c);break}}}}return t}function Ys(s){const e=Lt(s);if(e)return e.content;let t=Dt(s);return t=t.replace(/```tool_call\s*\n?[\s\S]*?\n?```/gi,""),t=t.replace(/<tool_call>[\s\S]*?<\/tool_call>/gi,""),t=t.replace(/```(?:json)?\s*\n?\s*\{\s*"name"\s*:[\s\S]*?\n?```/gi,""),t=t.replace(/\{\s*"content"\s*:\s*"[^"]*"\s*,\s*"next"\s*:\s*\[[\s\S]*?\]\s*\}/gi,""),t=t.replace(/\n{3,}/g,`
|
|
3
|
+
|
|
4
|
+
`),t.trim()}function Zs(s){let e=s.trim();const t=e.indexOf("{");t>0&&(e=e.substring(t));const o=e.lastIndexOf("}");return o<e.length-1&&o>0&&(e=e.substring(0,o+1)),e=e.replace(/:\s*"([^"]*)\n([^"]*)"/g,(n,r,a)=>`: "${r}\\n${a}"`),e=e.replace(/'([^']*?)'/g,(n,r)=>!r.includes(":")||r.length>50?`"${r}"`:n),e=e.replace(/([{,]\s*)(\w+)(\s*:)/g,'$1"$2"$3'),e=e.replace(/,(\s*[}\]])/g,"$1"),e=e.replace(/,\s*,/g,","),e=e.replace(/\/\/[^\n]*/g,""),e=e.replace(/\/\*[\s\S]*?\*\//g,""),e=e.replace(/:\s*undefined\b/g,": null"),e}function eo(s){return Js(s).map(t=>({...t,status:"pending"}))}class to{constructor(e){this.workflows=new Map,this.abortControllers=new Map,this.workflowClients=new Map,this.pendingToolRequests=new Map,this.storageRestored=!1,this.config=e,this.restoreFromStorage()}async restoreFromStorage(){try{const e=await y.getAllChatWorkflows();for(const t of e){if(t.status==="completed"||t.status==="cancelled"||t.status==="failed"){this.workflows.set(t.id,t);continue}await this.handleInterruptedWorkflow(t)}this.storageRestored=!0}catch(e){console.error("[ChatWorkflowHandler] Failed to restore from storage:",e),this.storageRestored=!0}}async handleInterruptedWorkflow(e){let t;switch(e.status){case"streaming":t="AI 响应流传输时中断,请重试";break;case"parsing":t="工具调用解析时中断,请重试";break;case"executing_tools":t="工具执行时中断,请重试";break;case"pending":t="工作流尚未开始执行,请重试";break;default:t="工作流执行时中断,请重试"}e.status="failed",e.error=t,e.updatedAt=Date.now();for(const o of e.toolCalls)(o.status==="running"||o.status==="pending")&&(o.status="failed",o.result={success:!1,error:"Service Worker 重启导致执行中断"});this.workflows.set(e.id,e),await y.saveChatWorkflow(e)}updateConfig(e){this.config={...this.config,...e}}async startWorkflow(e,t,o){console.log("[SW-ChatWorkflow] ▶ startWorkflow:",{chatId:e,clientId:o,existingWorkflows:this.workflows.size,timestamp:new Date().toISOString()});const n=this.workflows.get(e);if(n){if(n.status==="streaming"||n.status==="pending"||n.status==="executing_tools"){console.log("[SW-ChatWorkflow] Re-claiming active workflow:",{chatId:e,status:n.status}),this.broadcastStatus(n);return}console.warn("[SW-ChatWorkflow] Workflow already exists, skipping:",{chatId:e,status:n.status}),this.broadcastStatus(n);return}this.workflowClients.set(e,o);const r={id:e,status:"pending",params:t,content:"",toolCalls:[],createdAt:Date.now(),updatedAt:Date.now()};this.workflows.set(e,r),await y.saveChatWorkflow(r);const a=new AbortController;this.abortControllers.set(e,a),this.executeWorkflow(r,a.signal)}async cancelWorkflow(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e));const o=this.workflows.get(e);o&&(o.status="cancelled",o.updatedAt=Date.now(),await y.saveChatWorkflow(o),this.broadcastStatus(o))}broadcastRecoveredWorkflows(){for(const e of this.workflows.values())this.config.broadcast({type:"CHAT_WORKFLOW_RECOVERED",chatId:e.id,workflow:e})}getWorkflow(e){return this.workflows.get(e)}getAllWorkflows(){return Array.from(this.workflows.values()).filter(e=>e.status!=="completed"&&e.status!=="failed"&&e.status!=="cancelled")}handleMainThreadToolResponse(e){const t=this.pendingToolRequests.get(e.requestId);t&&(this.pendingToolRequests.delete(e.requestId),t.resolve(e))}async executeWorkflow(e,t){try{e.status="streaming",await y.saveChatWorkflow(e),this.broadcastStatus(e);const o=await this.streamChat(e,t);if(e.content=o,t.aborted)throw new Error("Workflow cancelled");e.status="parsing",await y.saveChatWorkflow(e),this.broadcastStatus(e);const n=eo(o),r=Ys(o);e.toolCalls=n,e.aiAnalysis=r,n.length>0&&this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_CALLS",chatId:e.id,aiAnalysis:r,toolCalls:n}),n.length>0&&(e.status="executing_tools",await y.saveChatWorkflow(e),this.broadcastStatus(e),await this.executeTools(e,t)),e.status="completed",e.completedAt=Date.now(),e.updatedAt=Date.now(),await y.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_COMPLETE",chatId:e.id,content:e.content,aiAnalysis:e.aiAnalysis,toolCalls:e.toolCalls})}catch(o){o.message==="Workflow cancelled"?e.status="cancelled":(e.status="failed",e.error=o.message,this.config.broadcast({type:"CHAT_WORKFLOW_FAILED",chatId:e.id,error:o.message})),e.updatedAt=Date.now(),await y.saveChatWorkflow(e)}finally{this.abortControllers.delete(e.id)}}async streamChat(e,t){var g,d,u,f,p,E;const{params:o}=e,{geminiConfig:n}=this.config,r=this.convertToGeminiMessages(o),a=o.temporaryModel||n.modelName||"gemini-2.5-flash";console.log("[SW-ChatWorkflow] streamChat called:",{workflowId:e.id,model:a,messagesCount:r.length,timestamp:new Date().toISOString()});const i={model:a,messages:r,stream:!0},{debugFetch:c}=await Promise.resolve().then(()=>P),l=await c(`${n.baseUrl}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`},body:JSON.stringify(i),signal:t},{label:`💬 工作流对话 (${a})`,logRequestBody:!0,isStreaming:!0});if(!l.ok){const T=await l.text();throw new Error(`Chat request failed: ${l.status} - ${T}`)}if(!l.body)throw new Error("No response body");const h=l.body.getReader(),m=new TextDecoder;let S="",w="";try{for(;;){const{done:T,value:_}=await h.read();if(T)break;w+=m.decode(_,{stream:!0});const C=w.split(`
|
|
5
|
+
`);w=C.pop()||"";for(const R of C)if(R.startsWith("data: ")){const x=R.slice(6).trim();if(x==="[DONE]")continue;try{const ee=(u=(d=(g=JSON.parse(x).choices)==null?void 0:g[0])==null?void 0:d.delta)==null?void 0:u.content;ee&&(S+=ee,this.config.broadcast({type:"CHAT_WORKFLOW_STREAM",chatId:e.id,content:S}))}catch{}}}if(w.startsWith("data: ")){const T=w.slice(6).trim();if(T&&T!=="[DONE]")try{const C=(E=(p=(f=JSON.parse(T).choices)==null?void 0:f[0])==null?void 0:p.delta)==null?void 0:E.content;C&&(S+=C,this.config.broadcast({type:"CHAT_WORKFLOW_STREAM",chatId:e.id,content:S}))}catch{}}}finally{h.releaseLock()}if(l.__debugLogId&&S){const{updateLogResponseBody:T}=await Promise.resolve().then(()=>P);T(l.__debugLogId,S)}return S}async executeTools(e,t){const o=this.workflowClients.get(e.id);for(const n of e.toolCalls){if(t.aborted)throw new Error("Workflow cancelled");n.status="running",this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_START",chatId:e.id,toolCallId:n.id,toolName:n.name});try{let r;if(Qe(n.name)||!Rt(n.name)){if(!o)throw new Error("No client ID found for workflow");const a=await this.config.requestMainThreadTool(o,e.id,n.id,n.name,n.arguments);r={success:a.success,data:a.result,error:a.error}}else{const a={geminiConfig:this.config.geminiConfig,videoConfig:this.config.videoConfig,signal:t},i=await Ve(n.name,n.arguments,a);r={success:i.success,data:i.data,error:i.error,taskId:i.taskId}}n.status=r.success?"completed":"failed",n.result=r,await y.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_COMPLETE",chatId:e.id,toolCallId:n.id,success:r.success,result:r.data,error:r.error,taskId:r.taskId})}catch(r){n.status="failed",n.result={success:!1,error:r.message},await y.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_COMPLETE",chatId:e.id,toolCallId:n.id,success:!1,error:r.message})}}}convertToGeminiMessages(e){var o;const t=[];e.systemPrompt&&t.push({role:"system",content:[{type:"text",text:e.systemPrompt}]});for(const n of e.messages){const r=[];if(n.content&&r.push({type:"text",text:n.content}),n.attachments)for(const a of n.attachments)a.type==="image"&&r.push({type:"image_url",image_url:{url:`data:${a.mimeType};base64,${a.data}`}});t.push({role:n.role,content:r})}if(e.newContent||(o=e.attachments)!=null&&o.length){const n=[];if(e.newContent&&n.push({type:"text",text:e.newContent}),e.attachments)for(const r of e.attachments)r.type==="image"&&n.push({type:"image_url",image_url:{url:`data:${r.mimeType};base64,${r.data}`}});t.push({role:"user",content:n})}return t}broadcastStatus(e){this.config.broadcast({type:"CHAT_WORKFLOW_STATUS",chatId:e.id,status:e.status,updatedAt:e.updatedAt})}}let O=null,K=null,ie=null,ce=null;function Xe(s,e,t){ie=e,ce=t,O=new Qs({geminiConfig:e,videoConfig:t,broadcast:n=>de(n)});const o=je();o&&o.setTaskStatusChangeCallback((n,r,a,i)=>{O==null||O.updateWorkflowStepForTask(n,r,a,i)}),K=new to({geminiConfig:e,videoConfig:t,broadcast:n=>de(n),sendToClient:(n,r)=>Ye(n,r),requestMainThreadTool:async(n,r,a,i,c)=>{const l=`chat_tool_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return new Promise((h,m)=>{const S=setTimeout(()=>{le.delete(l),y.deletePendingToolRequest(l),m(new Error(`Tool request timed out: ${i}`))},3e5);le.set(l,{resolve:w=>{clearTimeout(S),y.deletePendingToolRequest(l),h(w)},reject:w=>{clearTimeout(S),y.deletePendingToolRequest(l),m(w)},requestInfo:{requestId:l,chatId:r,toolCallId:a,toolName:i,args:c,clientId:n},timeout:S}),y.savePendingToolRequest({requestId:l,workflowId:r,stepId:a,toolName:i,args:c,createdAt:Date.now(),clientId:n}),Ye(n,{type:"MAIN_THREAD_TOOL_REQUEST",requestId:l,workflowId:r,stepId:a,toolName:i,args:c})})}})}const le=new Map;function so(s,e){if(!O){console.warn("[WorkflowHandler] Not initialized");return}s&&(ie={...ie||{},...s}),e&&(ce={...ce||{},...e}),!(!ie||!ce)&&(O.updateConfig({geminiConfig:ie,videoConfig:ce}),K&&K.updateConfig({geminiConfig:ie,videoConfig:ce}))}function oo(s){var t,o;if(!s||typeof s!="object")return!1;const e=s;return((t=e.type)==null?void 0:t.startsWith("WORKFLOW_"))||((o=e.type)==null?void 0:o.startsWith("CHAT_WORKFLOW_"))||!1}function Je(s,e){if(s.type.startsWith("CHAT_WORKFLOW_")){ro(s,e);return}if(!O){console.error("[WorkflowHandler] ✗ Not initialized, ignoring message:",s.type);return}const t=s;switch(t.type){case"WORKFLOW_SUBMIT":console.log("[SW-WorkflowHandler] ▶ WORKFLOW_SUBMIT received:",{workflowId:t.workflow.id,clientId:e,timestamp:new Date().toISOString()}),O.submitWorkflow(t.workflow);break;case"WORKFLOW_CANCEL":O.cancelWorkflow(t.workflowId);break;case"WORKFLOW_GET_STATUS":{const o=O.getWorkflow(t.workflowId);de({type:"WORKFLOW_STATUS_RESPONSE",workflowId:t.workflowId,workflow:o||null});break}case"WORKFLOW_GET_ALL":{const o=O.getAllWorkflows();de({type:"WORKFLOW_ALL_RESPONSE",workflows:o});break}}}function ro(s,e){var t;if(!K){console.error("[WorkflowHandler] ✗ Chat workflow handler not initialized");return}switch(s.type){case"CHAT_WORKFLOW_START":console.log("[SW-Workflow] ▶ CHAT_WORKFLOW_START received:",{chatId:s.chatId,clientId:e,stepsCount:(t=s.params.steps)==null?void 0:t.length,timestamp:new Date().toISOString()}),K.startWorkflow(s.chatId,s.params,e);break;case"CHAT_WORKFLOW_CANCEL":K.cancelWorkflow(s.chatId);break;case"CHAT_WORKFLOW_GET_STATUS":{const o=K.getWorkflow(s.chatId);de({type:"CHAT_WORKFLOW_STATUS_RESPONSE",chatId:s.chatId,workflow:o||null});break}case"CHAT_WORKFLOW_GET_ALL":{const o=K.getAllWorkflows();de({type:"CHAT_WORKFLOW_ALL_RESPONSE",workflows:o});break}}}async function no(s){const e=le.get(s.requestId);if(e){le.delete(s.requestId),e.resolve(s);return}if(await y.deletePendingToolRequest(s.requestId),!O){console.error("[WorkflowHandler] ✗ Not initialized, ignoring tool response");return}O.handleMainThreadToolResponse(s)}function ao(){if(O&&(O.broadcastRecoveredWorkflows(),O.resendPendingToolRequests()),K&&K.broadcastRecoveredWorkflows(),le.size!==0)for(const[,s]of le){const{requestInfo:e}=s;Ye(e.clientId,{type:"MAIN_THREAD_TOOL_REQUEST",requestId:e.requestId,workflowId:e.chatId,stepId:e.toolCallId,toolName:e.toolName,args:e.args})}}function de(s){St(s)}async function Ye(s,e){await Ie(s,e)||St(e)}const Ce=[],io=100;let Ze=!1,Q=null;function co(s){Ze=s}function et(){return Ze}function It(s){Q=s}function Ot(){return[...Ce]}function lo(s,e){const t=Ce.find(o=>o.id===s);t&&(t.responseBody=e.length>5e3?e.substring(0,5e3)+"...(truncated)":e,Q&&Q({...t}))}async function uo(s){return new Promise((e,t)=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.onerror=t,o.readAsDataURL(s)})}async function ho(s){const e=[];for(const[t,o]of s.entries())if(o instanceof Blob){const n={name:t,value:`[${o.type||"binary"}] ${o.size} bytes`,isFile:!0,mimeType:o.type};if(o.type.startsWith("image/")&&o.size<5*1024*1024)try{n.dataUrl=await uo(o)}catch{}o instanceof File&&(n.fileName=o.name),e.push(n)}else e.push({name:t,value:String(o).length>500?String(o).substring(0,500)+"...":String(o)});return e}async function fo(s,e,t){if(!Ze)return fetch(s,e);const o=typeof s=="string"?s:s instanceof URL?s.href:s.url,n=(e==null?void 0:e.method)||"GET",r=Date.now(),a=Math.random().toString(36).substring(2,10);let i,c,l;if(e!=null&&e.body){if(e.body instanceof FormData)try{c=await ho(e.body)}catch{i="[FormData - unable to parse]"}else if(t!=null&&t.logRequestBody)try{const m=typeof e.body=="string"?e.body:JSON.stringify(e.body),S=/data:image\/([^;]+);base64,([A-Za-z0-9+/=]+)/g;let w,g=0;for(l=[];(w=S.exec(m))!==null;){const f=`image/${w[1]}`,p=w[2];p.length>1e3&&(l.push({key:`image[${g}]`,dataUrl:`data:${f};base64,${p}`,mimeType:f,size:Math.round(p.length*.75/1024)}),g++)}l.length===0&&(l=void 0);let d=m.replace(/data:image\/([^;]+);base64,[A-Za-z0-9+/=]+/g,(f,p)=>`[📷 image/${p}]`);i=!o.includes("/chat/completions")&&d.length>3e3?d.substring(0,3e3)+"...(truncated)":d}catch{i="[unable to serialize body]"}}const h={id:a,timestamp:r,url:o,method:n,requestType:"sw-internal",details:(t==null?void 0:t.label)||`SW Internal: ${n} ${new URL(o).pathname}`,requestBody:i,formData:c,base64Images:l,isStreaming:t==null?void 0:t.isStreaming};Ce.unshift(h),Ce.length>io&&Ce.pop(),Q&&Q({...h});try{const m=await fetch(s,e);if(h.status=m.status,h.statusText=m.statusText,h.duration=Date.now()-r,t!=null&&t.isStreaming)h.responseBody="[流式响应 - 数据通过 SSE/Stream 实时传输,无法捕获完整响应体]";else if(t!=null&&t.logResponseBody)try{const S=m.headers.get("content-type")||"";if(S.includes("application/json")||S.includes("text/")){const g=await m.clone().text();h.responseBody=g.length>2e3?g.substring(0,2e3)+"...(truncated)":g}}catch{}return Q&&Q({...h}),m.__debugLogId=a,m}catch(m){const S=m.message||String(m);let w="NETWORK_ERROR";throw S.includes("ERR_CONNECTION_CLOSED")?w="ERR_CONNECTION_CLOSED":S.includes("ERR_CONNECTION_REFUSED")?w="ERR_CONNECTION_REFUSED":S.includes("ERR_CONNECTION_RESET")?w="ERR_CONNECTION_RESET":S.includes("ERR_CONNECTION_TIMED_OUT")||S.includes("timeout")?w="ERR_TIMEOUT":S.includes("ERR_NAME_NOT_RESOLVED")?w="ERR_DNS_FAILED":S.includes("ERR_INTERNET_DISCONNECTED")?w="ERR_OFFLINE":S.includes("ERR_SSL")||S.includes("certificate")?w="ERR_SSL":S.includes("Failed to fetch")?w="FETCH_FAILED":(S.includes("AbortError")||S.includes("aborted"))&&(w="ABORTED"),h.status=0,h.statusText=w,h.error=S,h.duration=Date.now()-r,Q&&Q({...h}),m}}const P=Object.freeze(Object.defineProperty({__proto__:null,debugFetch:fo,getInternalFetchLogs:Ot,isDebugFetchEnabled:et,setDebugFetchBroadcast:It,setDebugFetchEnabled:co,updateLogResponseBody:lo},Symbol.toStringTag,{value:"Module"})),A=self;zs(A),bs();const se={log:console.log.bind(console),info:console.info.bind(console),warn:console.warn.bind(console),error:console.error.bind(console)};function go(){console.log=(...s)=>{se.log(...s),et()&&Me("log",s)},console.info=(...s)=>{se.info(...s),et()&&Me("info",s)},console.warn=(...s)=>{se.warn(...s),Me("warn",s)},console.error=(...s)=>{se.error(...s),Me("error",s)}}function Me(s,e){const t=e.map(n=>{if(typeof n=="object")try{return JSON.stringify(n)}catch{return String(n)}return String(n)}).join(" "),o=t.startsWith("[SW]")||t.startsWith("[SW-")?t:`[SW] ${t}`;typeof tt=="function"&&tt({logLevel:s,logMessage:o,logSource:"service-worker"})}let tt=null;go(),It(s=>{A.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_DEBUG_LOG",entry:{...s,type:"fetch"}})})})}),Promise.resolve().then(()=>L).then(({setLLMApiLogBroadcast:s})=>{s(e=>{A.clients.matchAll().then(t=>{t.forEach(o=>{o.postMessage({type:"SW_DEBUG_LLM_API_LOG",log:e})})})})});const ue="0.5.14",Pe=`drawnix-v${ue}`,k="drawnix-images",he=`drawnix-static-v${ue}`,ve="drawnix-fonts",po="/__aitu_cache__/",mo="/asset-library/",kt=location.hostname==="localhost"||location.hostname==="127.0.0.1",wo=[{hostname:"google.datas.systems",pathPattern:"response_images",fallbackDomain:"cdn.i666.fun"},{hostname:"googlecdn2.datas.systems",pathPattern:"response_images",fallbackDomain:"googlecdn2.i666.fun"},{hostname:"filesystem.i666.fun",pathPattern:"response_images",fallbackDomain:"filesystem.i666.fun"}],So=/\.(jpg|jpeg|png|gif|webp|svg|bmp|ico)$/i,yo=/\.(mp4|webm|ogg|mov|avi|mkv|flv|wmv|m4v)$/i,F=new Map,oe=new Map,xt=30*1e3,_e=new Map,q=new Map,To=300*1e3,Mt=10,fe=new Set,ge=new Set,Eo=3600*1e3,st=new Map;function Pt(s){ge.add(s),st.set(s,Date.now()),console.warn(`Service Worker: 标记 ${s} 为 CORS 问题域名,后续请求将跳过 SW`)}function Co(s){if(!ge.has(s))return!1;const e=st.get(s);return e&&Date.now()-e>Eo?(ge.delete(s),st.delete(s),!1):!0}const be=[],_o=7,j=[],bo=500;let G=!1,pe=0;const Ao=15e3;let V=null;function vt(){if(!G)return;const s=Date.now();pe>0&&s-pe>Ao?(se.log("Service Worker: Debug heartbeat timeout, auto-disabling debug mode"),G=!1,pe=0,$e(!1),Promise.resolve().then(()=>P).then(({setDebugFetchEnabled:e})=>{e(!1)}),A.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_DEBUG_DISABLED"})})}),V&&(clearTimeout(V),V=null)):G&&(V=setTimeout(vt,5e3))}function $(s){if(!G)return"";const e=Math.random().toString(36).substring(2,10),t={...s,id:e,timestamp:Date.now()};return j.unshift(t),j.length>bo&&j.pop(),Bt(t),e}function M(s,e){if(!G||!s)return;const t=j.find(o=>o.id===s);t&&(Object.assign(t,e),Bt(t))}async function Bt(s){try{(await A.clients.matchAll()).forEach(t=>{t.postMessage({type:"SW_DEBUG_LOG",entry:s})})}catch{}}function Be(){return new Promise((s,e)=>{const t=indexedDB.open("ConsoleLogDB",1);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const n=o.target.result;if(!n.objectStoreNames.contains("logs")){const r=n.createObjectStore("logs",{keyPath:"id"});r.createIndex("timestamp","timestamp",{unique:!1}),r.createIndex("logLevel","logLevel",{unique:!1})}}})}async function Ro(s){try{const e=await Be(),t=e.transaction(["logs"],"readwrite");return t.objectStore("logs").add(s),new Promise((n,r)=>{t.oncomplete=()=>{e.close(),n()},t.onerror=()=>{e.close(),r(t.error)}})}catch(e){console.warn("Service Worker: 无法保存控制台日志:",e)}}async function Nt(){try{const s=await Be(),o=s.transaction(["logs"],"readonly").objectStore("logs").index("timestamp");return new Promise((n,r)=>{const a=o.openCursor(null,"prev"),i=[];a.onsuccess=()=>{const c=a.result;c?(i.push(c.value),c.continue()):(s.close(),n(i))},a.onerror=()=>{s.close(),r(a.error)}})}catch(s){return console.warn("Service Worker: 无法加载控制台日志:",s),[]}}async function Wo(){try{const s=await Be(),o=s.transaction(["logs"],"readwrite").objectStore("logs").index("timestamp"),n=Date.now()-_o*24*60*60*1e3,r=IDBKeyRange.upperBound(n);return new Promise((a,i)=>{const c=o.openCursor(r);let l=0;c.onsuccess=()=>{const h=c.result;h?(h.delete(),l++,h.continue()):(s.close(),l>0&&console.log(`Service Worker: 清理了 ${l} 条过期控制台日志`),a(l))},c.onerror=()=>{s.close(),i(c.error)}})}catch(s){return console.warn("Service Worker: 无法清理过期日志:",s),0}}async function Ut(){try{const s=await Be(),e=s.transaction(["logs"],"readwrite");return e.objectStore("logs").clear(),new Promise((o,n)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),n(e.error)}})}catch(s){console.warn("Service Worker: 无法清空控制台日志:",s)}}function qt(s){if(!G)return;const t={id:Math.random().toString(36).substring(2,10),timestamp:Date.now(),type:"console",...s};be.unshift(t),Ro(t),Do(t)}tt=qt;async function Do(s){try{(await A.clients.matchAll()).forEach(t=>{t.postMessage({type:"SW_CONSOLE_LOG",entry:s})})}catch{}}function Lo(){let s=0;return q.forEach(e=>{e.blob&&(s+=e.blob.size)}),s}function Ne(){return{version:ue,cacheNames:[Pe,k,he,ve],pendingImageRequests:F.size,pendingVideoRequests:_e.size,videoBlobCacheSize:q.size,videoBlobCacheTotalBytes:Lo(),completedImageRequestsSize:oe.size,failedDomainsCount:fe.size,failedDomains:Array.from(fe),corsFailedDomainsCount:ge.size,corsFailedDomains:Array.from(ge),debugLogsCount:j.length,consoleLogsCount:be.length,debugModeEnabled:G,workflowHandlerInitialized:re,memoryStats:{pendingRequestsMapSize:F.size,completedRequestsMapSize:oe.size,videoBlobCacheMapSize:q.size,failedDomainsSetSize:fe.size,corsFailedDomainsSetSize:ge.size,debugLogsArraySize:j.length,consoleLogsArraySize:be.length}}}function Gt(s){for(const e of wo)if(s.hostname===e.hostname&&s.pathname.includes(e.pathPattern))return e;return null}function Io(s,e){return So.test(s.pathname)||e.destination==="image"||Gt(s)!==null}function Oo(s,e){return yo.test(s.pathname)||e.destination==="video"||s.pathname.includes("/video/")||s.hash.startsWith("#merged-video-")||s.hash.includes("video")}function ko(s,e){return s.hostname==="fonts.googleapis.com"||s.hostname==="fonts.gstatic.com"?!0:/\.(woff|woff2|ttf|otf|eot)$/i.test(s.pathname)||e.destination==="font"}async function xo(){try{const s=indexedDB.open("ServiceWorkerDB",1);return new Promise((e,t)=>{s.onerror=()=>t(s.error),s.onsuccess=()=>{const o=s.result;if(o.objectStoreNames.contains("failedDomains")){const a=o.transaction(["failedDomains"],"readonly").objectStore("failedDomains").getAll();a.onsuccess=()=>{a.result.forEach(c=>fe.add(c.domain)),e()},a.onerror=()=>t(a.error)}else e()},s.onupgradeneeded=o=>{const n=o.target.result;n.objectStoreNames.contains("failedDomains")||n.createObjectStore("failedDomains",{keyPath:"domain"})}})}catch(s){console.warn("Service Worker: 无法加载失败域名列表:",s)}}async function Mo(s){try{const e=indexedDB.open("ServiceWorkerDB",1);return new Promise((t,o)=>{e.onerror=()=>o(e.error),e.onsuccess=()=>{const r=e.result.transaction(["failedDomains"],"readwrite");r.objectStore("failedDomains").put({domain:s,timestamp:Date.now()}),r.oncomplete=()=>{t()},r.onerror=()=>o(r.error)},e.onupgradeneeded=n=>{const r=n.target.result;r.objectStoreNames.contains("failedDomains")||r.createObjectStore("failedDomains",{keyPath:"domain"})}})}catch(e){console.warn("Service Worker: 无法保存失败域名:",e)}}function Po(s){s&&A.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_NEW_VERSION_READY",version:ue})})})}async function vo(s){try{const e=await s.keys();if(e.length<=10)return;const t=[];for(const a of e)try{const i=await s.match(a);if(i){const c=i.headers.get("sw-cache-date"),l=i.headers.get("sw-image-size");t.push({request:a,cacheDate:c?parseInt(c):0,imageSize:l?parseInt(l):0})}}catch(i){console.warn("Service Worker: Error reading cache entry:",i)}t.sort((a,i)=>a.cacheDate-i.cacheDate);const o=Math.max(1,Math.floor(t.length*.25));let n=0,r=0;for(let a=0;a<o&&a<t.length;a++)try{await s.delete(t[a].request),n++,r+=t[a].imageSize}catch(i){console.warn("Service Worker: Error deleting cache entry:",i)}}catch(e){console.warn("Service Worker: Cache cleanup failed:",e)}}const Bo=["/","/index.html","/manifest.json","/favicon.ico","/icons/favicon-new.svg"];A.addEventListener("install",s=>{const e=[];e.push(xo()),kt||e.push(caches.open(he).then(async t=>{const n=(await Promise.allSettled(Bo.map(async r=>{try{const a=await fetch(r,{cache:"reload"});return a.ok?(await t.put(r,a),{url:r,success:!0}):{url:r,success:!1,status:a.status}}catch(a){return{url:r,success:!1,error:String(a)}}}))).filter(r=>r.status==="rejected"||r.status==="fulfilled"&&!r.value.success);n.length>0&&console.warn("Service Worker: Some static files failed to cache:",n.length)}).catch(t=>{console.warn("Service Worker: Cache pre-loading failed:",t)})),s.waitUntil(Promise.all(e).then(async()=>{const t=await caches.keys(),o=t.some(a=>a.startsWith("drawnix-static-v")&&a!==he),n=t.some(a=>a.startsWith("drawnix-v")&&a!==Pe&&a!==k&&!a.startsWith("drawnix-static-v"));Po(o||n)}))}),A.addEventListener("activate",s=>{s.waitUntil(caches.keys().then(async e=>{const t=e.filter(r=>r.startsWith("drawnix-images-v")&&r!==k);if(t.length>0){const r=await caches.open(k);for(const a of t)try{const i=await caches.open(a),c=await i.keys();for(const l of c){const h=await i.match(l);h&&await r.put(l,h)}await caches.delete(a)}catch(i){console.warn(`Failed to migrate cache ${a}:`,i)}}const o=e.filter(r=>r.startsWith("drawnix-static-v")&&r!==he),n=e.filter(r=>r.startsWith("drawnix-v")&&r!==Pe&&r!==k&&!r.startsWith("drawnix-static-v"));return(o.length>0||n.length>0)&&setTimeout(async()=>{for(const r of[...o,...n])try{await caches.delete(r)}catch(a){console.warn("Failed to delete old cache:",r,a)}},3e4),Wo().catch(r=>{console.warn("Failed to cleanup expired console logs:",r)}),A.clients.claim()}))});const No=["TASK_QUEUE_INIT","TASK_QUEUE_UPDATE_CONFIG","TASK_SUBMIT","TASK_CANCEL","TASK_RETRY","TASK_RESUME","TASK_GET_STATUS","TASK_GET_ALL","TASK_DELETE","TASK_MARK_INSERTED","CHAT_START","CHAT_STOP","CHAT_GET_CACHED","TASK_RESTORE"];function Uo(s){if(!s||typeof s!="object")return!1;const e=s;return e.type?No.includes(e.type):!1}let re=!1,me=null,we=null;const Ue=[];function Ft(s){G&&A.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_POSTMESSAGE_LOG",entry:s})})})}_s(Ft),A.addEventListener("message",s=>{var n,r,a,i,c,l,h,m,S,w,g;const e=((n=s.data)==null?void 0:n.type)||"unknown",t=((r=s.source)==null?void 0:r.id)||"";let o="";if(Ge()&&(o=Ss(e,s.data,t),o&&G)){const u=Te().find(f=>f.id===o);u&&Ft(u)}if(s.data&&Uo(s.data)){const d=((a=s.source)==null?void 0:a.id)||"";if(Ks(s.data,d),s.data.type==="TASK_QUEUE_INIT"){const{geminiConfig:u,videoConfig:f}=s.data;if(me=u,we=f,!re&&(Xe(A,u,f),re=!0,Ue.length>0)){for(const p of Ue)Je(p.message,p.clientId);Ue.length=0}ao()}if(s.data.type==="TASK_QUEUE_UPDATE_CONFIG"){const{geminiConfig:u,videoConfig:f}=s.data;u&&(me={...me,...u}),f&&(we={...we,...f}),so(u,f)}return}if(s.data&&oo(s.data)){const d=((i=s.source)==null?void 0:i.id)||"";if(!re&&me&&we&&(Xe(A,me,we),re=!0),!re){(async()=>{try{const{geminiConfig:u,videoConfig:f}=await y.loadConfig();if(u&&f)me=u,we=f,Xe(A,u,f),re=!0,Je(s.data,d);else{console.warn("[SW] Cannot initialize workflow handler: no config in storage, requesting config from main thread");const p=await A.clients.matchAll({type:"window"});for(const E of p)E.postMessage({type:"SW_REQUEST_CONFIG",reason:"workflow_handler_not_initialized",pendingMessageType:s.data.type});Ue.push({message:s.data,clientId:d})}}catch(u){console.error("[SW] Failed to load config from storage:",u)}})();return}Je(s.data,d);return}if(s.data&&s.data.type==="MAIN_THREAD_TOOL_RESPONSE"){no(s.data);return}if(s.data&&s.data.type==="SKIP_WAITING")A.skipWaiting(),A.clients.matchAll().then(d=>{d.forEach(u=>{u.postMessage({type:"SW_UPDATED"})})});else if(s.data&&s.data.type==="GET_UPGRADE_STATUS")(c=s.source)==null||c.postMessage({type:"UPGRADE_STATUS",version:ue});else if(s.data&&s.data.type==="FORCE_UPGRADE")A.skipWaiting(),A.clients.matchAll().then(d=>{d.forEach(u=>{u.postMessage({type:"SW_UPDATED"})})});else if(s.data&&s.data.type==="DELETE_CACHE"){const{url:d}=s.data;d&&Vo(d).then(()=>{A.clients.matchAll().then(u=>{u.forEach(f=>{f.postMessage({type:"CACHE_DELETED",url:d})})})}).catch(u=>{console.error("Service Worker: Failed to delete cache:",u)})}else if(s.data&&s.data.type==="DELETE_CACHE_BATCH"){const{urls:d}=s.data;d&&Array.isArray(d)&&Qo(d).then(()=>{}).catch(u=>{console.error("Service Worker: Failed to batch delete caches:",u)})}else if(s.data&&s.data.type==="CLEAR_ALL_CACHE")Xo().then(()=>{}).catch(d=>{console.error("Service Worker: Failed to clear all cache:",d)});else if(s.data&&s.data.type==="SW_DEBUG_ENABLE")G=!0,pe=Date.now(),Promise.resolve().then(()=>P).then(({setDebugFetchEnabled:d})=>{d(!0)}),$e(!0),se.log("Service Worker: Debug mode enabled"),V&&clearTimeout(V),V=setTimeout(vt,5e3),A.clients.matchAll().then(d=>{d.forEach(u=>{u.postMessage({type:"SW_DEBUG_ENABLED"})})}),(l=s.source)==null||l.postMessage({type:"SW_DEBUG_STATUS",status:Ne()});else if(s.data&&s.data.type==="SW_DEBUG_HEARTBEAT")G&&(pe=Date.now());else if(s.data&&s.data.type==="SW_DEBUG_DISABLE")G=!1,pe=0,V&&(clearTimeout(V),V=null),Promise.resolve().then(()=>P).then(({setDebugFetchEnabled:d})=>{d(!1)}),$e(!1),be.length=0,j.length=0,Ut().catch(()=>{}),se.log("Service Worker: Debug mode disabled, logs cleared"),A.clients.matchAll().then(d=>{d.forEach(u=>{u.postMessage({type:"SW_DEBUG_DISABLED"})})}),(h=s.source)==null||h.postMessage({type:"SW_DEBUG_STATUS",status:Ne()});else if(s.data&&s.data.type==="SW_DEBUG_GET_STATUS")(async()=>{var f;const d=Ne(),u=await jo();(f=s.source)==null||f.postMessage({type:"SW_DEBUG_STATUS",status:{...d,cacheStats:u}})})();else if(s.data&&s.data.type==="SW_DEBUG_GET_LOGS"){const{limit:d=100,offset:u=0,filter:f}=s.data,p=Ot().map(C=>({...C,type:"fetch"})),E=new Map;for(const C of j)E.set(C.id,C);for(const C of p)E.set(C.id,C);let T=Array.from(E.values()).sort((C,R)=>R.timestamp-C.timestamp);f&&(f.type&&(T=T.filter(C=>C.type===f.type)),f.requestType&&(T=T.filter(C=>C.requestType===f.requestType)),f.url&&(T=T.filter(C=>{var R;return(R=C.url)==null?void 0:R.includes(f.url)})),f.status&&(T=T.filter(C=>C.status===f.status)));const _=T.slice(u,u+d);(m=s.source)==null||m.postMessage({type:"SW_DEBUG_LOGS",logs:_,total:T.length,offset:u,limit:d})}else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_LOGS")j.length=0,(S=s.source)==null||S.postMessage({type:"SW_DEBUG_LOGS_CLEARED"});else if(s.data&&s.data.type==="SW_DEBUG_GET_CACHE_ENTRIES"){const{cacheName:d,limit:u=50,offset:f=0}=s.data;(async()=>{var p,E;try{const T=await caches.open(d||k),_=await T.keys(),C=[];for(let R=f;R<Math.min(f+u,_.length);R++){const x=_[R],v=await T.match(x);if(v){const ee=v.headers.get("sw-cache-date"),Ae=v.headers.get("sw-image-size")||v.headers.get("content-length");C.push({url:x.url,cacheDate:ee?parseInt(ee):void 0,size:Ae?parseInt(Ae):void 0})}}(p=s.source)==null||p.postMessage({type:"SW_DEBUG_CACHE_ENTRIES",cacheName:d||k,entries:C,total:_.length,offset:f,limit:u})}catch(T){(E=s.source)==null||E.postMessage({type:"SW_DEBUG_CACHE_ENTRIES",error:String(T)})}})()}else if(s.data&&s.data.type==="SW_CONSOLE_LOG_REPORT"){const{logLevel:d,logMessage:u,logStack:f,logSource:p,url:E}=s.data;qt({logLevel:d,logMessage:u,logStack:f,logSource:p,url:E})}else if(s.data&&s.data.type==="SW_DEBUG_GET_CONSOLE_LOGS")(async()=>{var d,u;try{const{limit:f=500,offset:p=0,filter:E}=s.data;let T=await Nt();if(E&&(E.logLevel&&(T=T.filter(C=>C.logLevel===E.logLevel)),E.search)){const C=E.search.toLowerCase();T=T.filter(R=>{var x,v;return((x=R.logMessage)==null?void 0:x.toLowerCase().includes(C))||((v=R.logStack)==null?void 0:v.toLowerCase().includes(C))})}const _=T.slice(p,p+f);(d=s.source)==null||d.postMessage({type:"SW_DEBUG_CONSOLE_LOGS",logs:_,total:T.length,offset:p,limit:f})}catch(f){(u=s.source)==null||u.postMessage({type:"SW_DEBUG_CONSOLE_LOGS",logs:[],total:0,error:String(f)})}})();else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_CONSOLE_LOGS")(async()=>{var d;be.length=0,await Ut(),(d=s.source)==null||d.postMessage({type:"SW_DEBUG_CONSOLE_LOGS_CLEARED"})})();else if(s.data&&s.data.type==="SW_DEBUG_EXPORT_LOGS")(async()=>{var p;const d=await Nt(),u=Te(),f={exportTime:new Date().toISOString(),swVersion:ue,userAgent:"",status:Ne(),fetchLogs:j,consoleLogs:d,postmessageLogs:u};(p=s.source)==null||p.postMessage({type:"SW_DEBUG_EXPORT_DATA",data:f})})();else if(s.data&&s.data.type==="SW_DEBUG_GET_POSTMESSAGE_LOGS"){const{limit:d=200,offset:u=0,filter:f}=s.data;let p=Te();if(f&&(f.direction&&(p=p.filter(T=>T.direction===f.direction)),f.messageType)){const T=f.messageType.toLowerCase();p=p.filter(_=>{var C;return(C=_.messageType)==null?void 0:C.toLowerCase().includes(T)})}const E=p.slice(u,u+d);(w=s.source)==null||w.postMessage({type:"SW_DEBUG_POSTMESSAGE_LOGS",logs:E,total:p.length,offset:u,limit:d,stats:Cs()})}else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_POSTMESSAGE_LOGS")ys(),(g=s.source)==null||g.postMessage({type:"SW_DEBUG_POSTMESSAGE_LOGS_CLEARED"});else if(s.data&&s.data.type==="CRASH_SNAPSHOT"){const d=s.data.snapshot;d&&(Go(d),A.clients.matchAll().then(u=>{u.forEach(f=>{f.postMessage({type:"SW_DEBUG_NEW_CRASH_SNAPSHOT",snapshot:d})})}))}else s.data&&s.data.type==="SW_DEBUG_GET_CRASH_SNAPSHOTS"?(async()=>{var d,u;try{const f=await Fo();(d=s.source)==null||d.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS",snapshots:f,total:f.length})}catch(f){(u=s.source)==null||u.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS",snapshots:[],total:0,error:String(f)})}})():s.data&&s.data.type==="SW_DEBUG_CLEAR_CRASH_SNAPSHOTS"?(async()=>{var d;await $o(),(d=s.source)==null||d.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS_CLEARED"})})():s.data&&s.data.type==="SW_DEBUG_GET_LLM_API_LOGS"?(async()=>{var d,u;try{const{getAllLLMApiLogs:f}=await Promise.resolve().then(()=>L),p=await f();(d=s.source)==null||d.postMessage({type:"SW_DEBUG_LLM_API_LOGS",logs:p,total:p.length})}catch(f){(u=s.source)==null||u.postMessage({type:"SW_DEBUG_LLM_API_LOGS",logs:[],total:0,error:String(f)})}})():s.data&&s.data.type==="SW_DEBUG_CLEAR_LLM_API_LOGS"&&(async()=>{var u;const{clearAllLLMApiLogs:d}=await Promise.resolve().then(()=>L);await d(),(u=s.source)==null||u.postMessage({type:"SW_DEBUG_LLM_API_LOGS_CLEARED"})})()});const qo="MemorySnapshotDB",J="snapshots",$t=50;async function ot(){return new Promise((s,e)=>{const t=indexedDB.open(qo,1);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const n=o.target.result;if(!n.objectStoreNames.contains(J)){const r=n.createObjectStore(J,{keyPath:"id"});r.createIndex("timestamp","timestamp",{unique:!1}),r.createIndex("type","type",{unique:!1})}}})}async function Go(s){try{const e=await ot(),t=e.transaction(J,"readwrite"),o=t.objectStore(J);o.put(s);const n=o.count();n.onsuccess=()=>{const r=n.result;if(r>$t){const i=o.index("timestamp").openCursor();let c=0;const l=r-$t;i.onsuccess=h=>{const m=h.target.result;m&&c<l&&(o.delete(m.value.id),c++,m.continue())}}},await new Promise((r,a)=>{t.oncomplete=()=>{e.close(),r()},t.onerror=()=>{e.close(),a(t.error)}})}catch(e){console.warn("[SW] Failed to save crash snapshot:",e)}}async function Fo(){try{const s=await ot(),o=s.transaction(J,"readonly").objectStore(J).index("timestamp");return new Promise((n,r)=>{const a=o.getAll();a.onsuccess=()=>{s.close();const i=a.result.sort((c,l)=>l.timestamp-c.timestamp);n(i)},a.onerror=()=>{s.close(),r(a.error)}})}catch(s){return console.warn("[SW] Failed to get crash snapshots:",s),[]}}async function $o(){try{const s=await ot(),e=s.transaction(J,"readwrite");e.objectStore(J).clear(),await new Promise((o,n)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),n(e.error)}}),console.log("[SW] Crash snapshots cleared")}catch(s){console.warn("[SW] Failed to clear crash snapshots:",s)}}const Ho=["ConsoleLogDB","ServiceWorkerDB","sw-task-queue","aitu-workspace","drawnix-unified-cache","drawnix-kv-storage","drawnix-prompts","drawnix-chat-db","MemorySnapshotDB"];function zo(s){try{const e=JSON.stringify(s);return new Blob([e]).size}catch{return 0}}async function Ko(s){return new Promise(e=>{try{const t=indexedDB.open(s);t.onerror=()=>e({count:0,totalSize:0}),t.onsuccess=()=>{const o=t.result,n=Array.from(o.objectStoreNames);if(n.length===0){o.close(),e({count:0,totalSize:0});return}let r=0,a=0,i=0,c=0;const l=10;try{const h=o.transaction(n,"readonly");for(const m of n){const S=h.objectStore(m),w=S.count();w.onsuccess=()=>{const g=w.result;if(r+=g,g>0){const d=S.openCursor();let u=0;d.onsuccess=f=>{const p=f.target.result;if(p&&u<l)a+=zo(p.value),i++,u++,p.continue();else if(c++,c===n.length){o.close();const E=i>0?a/i:0,T=Math.round(E*r);e({count:r,totalSize:T})}},d.onerror=()=>{if(c++,c===n.length){o.close();const f=i>0?a/i:0,p=Math.round(f*r);e({count:r,totalSize:p})}}}else c++,c===n.length&&(o.close(),e({count:r,totalSize:0}))},w.onerror=()=>{if(c++,c===n.length){o.close();const g=i>0?a/i:0,d=Math.round(g*r);e({count:r,totalSize:d})}}}}catch{o.close(),e({count:0,totalSize:0})}},t.onupgradeneeded=o=>{o.target.result.close();try{indexedDB.deleteDatabase(s)}catch{}e({count:0,totalSize:0})}}catch{e({count:0,totalSize:0})}})}async function jo(){const s={},e=[Pe,k,he,ve];for(const t of e)try{const o=await caches.open(t),n=await o.keys();let r=0;const a=Math.min(n.length,100);let i=0;for(let c=0;c<a;c++){const l=await o.match(n[c]);if(l){const h=l.headers.get("sw-image-size")||l.headers.get("content-length");h&&(i+=parseInt(h))}}a>0&&n.length>a?r=Math.round(i/a*n.length):r=i,s[t]={count:n.length,totalSize:r,type:"cache"}}catch{s[t]={count:0,totalSize:0,type:"cache"}}for(const t of Ho)try{const o=await Ko(t);o.count>0&&(s[`[IDB] ${t}`]={...o,type:"indexeddb"})}catch{}return s}async function Vo(s){try{await(await caches.open(k)).delete(s)}catch(e){throw console.error("Service Worker: Failed to delete cache entry:",s,e),e}}async function Qo(s){try{const e=await caches.open(k);let t=0;for(const o of s)try{await e.delete(o),t++}catch(n){console.warn("Service Worker: Failed to delete cache in batch:",o,n)}}catch(e){throw console.error("Service Worker: Failed to batch delete caches:",e),e}}async function Xo(){try{const s=await caches.open(k),e=await s.keys();for(const t of e)await s.delete(t)}catch(s){throw console.error("Service Worker: Failed to clear image cache:",s),s}}async function Ht(s,e,t){try{(await A.clients.matchAll()).forEach(n=>{n.postMessage({type:"IMAGE_CACHED",url:s,size:e,mimeType:t,timestamp:Date.now()})})}catch(o){console.warn("Service Worker: Failed to notify image cached:",o)}}async function Jo(){try{if(navigator.storage&&navigator.storage.estimate){const s=await navigator.storage.estimate(),e=s.usage||0,t=s.quota||0,o=t>0?e/t*100:0;o>90&&(console.warn("Service Worker: Storage quota warning:",{usage:e,quota:t,percentage:o}),(await A.clients.matchAll()).forEach(r=>{r.postMessage({type:"QUOTA_WARNING",usage:e,quota:t})}))}}catch(s){console.warn("Service Worker: Failed to check storage quota:",s)}}A.addEventListener("fetch",s=>{const e=new URL(s.request.url),t=Date.now();if(e.protocol!=="http:"&&e.protocol!=="https:"){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"other",details:`Skipped: non-http protocol (${e.protocol})`,status:0,duration:0});return}if(e.pathname.startsWith(po)){const o=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"cache-url",details:"Intercepting cache URL request"});s.respondWith(Zo(s.request).then(n=>(M(o,{status:n.status,statusText:n.statusText,responseType:n.type,duration:Date.now()-t,cached:n.status===200}),n)).catch(n=>{throw M(o,{error:String(n),duration:Date.now()-t}),n}));return}if(e.pathname.startsWith(mo)){const o=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"asset-library",details:"Intercepting asset library request"});s.respondWith(er(s.request).then(n=>(M(o,{status:n.status,statusText:n.statusText,responseType:n.type,duration:Date.now()-t,cached:n.status===200}),n)).catch(n=>{throw M(o,{error:String(n),duration:Date.now()-t}),n}));return}if(e.hostname==="cdn.i666.fun"){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"passthrough",details:"Passthrough: cdn.i666.fun (fallback domain)",status:0,duration:0});return}if(e.hostname.endsWith(".volces.com")||e.hostname.endsWith(".volccdn.com")){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"passthrough",details:"Passthrough: Volcengine domain (no CORS)",status:0,duration:0});return}if(e.hostname.endsWith(".aliyuncs.com")){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"passthrough",details:"Passthrough: Aliyun OSS domain (no CORS)",status:0,duration:0});return}if(Co(e.hostname)){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"passthrough",details:`Passthrough: ${e.hostname} (CORS failed domain, auto-detected)`,status:0,duration:0});return}if(Oo(e,s.request)){const o=Date.now(),n=s.request.headers.get("range"),r=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"video",headers:n?{range:n}:void 0,details:n?`Video Range request: ${n}`:"Video request"});s.respondWith(tr(s.request).then(a=>(M(r,{status:a.status,statusText:a.statusText,responseType:a.type,duration:Date.now()-o,responseHeaders:{"content-type":a.headers.get("content-type")||"","content-length":a.headers.get("content-length")||"","content-range":a.headers.get("content-range")||""}}),a)).catch(a=>{throw M(r,{error:String(a),duration:Date.now()-o}),a}));return}if(ko(e,s.request)){const o=Date.now(),n=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"font",details:"Font request"});s.respondWith(Yo(s.request).then(r=>(M(n,{status:r.status,statusText:r.statusText,responseType:r.type,duration:Date.now()-o,cached:r.headers.has("sw-cache-date")}),r)).catch(r=>{throw M(n,{error:String(r),duration:Date.now()-o}),r}));return}if(e.origin!==location.origin&&Io(e,s.request)){const o=Date.now(),n=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"image",details:"External image request"});s.respondWith(nr(s.request).then(r=>(M(n,{status:r.status,statusText:r.statusText,responseType:r.type,duration:Date.now()-o,cached:r.headers.has("sw-cache-date"),size:parseInt(r.headers.get("content-length")||"0")}),r)).catch(r=>{throw M(n,{error:String(r),duration:Date.now()-o}),r}));return}if(s.request.method==="GET"){const o=s.request.mode==="navigate",n=s.request.destination!=="";if(o||n){const r=Date.now(),a=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"static",details:o?"Navigation request":`Static resource (${s.request.destination})`});s.respondWith(sr(s.request).then(i=>(M(a,{status:i.status,statusText:i.statusText,responseType:i.type,duration:Date.now()-r}),i)).catch(i=>{throw M(a,{error:String(i),duration:Date.now()-r}),i}));return}}if(G){const o=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"xhr",details:`XHR/API request (${s.request.method})`});s.respondWith((async()=>{try{const n=s.request.clone();let r,a={};if(s.request.headers.forEach((m,S)=>{a[S]=m}),["POST","PUT","PATCH"].includes(s.request.method))try{const m=s.request.headers.get("content-type")||"";m.includes("application/json")?(r=await n.text(),r.length>2e3&&(r=r.substring(0,2e3)+"... (truncated)")):m.includes("application/x-www-form-urlencoded")?(r=await n.text(),r.length>2e3&&(r=r.substring(0,2e3)+"... (truncated)")):r=`[${m||"binary data"}]`}catch{r="[unable to read body]"}M(o,{headers:a,details:r?`XHR/API request (${s.request.method})
|
|
6
|
+
|
|
7
|
+
Request Body:
|
|
8
|
+
${r}`:`XHR/API request (${s.request.method})`});const i=await fetch(s.request),c=i.clone();let l,h={};i.headers.forEach((m,S)=>{h[S]=m});try{const m=i.headers.get("content-type")||"";m.includes("application/json")||m.includes("text/")?(l=await c.text(),l.length>5e3&&(l=l.substring(0,5e3)+"... (truncated)")):l=`[${m||"binary data"}] (${i.headers.get("content-length")||"unknown"} bytes)`}catch{l="[unable to read response body]"}return M(o,{status:i.status,statusText:i.statusText,responseType:i.type,duration:Date.now()-t,responseHeaders:h,size:parseInt(i.headers.get("content-length")||"0"),details:r?`XHR/API request (${s.request.method})
|
|
9
|
+
|
|
10
|
+
Request Body:
|
|
11
|
+
${r}
|
|
12
|
+
|
|
13
|
+
Response Body:
|
|
14
|
+
${l}`:`XHR/API request (${s.request.method})
|
|
15
|
+
|
|
16
|
+
Response Body:
|
|
17
|
+
${l}`}),i}catch(n){throw M(o,{error:String(n),duration:Date.now()-t}),n}})());return}});async function Yo(s){new URL(s.url);const e=Math.random().toString(36).substring(2,10);try{const t=await caches.open(ve),o=await t.match(s);if(o)return o;const n=await fetch(s);if(n&&n.status===200){const r=n.clone(),a=new Headers(r.headers);a.set("sw-cache-date",Date.now().toString());const i=new Response(r.body,{status:r.status,statusText:r.statusText,headers:a});t.put(s,i).catch(c=>{console.warn(`Service Worker [Font-${e}]: 缓存字体失败:`,c)})}return n}catch(t){console.error(`Service Worker [Font-${e}]: 字体请求失败:`,t);const n=await(await caches.open(ve)).match(s);return n||new Response("Font loading failed",{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/plain"}})}}async function rt(s,e={}){return fetch(s,e)}async function Zo(s){const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=s.headers.get("range"),n=t.pathname.includes("/video/")||/\.(mp4|webm|ogg|mov)$/i.test(t.pathname);try{const r=await caches.open(k);let a=await r.match(s.url);if(a||(a=await r.match(t.pathname)),a){const i=await a.blob();return n?Se(i,o,e):new Response(i,{status:200,statusText:"OK",headers:{"Content-Type":i.type||"image/png","Content-Length":i.size.toString(),"Access-Control-Allow-Origin":"*","Cache-Control":"max-age=31536000"}})}return console.error("Service Worker: Media not found in cache:",{fullUrl:s.url,pathname:t.pathname}),new Response("Media not found",{status:404,statusText:"Not Found",headers:{"Content-Type":"text/plain"}})}catch(r){return console.error("Service Worker: Error handling cache URL request:",r),new Response("Internal error",{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain"}})}}async function er(s){const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=s.headers.get("range"),n=t.pathname;try{const a=await(await caches.open(k)).match(n);if(a){const i=await a.blob();return t.pathname.match(/\.(mp4|webm|ogg|mov)$/i)&&o?Se(i,o,e):new Response(i,{status:200,statusText:"OK",headers:{"Content-Type":i.type||"application/octet-stream","Content-Length":i.size.toString(),"Accept-Ranges":"bytes","Access-Control-Allow-Origin":"*","Cache-Control":"max-age=31536000"}})}return console.error(`Service Worker [Asset-${e}]: Asset not found in cache:`,n),new Response("Asset not found",{status:404,statusText:"Not Found",headers:{"Content-Type":"text/plain"}})}catch(r){return console.error(`Service Worker [Asset-${e}]: Error handling asset library request:`,r),new Response("Internal error",{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain"}})}}async function tr(s){const e=new URL(s.url),t=Math.random().toString(36).substring(2,10);try{const o=s.headers.get("range"),n=new URL(e);["_t","cache_buster","v","timestamp","nocache","_cb","t","retry","rand"].forEach(h=>n.searchParams.delete(h));const a=n.toString(),i=_e.get(a);if(i){i.count=(i.count||1)+1;const h=await i.promise;if(!h){const m={method:"GET",headers:new Headers(s.headers),mode:"cors",credentials:"omit"};return await fetch(e,m)}return Se(h,o,t)}if(q.has(a)){const h=q.get(a);if(h)return h.timestamp=Date.now(),Se(h.blob,o,t)}try{const m=await(await caches.open(k)).match(a);if(m){const S=await m.blob();return S.size/(1024*1024)<50&&q.set(a,{blob:S,timestamp:Date.now()}),Se(S,o,t)}}catch(h){console.warn(`Service Worker [Video-${t}]: 检查 Cache API 失败:`,h)}const c=(async()=>{const h={method:"GET",mode:"cors",credentials:"omit",cache:"default"},m=new URL(n),S=await fetch(m,h);if(!S.ok)throw console.error(`Service Worker [Video-${t}]: Video fetch failed:`,S.status),new Error(`Video fetch failed: ${S.status}`);if(S.status===206)return null;const w=await S.blob();if(w.size/(1024*1024)<50){q.set(a,{blob:w,timestamp:Date.now()});try{const d=await caches.open(k),u=new Response(w,{headers:{"Content-Type":w.type||"video/mp4","Content-Length":w.size.toString(),"sw-cache-date":Date.now().toString(),"sw-video-size":w.size.toString()}});await d.put(a,u)}catch(d){console.warn(`Service Worker [Video-${t}]: 持久化到 Cache API 失败:`,d)}}return w})();_e.set(a,{promise:c,timestamp:Date.now(),count:1,requestId:t}),c.finally(()=>{_e.get(a)&&_e.delete(a)});const l=await c;if(l===null){const h={method:"GET",headers:new Headers(s.headers),mode:"cors",credentials:"omit"};return await fetch(e,h)}return Se(l,o,t)}catch(o){return console.error(`Service Worker [Video-${t}]: Video request error:`,o),new Response("Video loading error",{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain"}})}}function Se(s,e,t){const o=s.size;if(!e)return new Response(s,{status:200,statusText:"OK",headers:{"Content-Type":"video/mp4","Content-Length":o.toString(),"Accept-Ranges":"bytes","Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":"Content-Range, Accept-Ranges, Content-Length"}});const n=e.match(/bytes=(\d+)-(\d*)/);if(!n)return console.error(`Service Worker [Video-${t}]: Invalid Range header format`),new Response(s,{status:200,statusText:"OK",headers:{"Content-Type":"video/mp4","Accept-Ranges":"bytes"}});const r=parseInt(n[1],10),a=n[2]?parseInt(n[2],10):o-1,i=s.slice(r,a+1),c=a-r+1;return new Response(i,{status:206,statusText:"Partial Content",headers:{"Content-Type":"video/mp4","Content-Range":`bytes ${r}-${a}/${o}`,"Content-Length":c.toString(),"Accept-Ranges":"bytes","Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":"Content-Range, Accept-Ranges, Content-Length"}})}async function sr(s){const e=new URL(s.url),t=s.mode==="navigate"||e.pathname.endsWith(".html"),o=await caches.open(he);if(kt)try{const r=await rt(s);if(r&&r.status===200&&s.url.startsWith("http"))return o.put(s,r.clone()),r;if(!r.ok){let a=await o.match(s);return!a&&t&&(a=await o.match("/"),a||(a=await o.match("/index.html"))),a||r}return r}catch{let a=await o.match(s);return!a&&t&&(a=await o.match("/"),a||(a=await o.match("/index.html"))),a||(t?zt():new Response("Resource unavailable",{status:503}))}if(t)try{const r=await rt(s,{cache:"reload"});if(r&&r.status===200&&s.url.startsWith("http"))return o.put(s,r.clone()),r;if(!r.ok){let a=await o.match(s);return a||(a=await o.match("/")),a||(a=await o.match("/index.html")),a||r}return r}catch{let a=await o.match(s);return a||(a=await o.match("/")),a||(a=await o.match("/index.html")),a||zt()}const n=await o.match(s);if(n)return n;try{const r=await rt(s),a=r.headers.get("Content-Type");if(r.status===200&&(a==null?void 0:a.includes("text/html"))&&(e.pathname.match(/\.(js|css|png|jpg|jpeg|gif|webp|svg|json|woff|woff2|ttf)$/i)||s.destination==="script"||s.destination==="style"||s.destination==="image"||s.destination==="font"))return console.warn("Service Worker: HTML response for static resource (404):",s.url),new Response("Resource not found",{status:404,statusText:"Not Found"});if(r&&r.status===200&&s.url.startsWith("http")&&o.put(s,r.clone()),r.status>=500){const c=await caches.keys();for(const l of c)if(l.startsWith("drawnix-static-v"))try{const m=await(await caches.open(l)).match(s);if(m)return m}catch{}}return r}catch{console.error("Static resource unavailable:",s.url);const a=await caches.keys();for(const i of a)if(i.startsWith("drawnix-static-v"))try{const l=await(await caches.open(i)).match(s);if(l)return l}catch{}return new Response("Resource unavailable offline",{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/plain"}})}}function zt(){return new Response(`<!DOCTYPE html>
|
|
18
|
+
<html lang="zh-CN">
|
|
19
|
+
<head>
|
|
20
|
+
<meta charset="UTF-8">
|
|
21
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
22
|
+
<title>离线 - aitu</title>
|
|
23
|
+
<style>
|
|
24
|
+
body {
|
|
25
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
26
|
+
display: flex;
|
|
27
|
+
flex-direction: column;
|
|
28
|
+
align-items: center;
|
|
29
|
+
justify-content: center;
|
|
30
|
+
min-height: 100vh;
|
|
31
|
+
margin: 0;
|
|
32
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
33
|
+
color: white;
|
|
34
|
+
text-align: center;
|
|
35
|
+
padding: 20px;
|
|
36
|
+
}
|
|
37
|
+
h1 { font-size: 2rem; margin-bottom: 1rem; }
|
|
38
|
+
p { font-size: 1.1rem; opacity: 0.9; max-width: 400px; }
|
|
39
|
+
button {
|
|
40
|
+
margin-top: 2rem;
|
|
41
|
+
padding: 12px 24px;
|
|
42
|
+
font-size: 1rem;
|
|
43
|
+
border: none;
|
|
44
|
+
border-radius: 8px;
|
|
45
|
+
background: white;
|
|
46
|
+
color: #667eea;
|
|
47
|
+
cursor: pointer;
|
|
48
|
+
transition: transform 0.2s;
|
|
49
|
+
}
|
|
50
|
+
button:hover { transform: scale(1.05); }
|
|
51
|
+
</style>
|
|
52
|
+
</head>
|
|
53
|
+
<body>
|
|
54
|
+
<h1>📡 无法连接到服务器</h1>
|
|
55
|
+
<p>请检查您的网络连接,或稍后再试。</p>
|
|
56
|
+
<button onclick="location.reload()">重试</button>
|
|
57
|
+
</body>
|
|
58
|
+
</html>`,{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}const nt=15e3,Kt=3e4;function jt(s,e,t){return Promise.race([s,new Promise((o,n)=>{setTimeout(()=>n(new Error(t)),e)})])}function or(){const s=Date.now(),e=[];if(q.forEach((t,o)=>{s-t.timestamp>To&&e.push(o)}),e.length>0&&e.forEach(t=>q.delete(t)),q.size>Mt){const t=Array.from(q.entries()).sort((r,a)=>r[1].timestamp-a[1].timestamp),o=q.size-Mt,n=t.slice(0,o);n.length>0&&n.forEach(([r])=>q.delete(r))}}function rr(){const s=Date.now(),e=[];F.forEach((o,n)=>{s-o.timestamp>Kt&&e.push(n)}),e.length>0&&(console.warn(`Service Worker: 清理 ${e.length} 个过期的 pending 请求`),e.forEach(o=>F.delete(o)));const t=[];oe.forEach((o,n)=>{s-o.timestamp>xt&&t.push(n)}),t.length>0&&t.forEach(o=>oe.delete(o)),or()}async function nr(s){try{const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=t.searchParams.has("bypass_sw")||t.searchParams.has("direct_fetch");["_t","cache_buster","v","timestamp","nocache","_cb","t","retry","_retry","rand","_force","bypass_sw","direct_fetch"].forEach(l=>t.searchParams.delete(l));const r=new Request(t.toString(),{method:s.method,headers:s.headers,mode:s.mode,credentials:s.credentials}),a=t.toString(),i=oe.get(a);if(i){if(Date.now()-i.timestamp<xt)return i.response.clone();oe.delete(a)}if(F.has(a)){const l=F.get(a);if(l){const h=Date.now()-l.timestamp;if(h>Kt)console.warn(`Service Worker [${e}]: 发现过期的 pending 请求 (${h}ms),清理并重新发起:`,a),F.delete(a);else{l.count=(l.count||1)+1,l.duplicateRequestIds=l.duplicateRequestIds||[],l.duplicateRequestIds.push(e);try{const m=await jt(l.promise,nt,"Image request timeout");return m&&m.clone?m.clone():m}catch(m){if(m.message==="Image request timeout")return console.warn(`Service Worker [${e}]: 重复请求等待超时,清理并返回超时响应让前端直接加载`),F.delete(a),Vt(s.url,e);throw m}}}}rr();const c=ar(r,s.url,a,e,o);F.set(a,{promise:c,timestamp:Date.now(),count:1,originalRequestId:e,duplicateRequestIds:[]}),c.then(l=>{l&&l.ok&&oe.set(a,{response:l.clone(),timestamp:Date.now()})}).catch(()=>{}).finally(()=>{F.get(a)&&F.delete(a)});try{return await jt(c,nt,"Image request timeout")}catch(l){if(l.message==="Image request timeout")return console.warn(`Service Worker [${e}]: 图片请求超时(${nt}ms),清理并返回超时响应让前端直接加载:`,s.url),F.delete(a),Vt(s.url,e);throw l}}catch(e){throw console.error("Service Worker fetch error:",e),e}}function Vt(s,e){return new Response("Image request timeout - use direct load",{status:504,statusText:"Gateway Timeout",headers:{"Content-Type":"text/plain","X-SW-Timeout":"true","X-SW-Original-URL":s,"Access-Control-Allow-Origin":"*"}})}async function ar(s,e,t,o,n=!1){try{const r=await caches.open(k);if(!n){const g=await r.match(s);if(g){const u=await g.clone().blob();if(u.size===0)console.warn(`Service Worker [${o}]: 检测到空缓存,删除并重新获取:`,e),await r.delete(s);else if(g.headers.get("sw-cache-date")){const p=Date.now(),E=new Response(u,{status:g.status,statusText:g.statusText,headers:{...Object.fromEntries(g.headers.entries()),"sw-cache-date":p.toString()}});return s.url.startsWith("http")&&await r.put(s,E.clone()),E}else{const p=new Response(u,{status:g.status,statusText:g.statusText,headers:{...Object.fromEntries(g.headers.entries()),"sw-cache-date":Date.now().toString()}});return s.url.startsWith("http")&&await r.put(s,p.clone()),p}}}const a=new URL(e),i=Gt(a);let c=null,l=!1;i&&i.fallbackDomain&&(c=e.replace(i.hostname,i.fallbackDomain),fe.has(i.hostname)&&(l=!0));let h,m=[{method:"GET",mode:"no-cors",cache:"no-cache",credentials:"omit",referrerPolicy:"no-referrer"},{method:"GET",mode:"cors",cache:"no-cache",credentials:"omit",referrerPolicy:"no-referrer"},{method:"GET",cache:"no-cache"}],S;l?S=[c]:(S=[e],c&&S.push(c));let w=null;for(let g=0;g<S.length;g++){const d=S[g],u=g>0;for(let f of m)try{let p,E=!1;for(let T=0;T<=2;T++)try{if(h=await fetch(d,f),h&&(h.status!==0||h.type==="opaque"))break}catch(_){p=_;const C=_.message||"";if(C.includes("CORS")||C.includes("cross-origin")||C.includes("Access-Control-Allow-Origin")||C.includes("Failed to fetch")||C.includes("NetworkError")||C.includes("TypeError")){E=!0;break}T<2&&await new Promise(R=>setTimeout(R,Math.pow(2,T)*1e3))}if(E){const T=new URL(d).hostname;Pt(T),console.log(`Service Worker [${o}]: CORS 错误,尝试 no-cors 模式获取图片:`,e);try{const _=await fetch(e,{mode:"no-cors",credentials:"omit",referrerPolicy:"no-referrer"});if(_.type==="opaque")return console.log(`Service Worker [${o}]: no-cors 模式成功获取 opaque 响应`),_}catch(_){console.warn(`Service Worker [${o}]: no-cors 模式也失败:`,_)}return new Response(null,{status:200,headers:{"Content-Type":"image/png","X-SW-CORS-Bypass":"true"}})}if(h&&(h.status!==0||h.type==="opaque"))break;p&&(w=p)}catch(p){w=p;continue}if(h&&(h.status!==0||h.type==="opaque"))break;i&&i.fallbackDomain&&g===0&&!l&&(fe.add(i.hostname),Mo(i.hostname).catch(f=>{console.warn("Service Worker: 保存失败域名到数据库时出错:",f)}))}if(!h||h.status===0&&h.type!=="opaque"){let g="All fetch attempts failed";return i&&i.fallbackDomain&&(l?g=`备用域名${i.fallbackDomain}也失败了`:g=`All fetch attempts failed for both ${i.hostname} and ${i.fallbackDomain} domains`),console.error(`Service Worker [${o}]: ${g}`,w),new Response("Image load failed after all attempts",{status:404,statusText:"Image Not Found",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET","Access-Control-Allow-Headers":"*"}})}if(h.type==="opaque"){console.log(`Service Worker [${o}]: 返回 opaque 响应,依赖浏览器 disk cache`);const g=new URL(e).hostname;return Pt(g),h}if(h.ok){const d=await h.clone().blob(),u=d.size/(1024*1024),f=new Response(d,{status:200,statusText:"OK",headers:{"Content-Type":h.headers.get("Content-Type")||"image/png","Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET","Access-Control-Allow-Headers":"*","Cache-Control":"max-age=3153600000","sw-cache-date":Date.now().toString(),"sw-image-size":d.size.toString()}});try{s.url.startsWith("http")&&(await r.put(s,f.clone()),await Ht(e,d.size,d.type),await Jo())}catch(p){console.warn(`Service Worker: Failed to cache normal response (${u.toFixed(2)}MB, 可能超出存储限制):`,p),await vo(r);try{s.url.startsWith("http")&&(await r.put(s,f.clone()),await Ht(e,d.size,d.type))}catch(E){console.error("Service Worker: Still failed to cache after cleanup:",E)}}return f}throw new Error(`HTTP ${h.status}: ${h.statusText}`)}catch(r){console.error("Service Worker fetch error:",r);const a=new URL(e);return r.message.includes("SSL_PROTOCOL_ERROR")||r.message.includes("ERR_SSL_PROTOCOL_ERROR")||r.message.includes("net::ERR_CERT")||r.message.includes("ERR_INSECURE_RESPONSE")?(console.warn("Service Worker: 检测到SSL/证书错误,尝试跳过Service Worker处理"),fetch(e,{method:"GET",mode:"no-cors",cache:"no-cache",credentials:"omit"}).catch(()=>new Response("SSL Error - Image not accessible",{status:404,statusText:"SSL Protocol Error",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*"}}))):a.pathname.match(/\.(jpg|jpeg|png|gif|webp|svg|bmp|ico)$/i)||a.searchParams.has("_t")||a.searchParams.has("cache_buster")||a.searchParams.has("timestamp")?new Response("Image not found",{status:404,statusText:"Not Found",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*"}}):new Response(`Network Error: ${r.message}`,{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*"}})}}const Y=[],ir=50,cr="llm-api-logs",lr=1,Z="logs",Qt=500;let ne=null;function at(){return new Promise((s,e)=>{const t=indexedDB.open(cr,lr);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const n=o.target.result;if(!n.objectStoreNames.contains(Z)){const r=n.createObjectStore(Z,{keyPath:"id"});r.createIndex("timestamp","timestamp",{unique:!1}),r.createIndex("taskType","taskType",{unique:!1}),r.createIndex("status","status",{unique:!1})}}})}async function Xt(s){try{const e=await at(),t=e.transaction(Z,"readwrite"),o=t.objectStore(Z);o.put(s);const n=o.count();n.onsuccess=()=>{const r=n.result;if(r>Qt){const a=o.index("timestamp"),i=r-Qt;let c=0;a.openCursor().onsuccess=l=>{const h=l.target.result;h&&c<i&&(h.delete(),c++,h.continue())}}},await new Promise((r,a)=>{t.oncomplete=()=>{e.close(),r()},t.onerror=()=>{e.close(),a(t.error)}})}catch(e){console.warn("[LLMApiLogger] Failed to save log to DB:",e)}}async function Jt(s){await Xt(s)}async function Yt(){try{const s=await at(),o=s.transaction(Z,"readonly").objectStore(Z).index("timestamp");return new Promise((n,r)=>{const a=o.getAll();a.onsuccess=()=>{s.close();const i=a.result.reverse();n(i)},a.onerror=()=>{s.close(),r(a.error)}})}catch(s){return console.warn("[LLMApiLogger] Failed to get logs from DB:",s),Y}}async function dr(s){const e=Y.find(t=>t.taskId===s&&t.status==="success"&&t.resultUrl);if(e)return e;try{return(await Yt()).find(n=>n.taskId===s&&n.status==="success"&&n.resultUrl)||null}catch(t){return console.warn("[LLMApiLogger] Failed to find log by taskId:",t),null}}async function ur(){Y.length=0;try{const s=await at(),e=s.transaction(Z,"readwrite");e.objectStore(Z).clear(),await new Promise((o,n)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),n(e.error)}})}catch(s){console.warn("[LLMApiLogger] Failed to clear logs from DB:",s)}}function hr(s){ne=s}function fr(s){const e=`llm-${Date.now()}-${Math.random().toString(36).substring(2,8)}`,t={id:e,timestamp:Date.now(),endpoint:s.endpoint,model:s.model,taskType:s.taskType,prompt:s.prompt?mr(s.prompt):void 0,requestBody:s.requestBody,hasReferenceImages:s.hasReferenceImages,referenceImageCount:s.referenceImageCount,status:"pending",taskId:s.taskId,workflowId:s.workflowId};return Y.unshift(t),Y.length>ir&&Y.pop(),Xt(t),ne&&ne({...t}),e}function gr(s,e){const t=Y.find(o=>o.id===s);t&&(t.status="success",t.httpStatus=e.httpStatus,t.duration=e.duration,t.resultType=e.resultType,t.resultCount=e.resultCount,t.resultUrl=e.resultUrl,t.resultText=e.resultText?it(e.resultText,1e3):void 0,t.responseBody=e.responseBody?it(e.responseBody,2e3):void 0,Jt(t),ne&&ne({...t}))}function pr(s,e){const t=Y.find(o=>o.id===s);t&&(t.status="error",t.httpStatus=e.httpStatus,t.duration=e.duration,t.errorMessage=wr(e.errorMessage),t.responseBody=e.responseBody?it(e.responseBody,2e3):void 0,Jt(t),ne&&ne({...t}))}function mr(s){return s.length<=200?s:s.substring(0,200)+"..."}function it(s,e){return s.length<=e?s:s.substring(0,e)+"..."}function wr(s){return s.length<=500?s:s.substring(0,500)+"..."}const L=Object.freeze(Object.defineProperty({__proto__:null,clearAllLLMApiLogs:ur,completeLLMApiLog:gr,failLLMApiLog:pr,findSuccessLogByTaskId:dr,getAllLLMApiLogs:Yt,setLLMApiLogBroadcast:hr,startLLMApiLog:fr},Symbol.toStringTag,{value:"Module"}));async function Sr(s,e,t,o,n,r,a){try{if(Qe(e)){ct(s,{success:!1,error:`Tool "${e}" requires main thread execution`,type:"error"},r,a);return}const i=await Ve(e,t,{geminiConfig:o,videoConfig:n,onProgress:()=>{}});ct(s,i,r,a)}catch(i){ct(s,{success:!1,error:i.message||"Tool execution failed",type:"error"},r)}}function ct(s,e,t,o){const n={type:"MCP_TOOL_RESULT",requestId:s,success:e.success,data:e.data,error:e.error,resultType:e.type};Ie(t,n)}const yr=Object.freeze(Object.defineProperty({__proto__:null,executeMCPTool:Sr},Symbol.toStringTag,{value:"Module"}))})();
|