aitu-app 0.5.48 → 0.5.49

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.
Files changed (163) hide show
  1. package/README.md +3 -3
  2. package/assets/{ChatMessagesArea-JoqYi_ld.js → ChatMessagesArea-B1bvPNpp.js} +3 -3
  3. package/assets/DialogTaskList-BSSAOh5P.js +1 -0
  4. package/assets/{DialogTaskList-CKYvHKiR.css → DialogTaskList-CB3gJdCM.css} +1 -1
  5. package/assets/{ToolboxDrawer-BOUbQFDR.js → ToolboxDrawer-D0eNy0jh.js} +1 -1
  6. package/assets/{ai-analyze-kieSuHap.js → ai-analyze-BfguOEXf.js} +1 -1
  7. package/assets/ai-image-generation-8fHKU7WT.js +1 -0
  8. package/assets/ai-image-generation-C0zeQsiB.css +1 -0
  9. package/assets/ai-video-generation-CUxwbJSx.js +5 -0
  10. package/assets/ai-video-generation-D3hRXNLI.css +1 -0
  11. package/assets/{arc-CK8n3maf.js → arc-CMg9c-1-.js} +1 -1
  12. package/assets/{arc-BaS7Wfdw.js → arc-Ch5MOiK9.js} +1 -1
  13. package/assets/{batch-image-generation-CXI7JS0B.js → batch-image-generation-Do-DwI3V.js} +1 -1
  14. package/assets/{blockDiagram-38ab4fdb-t4yZT92L.js → blockDiagram-38ab4fdb-BSLYbN30.js} +1 -1
  15. package/assets/{blockDiagram-38ab4fdb-2I9X-Mrl.js → blockDiagram-38ab4fdb-Ggjt8TxA.js} +1 -1
  16. package/assets/{c4Diagram-3d4e48cf-33GS-ewd.js → c4Diagram-3d4e48cf-C0C3iAjE.js} +1 -1
  17. package/assets/{c4Diagram-3d4e48cf-BC8WFOQe.js → c4Diagram-3d4e48cf-DkqBfxSN.js} +1 -1
  18. package/assets/channel-Ck9KEf2t.js +1 -0
  19. package/assets/channel-D5T_ahKm.js +1 -0
  20. package/assets/{classDiagram-70f12bd4-C8akklOH.js → classDiagram-70f12bd4-B4UmUpMK.js} +1 -1
  21. package/assets/{classDiagram-70f12bd4-CqBjoz8w.js → classDiagram-70f12bd4-Be9fBTCV.js} +1 -1
  22. package/assets/{classDiagram-v2-f2320105-B2ATMAZk.js → classDiagram-v2-f2320105-C2mLjgdh.js} +1 -1
  23. package/assets/{classDiagram-v2-f2320105-BupfQjOQ.js → classDiagram-v2-f2320105-VmfLSAro.js} +1 -1
  24. package/assets/clone-B_t1LC0g.js +1 -0
  25. package/assets/clone-pVjeeFE0.js +1 -0
  26. package/assets/{createText-2e5e7dd3-BYZnckX_.js → createText-2e5e7dd3--nnrtJNV.js} +1 -1
  27. package/assets/{createText-2e5e7dd3-CNyW-xvt.js → createText-2e5e7dd3-Br8kBZH8.js} +1 -1
  28. package/assets/{edges-e0da2a9e-BosqVjkA.js → edges-e0da2a9e-CHqsQcjz.js} +1 -1
  29. package/assets/{edges-e0da2a9e-UXCUvB-1.js → edges-e0da2a9e-Cjrn7Aq-.js} +1 -1
  30. package/assets/{erDiagram-9861fffd--Z0GlgEn.js → erDiagram-9861fffd-B_6GFzTQ.js} +1 -1
  31. package/assets/{erDiagram-9861fffd-wOY7N0rY.js → erDiagram-9861fffd-ufYXjhwZ.js} +1 -1
  32. package/assets/{flowDb-956e92f1-C3fx0kTY.js → flowDb-956e92f1-BKwUQ-hl.js} +1 -1
  33. package/assets/{flowDb-956e92f1-BVIXa6sC.js → flowDb-956e92f1-CAj-C03Q.js} +1 -1
  34. package/assets/{flowDiagram-66a62f08-BfFxG84W.js → flowDiagram-66a62f08-C8FXmVce.js} +1 -1
  35. package/assets/{flowDiagram-66a62f08-CDDobrgc.js → flowDiagram-66a62f08-Dq5fbX1Y.js} +1 -1
  36. package/assets/flowDiagram-v2-96b9c2cf-8w1P8dgG.js +1 -0
  37. package/assets/flowDiagram-v2-96b9c2cf-CRt8Tw6t.js +1 -0
  38. package/assets/{flowchart-elk-definition-4a651766-DTa5Ugc1.js → flowchart-elk-definition-4a651766-BjL7RQ7O.js} +1 -1
  39. package/assets/{flowchart-elk-definition-4a651766-BmmcFiPZ.js → flowchart-elk-definition-4a651766-CD9vIlxr.js} +1 -1
  40. package/assets/{ganttDiagram-c361ad54-DPlnAJJx.js → ganttDiagram-c361ad54-D7_HVbbq.js} +1 -1
  41. package/assets/{ganttDiagram-c361ad54-Bbn-nHAs.js → ganttDiagram-c361ad54-n9ELUpiB.js} +1 -1
  42. package/assets/{gitGraphDiagram-72cf32ee-Dl7ComzH.js → gitGraphDiagram-72cf32ee-B47OoAyc.js} +1 -1
  43. package/assets/{gitGraphDiagram-72cf32ee-DeIZExbc.js → gitGraphDiagram-72cf32ee-xb7q7cuL.js} +1 -1
  44. package/assets/{graph-DHiGmXV6.js → graph-BeeTwCH3.js} +1 -1
  45. package/assets/{graph-Dfptg6Al.js → graph-Dz4khTZm.js} +1 -1
  46. package/assets/{grid-image-CARGYvh_.js → grid-image-ggMTti9w.js} +1 -1
  47. package/assets/{has-9uhq4yT9.js → has-BsV_fqUH.js} +1 -1
  48. package/assets/{hasIn-CvQXXf4b.js → hasIn-__wdhirj.js} +1 -1
  49. package/assets/{index-3862675e-DUJvwjP7.js → index-3862675e-CYiGbhd6.js} +1 -1
  50. package/assets/{index-3862675e-DCshUjlh.js → index-3862675e-CkTdLODf.js} +1 -1
  51. package/assets/{index-DM-AXm0q.js → index-4geuWAgE.js} +1 -1
  52. package/assets/index-920UvYLQ.css +9 -0
  53. package/assets/{index-Dj4_g4Si.js → index-9ACcVAdm.js} +4 -4
  54. package/assets/{index-sBjGDMrw.js → index-B-LmeOUH.js} +1 -1
  55. package/assets/{index-DIw6QU0k.js → index-BNEDl4J2.js} +1 -1
  56. package/assets/{index-B-jeRaNV.js → index-BVpCfTKg.js} +1 -1
  57. package/assets/{index-DVI-EeTo.js → index-C6OIGmaF.js} +1 -1
  58. package/assets/{index-Y-mRUgjd.js → index-CvrZFlag.js} +314 -314
  59. package/assets/{index-CpsKZ1yJ.js → index-DxPda7bw.js} +1 -1
  60. package/assets/{index-CeRB07JB.js → index-FYEvKL6-.js} +2 -2
  61. package/assets/{index-DB2ccmBs.js → index-WI9w4wcL.js} +1 -1
  62. package/assets/{infoDiagram-f8f76790-BoZxRLZa.js → infoDiagram-f8f76790-BAaXqHpe.js} +1 -1
  63. package/assets/{infoDiagram-f8f76790-BjAnq3Fb.js → infoDiagram-f8f76790-C8gMSdke.js} +1 -1
  64. package/assets/{inspiration-board-DXC6MTKm.js → inspiration-board-DLQ3bgA5.js} +1 -1
  65. package/assets/{isEmpty-CRzPUjzr.js → isEmpty-CRXO1bLi.js} +1 -1
  66. package/assets/{journeyDiagram-49397b02-CsYOzIaw.js → journeyDiagram-49397b02-Bth8e3TS.js} +1 -1
  67. package/assets/{journeyDiagram-49397b02-vhPJlWtN.js → journeyDiagram-49397b02-C7g-8Hvn.js} +1 -1
  68. package/assets/{layout-DsD2W5B-.js → layout-B0Pa2rBm.js} +1 -1
  69. package/assets/{layout-XsNQWLV0.js → layout-KY-X4wEQ.js} +1 -1
  70. package/assets/{line-GD0UFJy2.js → line-BDjluZsg.js} +1 -1
  71. package/assets/{line-DrBei8wT.js → line-Nete9nw6.js} +1 -1
  72. package/assets/{linear-DARUpMG_.js → linear-BlRKrrAt.js} +1 -1
  73. package/assets/{linear-C3LLInY2.js → linear-Bu02SEaK.js} +1 -1
  74. package/assets/{mermaid.core-mIRDwmS-.js → mermaid.core-yVPD7ieH.js} +4 -4
  75. package/assets/{mindmap-definition-fc14e90a-DzsbYOPH.js → mindmap-definition-fc14e90a-CbPO3n6C.js} +1 -1
  76. package/assets/{mindmap-definition-fc14e90a-RTmso76i.js → mindmap-definition-fc14e90a-U1pw-9Ng.js} +1 -1
  77. package/assets/{photo-wall-splitter-BCzhetlI.js → photo-wall-splitter-gAV3J-3j.js} +1 -1
  78. package/assets/{pick-Cnk3HYZr.js → pick-CIdLSF0Z.js} +1 -1
  79. package/assets/{pieDiagram-8a3498a8-BAWZdKJV.js → pieDiagram-8a3498a8-CFDa6wYQ.js} +1 -1
  80. package/assets/{pieDiagram-8a3498a8-BtX8nRt7.js → pieDiagram-8a3498a8-D0ywaKa6.js} +1 -1
  81. package/assets/{quadrantDiagram-120e2f19-9KVrLKzH.js → quadrantDiagram-120e2f19-B0aJtXqY.js} +1 -1
  82. package/assets/{quadrantDiagram-120e2f19-DuY-5Itm.js → quadrantDiagram-120e2f19-JUTgchBu.js} +1 -1
  83. package/assets/{requirementDiagram-deff3bca-C8rxl4Fw.js → requirementDiagram-deff3bca-B9FhatVo.js} +1 -1
  84. package/assets/{requirementDiagram-deff3bca-x1t2_QSh.js → requirementDiagram-deff3bca-D8Rme9Ge.js} +1 -1
  85. package/assets/{sankeyDiagram-04a897e0-BkVc7A98.js → sankeyDiagram-04a897e0-B-gbcDvI.js} +1 -1
  86. package/assets/{sankeyDiagram-04a897e0-DOdzmEl3.js → sankeyDiagram-04a897e0-DfbHNdsW.js} +1 -1
  87. package/assets/{sequenceDiagram-704730f1-BcyOOfKB.js → sequenceDiagram-704730f1-B6l3EwQG.js} +1 -1
  88. package/assets/{sequenceDiagram-704730f1-CYZBUVl_.js → sequenceDiagram-704730f1-BKBzlyjL.js} +1 -1
  89. package/assets/settings-dialog-Blkz7e5P.js +1 -0
  90. package/assets/{stateDiagram-587899a1-AYFDuJIM.js → stateDiagram-587899a1-CWO6S--h.js} +1 -1
  91. package/assets/{stateDiagram-587899a1-CAV_A2k6.js → stateDiagram-587899a1-D9ZTBTJW.js} +1 -1
  92. package/assets/{stateDiagram-v2-d93cdb3a-BS-kfhoL.js → stateDiagram-v2-d93cdb3a-DpPNUJIJ.js} +1 -1
  93. package/assets/{stateDiagram-v2-d93cdb3a-2j9li-ny.js → stateDiagram-v2-d93cdb3a-RDHyBBsc.js} +1 -1
  94. package/assets/{styles-6aaf32cf-CJe3mUWs.js → styles-6aaf32cf-raskOVgm.js} +1 -1
  95. package/assets/{styles-6aaf32cf-Dt2RGJ8A.js → styles-6aaf32cf-rn-U3G-T.js} +1 -1
  96. package/assets/{styles-9a916d00-IS97_M50.js → styles-9a916d00-8SvYD_6R.js} +1 -1
  97. package/assets/{styles-9a916d00-cAlItWAP.js → styles-9a916d00-het7_VjA.js} +1 -1
  98. package/assets/{styles-c10674c1-C-hWHZcb.js → styles-c10674c1-C1pqdP96.js} +1 -1
  99. package/assets/{styles-c10674c1-DVJIr7Cb.js → styles-c10674c1-CUvKZMsb.js} +1 -1
  100. package/assets/{svgDrawCommon-08f97a94-C0x85f0W.js → svgDrawCommon-08f97a94-CzdMcmjT.js} +1 -1
  101. package/assets/{svgDrawCommon-08f97a94-CaM6o6f6.js → svgDrawCommon-08f97a94-DfziZaZJ.js} +1 -1
  102. package/assets/{timeline-definition-85554ec2-BYDl8yjo.js → timeline-definition-85554ec2-D8z5E6iu.js} +1 -1
  103. package/assets/{timeline-definition-85554ec2-hev3Czd5.js → timeline-definition-85554ec2-DSFZUclI.js} +1 -1
  104. package/assets/{ttd-dialog-Dz9MP-od.js → ttd-dialog-DMiivQmt.js} +4 -4
  105. package/assets/{upload-Dw77S_Me.js → upload-Dh3D6Z7E.js} +1 -1
  106. package/assets/{video-recovery-service-DrA0J5gR.js → video-recovery-service-DYhEBO96.js} +1 -1
  107. package/assets/{xychartDiagram-e933f94c-Dd-QLan6.js → xychartDiagram-e933f94c-O_OlRzES.js} +1 -1
  108. package/assets/{xychartDiagram-e933f94c-PAtdBcGf.js → xychartDiagram-e933f94c-pg-_fREb.js} +1 -1
  109. package/cdn-config.js +0 -7
  110. package/package.json +1 -1
  111. package/precache-manifest.json +305 -233
  112. package/sw.js +7 -7
  113. package/user-manual/gifs//346/200/235/347/273/264/345/257/274/345/233/276/345/210/233/345/273/272/346/274/224/347/244/272.gif +0 -0
  114. package/user-manual/screenshots/ai-step-0.png +0 -0
  115. package/user-manual/screenshots/ai-step-1.png +0 -0
  116. package/user-manual/screenshots/ai-step-2.png +0 -0
  117. package/user-manual/screenshots/ai-step-3.png +0 -0
  118. package/user-manual/screenshots/app-menu.png +0 -0
  119. package/user-manual/screenshots/backup-restore.png +0 -0
  120. package/user-manual/screenshots/canvas-tools.png +0 -0
  121. package/user-manual/screenshots/debug-panel.png +0 -0
  122. package/user-manual/screenshots/drawing-step-0.png +0 -0
  123. package/user-manual/screenshots/drawing-step-1.png +0 -0
  124. package/user-manual/screenshots/drawing-step-2.png +0 -0
  125. package/user-manual/screenshots/edit-selected.png +0 -0
  126. package/user-manual/screenshots/element-selected.png +0 -0
  127. package/user-manual/screenshots/flowchart-step-1.png +0 -0
  128. package/user-manual/screenshots/flowchart-step-2.png +0 -0
  129. package/user-manual/screenshots/flowchart-step-3.png +0 -0
  130. package/user-manual/screenshots/image-preview-empty.png +0 -0
  131. package/user-manual/screenshots/insert-from-library.png +0 -0
  132. package/user-manual/screenshots/insert-tools.png +0 -0
  133. package/user-manual/screenshots/inspiration-step-1.png +0 -0
  134. package/user-manual/screenshots/inspiration-step-2.png +0 -0
  135. package/user-manual/screenshots/media-library.png +0 -0
  136. package/user-manual/screenshots/mindmap-step-1.png +0 -0
  137. package/user-manual/screenshots/mindmap-step-2.png +0 -0
  138. package/user-manual/screenshots/mindmap-toolbar-menu.png +0 -0
  139. package/user-manual/screenshots/project-drawer.png +0 -0
  140. package/user-manual/screenshots/settings-dialog.png +0 -0
  141. package/user-manual/screenshots/shape-step-1.png +0 -0
  142. package/user-manual/screenshots/shape-step-2.png +0 -0
  143. package/user-manual/screenshots/text-step-1.png +0 -0
  144. package/user-manual/screenshots/text-step-2.png +0 -0
  145. package/user-manual/screenshots/toolbox-drawer.png +0 -0
  146. package/user-manual/screenshots/toolbox-entry.png +0 -0
  147. package/user-manual/screenshots/video-entry.png +0 -0
  148. package/user-manual/screenshots/view-navigation.png +0 -0
  149. package/user-manual/screenshots/zoom-menu.png +0 -0
  150. package/version.json +8 -3
  151. package/assets/DialogTaskList-Bny0jVKZ.js +0 -1
  152. package/assets/ai-image-generation-BFVVUcys.js +0 -1
  153. package/assets/ai-image-generation-DGSgu0yT.css +0 -1
  154. package/assets/ai-video-generation-BeUDCJbm.js +0 -5
  155. package/assets/ai-video-generation-DcOYvVJu.css +0 -1
  156. package/assets/channel-CDoSfPuP.js +0 -1
  157. package/assets/channel-EocIoBTY.js +0 -1
  158. package/assets/clone-B1Q1_5Pt.js +0 -1
  159. package/assets/clone-BSgWY5XH.js +0 -1
  160. package/assets/flowDiagram-v2-96b9c2cf-CHM0pX9Y.js +0 -1
  161. package/assets/flowDiagram-v2-96b9c2cf-DKLcZ2Te.js +0 -1
  162. package/assets/index-DGDQ0Qn2.css +0 -9
  163. package/assets/settings-dialog-Dq2kMBKN.js +0 -1
package/sw.js CHANGED
@@ -1,11 +1,11 @@
1
- (function(){"use strict";var A=(s=>(s.PENDING="pending",s.PROCESSING="processing",s.COMPLETED="completed",s.FAILED="failed",s.CANCELLED="cancelled",s))(A||{}),L=(s=>(s.IMAGE="image",s.VIDEO="video",s.CHARACTER="character",s.INSPIRATION_BOARD="inspiration_board",s.CHAT="chat",s))(L||{}),I=(s=>(s.SUBMITTING="submitting",s.POLLING="polling",s.DOWNLOADING="downloading",s))(I||{});const ks={timeouts:{image:600*1e3,video:1200*1e3,character:600*1e3,inspiration_board:600*1e3,chat:600*1e3}},Ps=["apikey","api_key","password","token","secret","authorization","bearer","credential","key"];function je(s){if(!s)return s;if(typeof s=="string")return s.toLowerCase().startsWith("bearer ")?"[REDACTED]":s;if(Array.isArray(s))return s.map(e=>je(e));if(typeof s=="object"){const e={};for(const[t,o]of Object.entries(s)){const r=t.toLowerCase();Ps.some(n=>r.includes(n))?e[t]="[REDACTED]":e[t]=je(o)}return e}return s}function Dt(s){if(!s)return s;try{const e=JSON.parse(s),t=je(e);return JSON.stringify(t)}catch{let e=s;return e=e.replace(/Bearer\s+[a-zA-Z0-9-_]+/gi,"Bearer [REDACTED]"),e=e.replace(/"(api[_-]?key|apikey|authorization|token|secret|password|credential)"\s*:\s*"[^"]+"/gi,(t,o)=>`"${o}": "[REDACTED]"`),e}}function Ve(s){return s instanceof Error?s.name||"Error":"Unknown error"}const Qe="sw-task-queue",Lt=2,k="tasks",j="config",B="workflows",U="chat-workflows",F="pending-tool-requests",Ms=[k,j,B,U,F];function vs(){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 xs(s){const e=[];for(const t of Ms)s.objectStoreNames.contains(t)||e.push(t);return e}function Ns(s){return new Promise((e,t)=>{const o=s+1;console.log(`[SWStorage] Repairing database: upgrading from v${s} to v${o}`);const r=indexedDB.open(Qe,o);r.onerror=()=>{console.error("[SWStorage] Failed to repair DB:",r.error),t(r.error)},r.onsuccess=()=>{e(r.result)},r.onupgradeneeded=n=>{const a=n.target.result;It(a)}})}function It(s){if(!s.objectStoreNames.contains(k)){const e=s.createObjectStore(k,{keyPath:"id"});e.createIndex("status","status",{unique:!1}),e.createIndex("type","type",{unique:!1}),e.createIndex("createdAt","createdAt",{unique:!1})}if(s.objectStoreNames.contains(j)||s.createObjectStore(j,{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(U)){const e=s.createObjectStore(U,{keyPath:"id"});e.createIndex("status","status",{unique:!1}),e.createIndex("createdAt","createdAt",{unique:!1})}s.objectStoreNames.contains(F)||s.createObjectStore(F,{keyPath:"requestId"}).createIndex("workflowId","workflowId",{unique:!1})}async function Bs(){const s=await vs();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 r=o.result,n=xs(r);if(n.length>0){console.warn(`[SWStorage] Missing object stores: ${n.join(", ")}. Repairing...`),r.close(),Ns(r.version).then(e).catch(t);return}e(r)},o.onupgradeneeded=r=>{const n=r.target.result;It(n)}})}class Us{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=Bs()),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((r,n)=>{const a=o.transaction(k,"readwrite"),i=a.objectStore(k);for(const c of e)i.put(c);a.oncomplete=()=>{t.forEach(({resolve:c})=>c()),r()},a.onerror=()=>{const c=a.error;t.forEach(({reject:l})=>l(c)),n(c)}})}catch(o){console.error("[SWStorage] Failed to batch save tasks:",o),t.forEach(({reject:r})=>r(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((r,n)=>{const c=o.transaction(k,"readwrite").objectStore(k).put(e);c.onerror=()=>n(c.error),c.onsuccess=()=>r()}),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,r)=>{const i=t.transaction(k,"readonly").objectStore(k).get(e);i.onerror=()=>r(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(k,"readonly").objectStore(k).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,r)=>{const c=t.transaction(k,"readonly").objectStore(k).index("status").getAll(e);c.onerror=()=>r(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:r,type:n,sortOrder:a="desc"}=e;try{const i=await this.getDB();return new Promise((c,l)=>{const p=i.transaction(k,"readonly").objectStore(k),w=p.index("createdAt"),m=p.count();let d=0;m.onsuccess=()=>{d=m.result};const y=a==="desc"?"prev":"next",S=w.openCursor(null,y),h=[];let f=0,g=0;S.onerror=()=>l(S.error),S.onsuccess=T=>{const _=T.target.result;if(!_){c({tasks:h,total:g,hasMore:g>t+h.length});return}const E=_.value,D=!r||E.status===r,b=!n||E.type===n;D&&b&&(g++,f<t?f++:h.length<o&&h.push(E)),_.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,r)=>{const i=t.transaction(k,"readwrite").objectStore(k).delete(e);i.onerror=()=>r(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((r,n)=>{const a=o.transaction(j,"readwrite"),i=a.objectStore(j);e&&i.put({key:"gemini",...e}),t&&i.put({key:"video",...t}),a.oncomplete=()=>r(),a.onerror=()=>n(a.error)})}catch(o){console.error("[SWStorage] Failed to save config:",Ve(o))}}async loadConfig(){try{const e=await this.getDB();return new Promise((t,o)=>{const r=e.transaction(j,"readonly"),n=r.objectStore(j),a=n.get("gemini"),i=n.get("video");r.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})},r.onerror=()=>o(r.error)})}catch(e){return console.error("[SWStorage] Failed to load config:",Ve(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,r)=>{const n=t.transaction(j,"readwrite");n.objectStore(j).put({key:"systemPrompt",value:e,updatedAt:Date.now()}),n.oncomplete=()=>o(),n.onerror=()=>r(n.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(j,"readonly").objectStore(j).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,r)=>{const i=t.transaction(B,"readwrite").objectStore(B).put(e);i.onerror=()=>r(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,r)=>{const i=t.transaction(B,"readonly").objectStore(B).get(e);i.onerror=()=>r(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,r)=>{const c=t.transaction(B,"readonly").objectStore(B).index("status").getAll(e);c.onerror=()=>r(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,r)=>{const i=t.transaction(B,"readwrite").objectStore(B).delete(e);i.onerror=()=>r(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,r)=>{const i=t.transaction(U,"readwrite").objectStore(U).put(e);i.onerror=()=>r(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,r)=>{const i=t.transaction(U,"readonly").objectStore(U).get(e);i.onerror=()=>r(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(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 chat workflows:",e),[]}}async getChatWorkflowsByStatus(e){try{const t=await this.getDB();return new Promise((o,r)=>{const c=t.transaction(U,"readonly").objectStore(U).index("status").getAll(e);c.onerror=()=>r(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,r)=>{const i=t.transaction(U,"readwrite").objectStore(U).delete(e);i.onerror=()=>r(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,r)=>{const i=t.transaction(F,"readwrite").objectStore(F).put(e);i.onerror=()=>r(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(F,"readonly").objectStore(F).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,r)=>{const c=t.transaction(F,"readonly").objectStore(F).index("workflowId").getAll(e);c.onerror=()=>r(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,r)=>{const i=t.transaction(F,"readonly").objectStore(F).get(e);i.onerror=()=>r(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,r)=>{const i=t.transaction(F,"readwrite").objectStore(F).delete(e);i.onerror=()=>r(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 C=new Us;let Pe=!1;const Fs=500,oe=[];let Me=0;function qs(){return Pe}const $s=["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"],Ae=new Map;function Ot(s){const e=Pe;Pe=s,!s&&e&&(oe.length=0,Ae.clear(),Me=0)}function Je(){return Pe}function Wt(s){return qs()?!$s.includes(s):!1}function Gs(s,e,t){if(!Wt(s))return"";const o=`pm-recv-${Date.now()}-${++Me}`,r={id:o,timestamp:Date.now(),direction:"receive",messageType:s,data:Xe(e),clientId:t};if(Pt(r),zs(s)){const n=Mt(e);n&&Ae.set(n,{entry:r,startTime:Date.now()})}return o}function kt(s,e,t){if(!Wt(s))return"";const o=`pm-send-${Date.now()}-${++Me}`,r={id:o,timestamp:Date.now(),direction:"send",messageType:s,data:Xe(e),clientId:t};if(Ks(s)){const n=Mt(e);if(n){const a=Ae.get(n);a&&(r.duration=Date.now()-a.startTime,a.entry.response=Xe(e),a.entry.duration=r.duration,Ae.delete(n))}}return Pt(r),o}function Pt(s){oe.unshift(s),oe.length>Fs&&oe.pop()}function Re(){return[...oe]}function Hs(){oe.length=0,Ae.clear(),Me=0}function zs(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 Ks(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 Mt(s){if(!s||typeof s!="object")return null;const e=s;return e.requestId||e.taskId||e.workflowId||e.chatId||null}function Xe(s){if(!s)return s;try{const e=JSON.parse(JSON.stringify(s));return vt(e),e}catch{return"[Non-serializable data]"}}function vt(s){if(!s||typeof s!="object")return;const e=["apiKey","password","token","secret","key"],t=s;for(const o in t)e.some(r=>o.toLowerCase().includes(r))?t[o]="[REDACTED]":typeof t[o]=="object"&&vt(t[o])}function js(){const s={total:oe.length,sent:0,received:0,byType:{}};for(const e of oe)e.direction==="send"?s.sent++:s.received++,s.byType[e.messageType]||(s.byType[e.messageType]=0),s.byType[e.messageType]++;return s}let ve=!1,he=null;function Ye(s){ve=s,Ot(s)}function Vs(s){he=s}function xt(s,e){if(!s){console.warn("[MessageBus] No client provided");return}let t="";if(Je()){const o=(e==null?void 0:e.type)||"unknown";t=kt(o,e,s.id)}try{s.postMessage(e)}catch(o){console.warn("[MessageBus] Failed to postMessage to client:",s.id,o);return}if(t&&ve&&he){const r=Re().find(n=>n.id===t);r&&he(r)}}function Nt(s){const e=self,t=(s==null?void 0:s.type)||"unknown";e.clients.matchAll().then(o=>{o.forEach(r=>{let n="";if(Je()&&(n=kt(t,s,r.id)),r.postMessage(s),n&&ve&&he){const i=Re().find(c=>c.id===n);i&&he(i)}})})}async function xe(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?(xt(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 Qs(s,e){ve=!1,Ot(!1),he=null}const Js={"1x1":"1024x1024","16x9":"1792x1024","9x16":"1024x1792","4x3":"1536x1152","3x4":"1152x1536","3x2":"1536x1024","2x3":"1024x1536","4x5":"1024x1280","5x4":"1280x1024","21x9":"1792x768"};function Ze(s){return!s||s==="auto"?void 0:{"1:1":"1x1","2:3":"2x3","3:2":"3x2","3:4":"3x4","4:3":"4x3","4:5":"4x5","5:4":"5x4","9:16":"9x16","16:9":"16x9","21:9":"21x9"}[s]||Js[s]||s}function Bt(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 Ut(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 Ft extends Error{constructor(e){super(e),this.name="VideoGenerationFailedError"}}async function et(s,e,t={}){var w,m;const{onProgress:o,signal:r,apiKey:n,interval:a=5e3,maxAttempts:i=1080}=t;let c=0,l=0;const u=10,{debugFetch:p}=await Promise.resolve().then(()=>N);for(;c<i;){if(r!=null&&r.aborted)throw new Error("Video generation cancelled");try{const d=await p(`${s}/videos/${e}`,{headers:n?{Authorization:`Bearer ${n}`}:{},signal:r},{label:`🔄 查询视频状态 #${c+1}`,logResponseBody:!0});if(!d.ok){if(l++,console.warn(`[VideoPolling] Status query failed (${d.status}), attempt ${l}/${u}, will retry with longer interval`),l>=u)throw new Error(`Failed to get video status after ${u} consecutive errors: ${d.status}`);const f=Math.min(a*Math.pow(1.5,l),6e4);await new Promise(g=>setTimeout(g,f)),c++;continue}l=0;const y=await d.json(),S=(w=y.status)==null?void 0:w.toLowerCase(),h=y.progress??Math.min(10+c*2,90);if(o==null||o(h,"polling"),S==="completed"||S==="succeeded")return o==null||o(100),y;if(S==="failed"||S==="error"){const f=typeof y.error=="string"?y.error:((m=y.error)==null?void 0:m.message)||y.message||"Video generation failed";throw new Ft(f)}await new Promise(f=>setTimeout(f,a)),c++}catch(d){if(d instanceof Ft){if((d.message.includes("429")||d.message.toLowerCase().includes("too many requests"))&&l<u){l++,console.warn(`[VideoPolling] Business error looks like rate limit (#${l}): ${d.message}, retrying...`);const h=Math.min(a*Math.pow(1.5,l),6e4);await new Promise(f=>setTimeout(f,h)),c++;continue}throw d}if(r!=null&&r.aborted)throw new Error("Video generation cancelled");if(l++,console.warn(`[VideoPolling] Network error during status query, attempt ${l}/${u}:`,d),l>=u)throw d;const y=Math.min(a*Math.pow(1.5,l),6e4);await new Promise(S=>setTimeout(S,y)),c++}}throw new Error("Video generation timed out")}const tt="drawnix-images",Xs=720*60*1e3,Ys="drawnix-unified-cache",st="media";async function Zs(s){return new Promise(e=>{try{const t=indexedDB.open(Ys);t.onerror=()=>{console.warn("[MediaUtils] Failed to open IndexedDB:",t.error),e(null)},t.onsuccess=()=>{try{const o=t.result;if(!o.objectStoreNames.contains(st)){o.close(),e(null);return}const a=o.transaction(st,"readonly").objectStore(st).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 ot(s,e){try{if(s.startsWith("data:"))return rt(s);const t=await caches.open(tt),o=await t.match(s);if(o)return await o.blob();const r=await fetch(s,{signal:e});if(r.ok){const n=await r.blob();try{const a=new Response(n.slice(),{headers:{"Content-Type":n.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 n}return console.warn(`[MediaUtils] Network fetch failed: ${s.substring(0,50)}...`,r.status),null}catch(t){return console.warn(`[MediaUtils] Error in fetchImageWithCache: ${s.substring(0,50)}...`,t),null}}function rt(s){try{const[e,t]=s.split(",");if(!t)return null;const o=e.match(/data:([^;]+)/),r=o?o[1]:"image/png",n=atob(t),a=new Uint8Array(n.length);for(let i=0;i<n.length;i++)a[i]=n.charCodeAt(i);return new Blob([a],{type:r})}catch(e){return console.warn("[MediaUtils] Failed to convert data URL to Blob:",e),null}}async function qt(s){return new Promise((e,t)=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.onerror=t,o.readAsDataURL(s)})}const nt=1024*1024,Ne=.1,Be=2048;async function $t(s,e=nt){if(s.size<=e)return s;try{const t=await createImageBitmap(s);let{width:o,height:r}=t;const n={width:o,height:r};if(o>Be||r>Be){const y=Math.min(Be/o,Be/r);o=Math.round(o*y),r=Math.round(r*y)}const a=new OffscreenCanvas(o,r),i=a.getContext("2d");if(!i)return console.warn("[MediaUtils] Failed to get 2d context from OffscreenCanvas"),s;i.drawImage(t,0,0,o,r),t.close();let c=Ne,l=.95,u=null,p=0;const w=8;for(let y=0;y<w;y++){const S=(c+l)/2,h=await a.convertToBlob({type:"image/jpeg",quality:S});if(h.size<=e?(u=h,p=S,c=S):l=S,l-c<.02)break}if(u)return u;let m=await a.convertToBlob({type:"image/jpeg",quality:Ne}),d=.8;for(;d>=.3&&m.size>e;){const y=Math.round(o*d),S=Math.round(r*d),h=new OffscreenCanvas(y,S),f=h.getContext("2d");if(!f)break;const g=await createImageBitmap(s);f.drawImage(g,0,0,y,S),g.close();let T=Ne,_=.95,E=null;for(let D=0;D<6;D++){const b=(T+_)/2,W=await h.convertToBlob({type:"image/jpeg",quality:b});if(W.size<=e?(E=W,T=b):_=b,_-T<.02)break}if(E)return E;m=await h.convertToBlob({type:"image/jpeg",quality:Ne}),d-=.1}return m}catch(t){return console.warn("[MediaUtils] Image compression failed, returning original:",t),s}}async function ne(s,e=nt){const t=await $t(s,e);return qt(t)}async function eo(s,e){let t=null,o="";if(typeof s=="string"?(o=s,t=await ot(s,e)):t=s,!t)throw new Error("Failed to fetch image for info");const r=t.size,n=await createImageBitmap(t),a=n.width,i=n.height;return n.close(),o||(o=await ne(t,200*1024)),{width:a,height:i,size:r,url:o}}async function Gt(s,e){if(s.startsWith("data:")){if((s.split(",")[1]||"").length*3/4>nt){const r=rt(s);if(r){const n=await ne(r);return{originalUrl:s,value:n,isBase64:!0}}}return{originalUrl:s,value:s,isBase64:!0}}try{const t=await caches.open(tt);if(s.startsWith("/asset-library/")){const o=await t.match(s);if(o){const r=await o.blob(),n=await ne(r);return{originalUrl:s,value:n,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}`,r=await t.match(o);if(r){const n=await r.blob(),a=await ne(n);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 n=await Zs(s),a=o.headers.get("sw-cache-date"),i=a?parseInt(a,10):0,c=n??i,l=Date.now(),u=c?l-c:1/0,p=u/(3600*1e3);if(c>0&&u<Xs)return{originalUrl:s,value:s,isBase64:!1};const w=await o.blob(),m=await ne(w);return{originalUrl:s,value:m,isBase64:!0}}const r=await fetch(s,{signal:e});if(r.ok){const n=await r.blob();try{const i=new Response(n.slice(),{headers:{"Content-Type":n.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 ne(n);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 Ht(s,e){return!s||s.length===0?[]:(await Promise.all(s.map(o=>Gt(o,e)))).map(o=>o.value)}function at(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=Ze(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 to(s){return s.startsWith("data:image/")&&s.includes(";base64,")}function so(s){const e=s.match(/^data:(image\/[^;]+);base64,(.+)$/);return e?{mimeType:e[1],base64:e[2]}:null}async function zt(s,e="image/png"){try{const t=atob(s),o=new Uint8Array(t.length);for(let u=0;u<t.length;u++)o[u]=t.charCodeAt(u);const r=new Blob([o],{type:e}),n=`img-${Date.now()}-${Math.random().toString(36).substring(2,10)}`,a=e.split("/")[1]||"png",i=`/__aitu_cache__/image/${n}.${a}`,c=await caches.open(tt),l=new Response(r,{status:200,headers:{"Content-Type":e,"Content-Length":r.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 it(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 zt(c.b64_json,"image/png"):null}const o=s.data[0],r=await t(o);if(!r)throw(i=o.revised_prompt)!=null&&i.includes("PROHIBITED_CONTENT")?new Error("内容被拒绝:包含违禁内容"):new Error("No image URL in response");const n=s.data.map((c,l)=>t(c)),a=(await Promise.all(n)).filter(Boolean);return{url:r,urls:a.length>1?a:void 0}}async function Kt(s){if(!to(s))return{url:s,migrated:!1};const e=so(s);if(!e)return{url:s,migrated:!1};try{return{url:await zt(e.base64,e.mimeType),migrated:!0}}catch(t){return console.error("[Migration] Failed to migrate Base64 URL:",t),{url:s,migrated:!1}}}const ct=Object.freeze(Object.defineProperty({__proto__:null,blobToBase64:qt,blobToCompressedBase64:ne,buildImageGenerationRequestBody:at,compressImageBlob:$t,convertAspectRatioToSize:Ze,dataUrlToBlob:rt,extractUrlsFromUploadedImages:Bt,fetchImageWithCache:ot,getImageInfo:eo,mergeReferenceImages:Ut,migrateBase64UrlIfNeeded:Kt,parseImageGenerationResponse:it,pollVideoUntilComplete:et,processReferenceImage:Gt,processReferenceImages:Ht},Symbol.toStringTag,{value:"Module"}));class oo{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,I.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:r}=t,{params:n}=e,a=n.referenceImages||Bt(n.uploadedImages);let i;const{getImageInfo:c}=await Promise.resolve().then(()=>ct),{startLLMApiLog:l,completeLLMApiLog:u,failLLMApiLog:p}=await Promise.resolve().then(()=>O),{debugFetch:w}=await Promise.resolve().then(()=>N);let m;a&&a.length>0&&(i=await Ht(a,o),m=await Promise.all(a.map(async E=>{try{const D=await c(E,o);return{url:D.url,size:D.size,width:D.width,height:D.height}}catch(D){return console.warn(`[ImageHandler] Failed to get image info for log: ${E}`,D),{url:E,size:0,width:0,height:0}}})));const d=n.size||Ze(n.aspectRatio),y=at({prompt:n.prompt,model:n.model,size:d,referenceImages:i,isInspirationBoard:n.isInspirationBoard,inspirationBoardImageCount:n.inspirationBoardImageCount},r.modelName);t.onProgress(e.id,10,I.SUBMITTING);const S=Date.now(),h=l({endpoint:"/images/generations",model:r.modelName||"unknown",taskType:"image",prompt:n.prompt,hasReferenceImages:!!i&&i.length>0,referenceImageCount:i==null?void 0:i.length,referenceImages:m,taskId:e.id}),f=await w(`${r.baseUrl}/images/generations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r.apiKey}`},body:JSON.stringify(y),signal:o},{label:`🎨 生成图片 (${r.modelName})`,logRequestBody:!0,logResponseBody:!0});if(!f.ok){const E=await f.text();throw p(h,{httpStatus:f.status,duration:Date.now()-S,errorMessage:E,responseBody:E}),new Error(`Image generation failed: ${f.status} - ${E}`)}t.onProgress(e.id,80,I.DOWNLOADING);const g=await f.json(),T=JSON.stringify(g),{url:_}=await it(g,e.id);return u(h,{httpStatus:f.status,duration:Date.now()-S,resultType:"image",resultCount:1,resultUrl:_,responseBody:T}),t.onProgress(e.id,100),{url:_,format:"png",size:0,width:n.width,height:n.height}}}class ro{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,I.SUBMITTING);const{response:r,logId:n}=await this.submitVideoGeneration(e,t,o.signal);return t.onRemoteId(e.id,r.id),t.onProgress(e.id,5,I.POLLING),await this.pollUntilComplete(r.id,e.id,t,o.signal,n)}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:r}=await Promise.resolve().then(()=>O),n=r({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,I.POLLING),await this.pollUntilComplete(e.remoteId,e.id,t,o.signal,n)}finally{this.cleanup(e.id)}}cancel(e){this.cleanup(e)}async submitVideoGeneration(e,t,o){const{videoConfig:r}=t,{params:n}=e,a=new FormData;a.append("model",n.model||"veo3"),a.append("prompt",n.prompt),n.duration&&a.append("seconds",String(n.duration)),n.size&&a.append("size",n.size);const i=Ut({referenceImages:n.referenceImages,uploadedImages:n.uploadedImages,inputReference:n.inputReference,inputReferences:n.inputReferences}),{getImageInfo:c}=await Promise.resolve().then(()=>ct),l=await Promise.all(i.map(async g=>{try{const T=await c(g,o);return{url:T.url,size:T.size,width:T.width,height:T.height}}catch(T){return console.warn(`[VideoHandler] Failed to get image info for log: ${g}`,T),{url:g,size:0,width:0,height:0}}}));if(i.length>0)for(let g=0;g<i.length;g++){const T=i[g];try{const _=await ot(T,o);_?a.append("input_reference",_,`reference-${g+1}.png`):(console.warn(`[VideoHandler] Failed to get reference image: ${T}`),a.append("input_reference",T))}catch(_){console.warn(`[VideoHandler] Error fetching reference image: ${T}`,_),a.append("input_reference",T)}}const{debugFetch:u}=await Promise.resolve().then(()=>N),{startLLMApiLog:p,completeLLMApiLog:w,failLLMApiLog:m}=await Promise.resolve().then(()=>O),d=Date.now(),y=n.model||"veo3",S=p({endpoint:"/videos",model:y,taskType:"video",prompt:n.prompt,hasReferenceImages:i.length>0,referenceImageCount:i.length,referenceImages:l,taskId:e.id}),h=await u(`${r.baseUrl}/videos`,{method:"POST",headers:r.apiKey?{Authorization:`Bearer ${r.apiKey}`}:void 0,body:a,signal:o},{label:`🎬 提交视频生成 (${y})`,logResponseBody:!0});if(!h.ok){const g=await h.text();throw m(S,{httpStatus:h.status,duration:Date.now()-d,errorMessage:g,responseBody:g}),new Error(`Video submission failed: ${h.status} - ${g}`)}const f=await h.json();if(f.id){const{updateLLMApiLogMetadata:g}=await Promise.resolve().then(()=>O);g(S,{remoteId:f.id,responseBody:JSON.stringify(f),httpStatus:h.status})}return{response:f,logId:S}}async pollUntilComplete(e,t,o,r,n){const{videoConfig:a}=o,i=Date.now();try{const c=await et(a.baseUrl,e,{onProgress:(u,p)=>{o.onProgress(t,u,p)},signal:r,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(n){const{completeLLMApiLog:u}=await Promise.resolve().then(()=>O);u(n,{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(n){const{failLLMApiLog:l}=await Promise.resolve().then(()=>O);l(n,{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 no{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,I.SUBMITTING);const{response:r,logId:n}=await this.createCharacter(e,t,o.signal);return t.onRemoteId(e.id,r.id),t.onProgress(e.id,10,I.POLLING),await this.pollUntilComplete(r.id,e.id,t,o.signal,n)}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:r}=await Promise.resolve().then(()=>O),n=r({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,I.POLLING),await this.pollUntilComplete(e.remoteId,e.id,t,o.signal,n)}finally{this.cleanup(e.id)}}cancel(e){this.cleanup(e)}async createCharacter(e,t,o){const{videoConfig:r}=t,{params:n}=e,a=this.getCharacterModel(n.model),i=new FormData;i.append("character_from_task",n.sourceVideoTaskId||""),i.append("model",a),n.characterTimestamps&&i.append("character_timestamps",n.characterTimestamps);const{debugFetch:c}=await Promise.resolve().then(()=>N),{startLLMApiLog:l,completeLLMApiLog:u,failLLMApiLog:p}=await Promise.resolve().then(()=>O),w=Date.now(),m=l({endpoint:"/videos",model:a,taskType:"character",prompt:`角色提取: ${n.sourceVideoTaskId}`,taskId:e.id}),d=await c(`${r.baseUrl}/videos`,{method:"POST",headers:{...r.apiKey?{Authorization:`Bearer ${r.apiKey}`}:{}},body:i,signal:o},{label:`👤 创建角色视频 (${a})`,logResponseBody:!0});if(!d.ok){const S=await d.text();throw p(m,{httpStatus:d.status,duration:Date.now()-w,errorMessage:S,responseBody:S}),new Error(`Character creation failed: ${d.status} - ${S}`)}const y=await d.json();if(y.id){const{updateLLMApiLogMetadata:S}=await Promise.resolve().then(()=>O);S(m,{remoteId:y.id,responseBody:JSON.stringify(y),httpStatus:d.status})}return{response:y,logId:m}}async pollUntilComplete(e,t,o,r,n){const{videoConfig:a}=o,i=3e3,c=60,l=Date.now();let u=0;return new Promise((p,w)=>{const m=async()=>{if(r.aborted){if(n){const{failLLMApiLog:d}=await Promise.resolve().then(()=>O);d(n,{duration:Date.now()-l,errorMessage:"Task cancelled"})}w(new Error("Task cancelled"));return}if(u++,u>c){if(n){const{failLLMApiLog:d}=await Promise.resolve().then(()=>O);d(n,{duration:Date.now()-l,errorMessage:"Character creation timeout"})}w(new Error("Character creation timeout"));return}try{const d=await this.queryCharacter(e,a,r),y=Math.min(10+u/c*90,99);if(o.onProgress(t,y,I.POLLING),d.username){if(o.onProgress(t,100),n){const{completeLLMApiLog:h}=await Promise.resolve().then(()=>O);h(n,{httpStatus:200,duration:Date.now()-l,resultType:"character",resultCount:1,resultUrl:d.profile_picture_url,responseBody:JSON.stringify(d)})}p({url:d.profile_picture_url,format:"png",size:0,characterUsername:d.username,characterProfileUrl:d.profile_picture_url,characterPermalink:d.permalink});return}const S=setTimeout(m,i);this.pollingIntervals.set(t,S)}catch(d){if(d instanceof Error&&d.message.includes("404")){const y=setTimeout(m,i);this.pollingIntervals.set(t,y)}else if(u<c){const y=setTimeout(m,i);this.pollingIntervals.set(t,y)}else{if(n){const{failLLMApiLog:y}=await Promise.resolve().then(()=>O);y(n,{duration:Date.now()-l,errorMessage:d instanceof Error?d.message:String(d)})}w(d)}}};m()})}async queryCharacter(e,t,o){const{debugFetch:r}=await Promise.resolve().then(()=>N),n=await r(`${t.baseUrl}/videos/${e}`,{method:"GET",headers:t.apiKey?{Authorization:`Bearer ${t.apiKey}`}:void 0,signal:o},{label:"👤 查询角色状态",logResponseBody:!0});if(!n.ok)throw new Error(`Character query failed: ${n.status}`);return n.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 ao{constructor(){this.abortControllers=new Map}async execute(e,t){const o=e.params,r=new AbortController;this.abortControllers.set(e.id,r);try{const n=this.convertToGeminiMessages(o),a=await this.streamChat(n,t.geminiConfig,o.temporaryModel,o.systemPrompt,r.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,r){const n=new AbortController;this.abortControllers.set(e,n);try{const a=this.convertToGeminiMessages(t);return await this.streamChat(a,o,t.temporaryModel,t.systemPrompt,n.signal,r)}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 r of e.messages){const n=[];if(r.content&&n.push({type:"text",text:r.content}),r.attachments)for(const a of r.attachments)a.type==="image"&&n.push({type:"image_url",image_url:{url:`data:${a.mimeType};base64,${a.data}`}});t.push({role:r.role,content:n})}if(e.newContent||(o=e.attachments)!=null&&o.length){const r=[];if(e.newContent&&r.push({type:"text",text:e.newContent}),e.attachments)for(const n of e.attachments)n.type==="image"&&r.push({type:"image_url",image_url:{url:`data:${n.mimeType};base64,${n.data}`}});t.push({role:"user",content:r})}return t}async streamChat(e,t,o,r,n,a){var ee,We,ke,_s,bs,As,Rs,Ds,Ls;const i=o||t.modelName||"gemini-2.5-flash",c={model:i,messages:e,stream:!0},{debugFetch:l}=await Promise.resolve().then(()=>N),{startLLMApiLog:u,completeLLMApiLog:p,failLLMApiLog:w}=await Promise.resolve().then(()=>O),m=Date.now(),d=e.filter(v=>v.role==="user").pop(),y=((We=(ee=d==null?void 0:d.content)==null?void 0:ee[0])==null?void 0:We.text)||"",{getImageInfo:S}=await Promise.resolve().then(()=>ct),h=[];for(const v of e)if(v.role==="user"&&v.content){for(const de of v.content)if(de.type==="image_url"&&((ke=de.image_url)!=null&&ke.url))try{const K=await S(de.image_url.url,n);h.push({url:K.url,size:K.size,width:K.width,height:K.height})}catch(K){console.warn("[ChatHandler] Failed to get image info for log",K),h.push({url:de.image_url.url,size:0,width:0,height:0})}}const f=u({endpoint:"/chat/completions",model:i,taskType:"chat",prompt:y,requestBody:JSON.stringify(c,null,2),hasReferenceImages:h.length>0,referenceImageCount:h.length,referenceImages:h}),g=await l(`${t.baseUrl}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`},body:JSON.stringify(c),signal:n},{label:`💬 对话请求 (${i})`,logRequestBody:!0,isStreaming:!0});if(!g.ok){const v=await g.text();throw w(f,{httpStatus:g.status,duration:Date.now()-m,errorMessage:v}),new Error(`Chat request failed: ${g.status} - ${v}`)}const T=m,_=f;if(!g.body)throw new Error("No response body");const E=g.body.getReader(),D=new TextDecoder;let b="",W="";try{for(;;){const{done:v,value:de}=await E.read();if(v)break;W+=D.decode(de,{stream:!0});const K=W.split(`
2
- `);W=K.pop()||"";for(const Is of K)if(Is.startsWith("data: ")){const Os=Is.slice(6).trim();if(Os==="[DONE]")continue;try{const Ws=(As=(bs=(_s=JSON.parse(Os).choices)==null?void 0:_s[0])==null?void 0:bs.delta)==null?void 0:As.content;Ws&&(b+=Ws,a==null||a(b))}catch{}}}if(W.startsWith("data: ")){const v=W.slice(6).trim();if(v&&v!=="[DONE]")try{const K=(Ls=(Ds=(Rs=JSON.parse(v).choices)==null?void 0:Rs[0])==null?void 0:Ds.delta)==null?void 0:Ls.content;K&&(b+=K,a==null||a(b))}catch{}}}finally{E.releaseLock()}if(g.__debugLogId&&b){const{updateLogResponseBody:v}=await Promise.resolve().then(()=>N);v(g.__debugLogId,b)}const{completeLLMApiLog:Z}=await Promise.resolve().then(()=>O);return Z(_,{httpStatus:g.status,duration:Date.now()-T,resultType:"text",resultCount:1,resultText:b}),b}}class io{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.hadSavedConfig=!1,this.sw=e,this.config={...ks,...t},this.imageHandler=new oo,this.videoHandler=new ro,this.characterHandler=new no,this.chatHandler=new ao,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 C.loadConfig();t&&o&&(this.geminiConfig=t,this.videoConfig=o,this.initialized=!0,this.hadSavedConfig=!0);const r=await C.getAllTasks();let n=0;for(const a of r){if(a.status===A.COMPLETED&&((e=a.result)!=null&&e.url)&&a.result.url.startsWith("data:image/")){const{url:i,migrated:c}=await Kt(a.result.url);c&&(a.result.url=i,await C.saveTask(a),n++)}if(this.tasks.set(a.id,a),a.type===L.CHAT&&a.status===A.PROCESSING){await this.markTaskFailed(a.id,{code:"INTERRUPTED",message:"Chat 请求被中断(页面刷新),请重试"});continue}this.shouldResumeTask(a)&&this.resumeTaskExecution(a)}n>0}catch(t){console.error("[SWTaskQueue] Failed to restore from storage:",t)}}shouldResumeTask(e){return e.type===L.CHAT&&e.status===A.PROCESSING?!1:!!(e.status===A.PROCESSING||e.status===A.PENDING||(e.type===L.VIDEO||e.type===L.CHARACTER)&&e.status===A.FAILED&&e.remoteId&&this.isNetworkError(e))}isNetworkError(e){var i,c,l,u;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)||"",r=((u=e.error)==null?void 0:u.code)||"",n=`${t} ${o}`.toLowerCase();return n.includes("generation_failed")||n.includes("invalid_argument")||n.includes("prohibited")||n.includes("content policy")||n.includes("视频生成失败")||r.includes("generation_failed")||r.includes("INVALID")?!1:n.includes("failed to fetch")||n.includes("network")||n.includes("fetch")||n.includes("timeout")||n.includes("aborted")||n.includes("connection")||n.includes("status query failed")||n.includes("429")||n.includes("too many requests")}async resumeTaskExecution(e){if(this.initialized){if(e.remoteId&&(e.type===L.VIDEO||e.type===L.CHARACTER))e.status===A.FAILED&&(e.status=A.PROCESSING,e.error=void 0,e.executionPhase=I.POLLING,e.updatedAt=Date.now(),this.tasks.set(e.id,e),await C.saveTask(e)),this.runningTasks.add(e.id),this.broadcastToClients({type:"TASK_STATUS",taskId:e.id,status:A.PROCESSING,progress:e.progress,phase:I.POLLING,updatedAt:e.updatedAt}),this.executeResume(e,e.remoteId);else if(e.status===A.PENDING)this.processQueue();else if((e.type===L.VIDEO||e.type===L.CHARACTER)&&e.status===A.PROCESSING&&!e.remoteId){const{findSuccessLogByTaskId:t,findLatestLogByTaskId:o}=await Promise.resolve().then(()=>O),r=await t(e.id);if(r&&r.resultUrl){let i,c,l;if(r.responseBody)try{const u=JSON.parse(r.responseBody);i=u.width,c=u.height,l=parseInt(u.seconds||"0")||0}catch{}await this.handleTaskSuccess(e.id,{url:r.resultUrl,format:e.type===L.VIDEO?"mp4":"png",size:0,width:i,height:c,duration:l});return}const n=await o(e.id);let a=n==null?void 0:n.remoteId;if(!a&&(n!=null&&n.responseBody))try{const i=JSON.parse(n.responseBody);i.id&&(a=i.id)}catch{}if(a){e.remoteId=a,e.executionPhase=I.POLLING,e.updatedAt=Date.now(),this.tasks.set(e.id,e),await C.saveTask(e),this.resumeTaskExecution(e);return}await this.handleTaskError(e.id,new Error("任务中断且无法恢复(未找到已完成的结果)"))}else if((e.type===L.IMAGE||e.type===L.INSPIRATION_BOARD)&&e.status===A.PROCESSING){const{findSuccessLogByTaskId:t}=await Promise.resolve().then(()=>O),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){if(await this.storageRestorePromise,!this.hadSavedConfig){const o=[];for(const r of this.tasks.values())r.status===A.PENDING&&o.push(r.id);if(o.length>0){console.log(`[SWTaskQueue] First-time init: clearing ${o.length} orphan PENDING tasks created without API key`);for(const r of o)this.tasks.delete(r),await C.deleteTask(r)}}this.geminiConfig=e,this.videoConfig=t,this.initialized=!0,this.hadSavedConfig=!0,await C.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 C.saveConfig(this.geminiConfig,this.videoConfig)}async submitTask(e,t,o,r){if(!this.initialized){console.warn(`[SWTaskQueue] Cannot submit task ${e}: queue not initialized (no API key)`),this.broadcastToClients({type:"TASK_REJECTED",taskId:e,reason:"NO_API_KEY"});return}if(this.tasks.has(e)){console.warn(`[SWTaskQueue] Task ${e} already exists`);return}const n=Date.now(),a={id:e,type:t,status:A.PENDING,params:o,createdAt:n,updatedAt:n};this.tasks.set(e,a),await C.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=A.CANCELLED,t.updatedAt=Date.now(),this.tasks.set(e,t),await C.saveTask(t),this.broadcastToClients({type:"TASK_CANCELLED",taskId:e}))}async retryTask(e){const t=this.tasks.get(e);if(!(!t||t.status!==A.FAILED&&t.status!==A.CANCELLED)){if(!t.remoteId&&(t.type===L.VIDEO||t.type===L.CHARACTER))try{const{findLatestLogByTaskId:o}=await Promise.resolve().then(()=>O),r=await o(t.id);if(r!=null&&r.remoteId)t.remoteId=r.remoteId;else if(r!=null&&r.responseBody){const n=JSON.parse(r.responseBody);n.id&&(t.remoteId=n.id)}}catch(o){console.warn(`[SWTaskQueue] Failed to recover remoteId for retry: ${t.id}`,o)}t.status=A.PENDING,t.error=void 0,t.updatedAt=Date.now(),this.tasks.set(e,t),await C.saveTask(t),this.broadcastToClients({type:"TASK_STATUS",taskId:t.id,status:t.status,updatedAt:t.updatedAt}),this.processQueue()}}async resumeTask(e,t,o,r){let n=this.tasks.get(e);if(!n){const a=Date.now();n={id:e,type:o,status:A.PROCESSING,params:{prompt:""},createdAt:a,updatedAt:a,remoteId:t,executionPhase:I.POLLING},this.tasks.set(e,n),await C.saveTask(n)}(o===L.VIDEO||o===L.CHARACTER)&&(this.runningTasks.add(e),this.executeResume(n,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 C.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 C.saveTask(o)}async restoreTasks(e){for(const t of e)t.status!==A.COMPLETED&&t.status!==A.CANCELLED&&(this.tasks.set(t.id,t),await C.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 r=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:r,timestamp:Date.now(),delivered:!1}),this.broadcastToClients({type:"CHAT_DONE",chatId:e,fullContent:r});const n=this.chatResultCache.get(e);n&&(n.delivered=!0),this.cleanupChatCache()}catch(r){this.broadcastToClients({type:"CHAT_ERROR",chatId:e,error:r instanceof Error?r.message:String(r)})}}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 C.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===A.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}if(this.runningTasks.add(e.id),e.status=A.PROCESSING,e.startedAt=Date.now(),e.updatedAt=Date.now(),e.executionPhase=I.SUBMITTING,this.tasks.set(e.id,e),await C.saveTask(e),this.broadcastToClients({type:"TASK_STATUS",taskId:e.id,status:e.status,phase:e.executionPhase,updatedAt:e.updatedAt}),e.remoteId&&(e.type===L.VIDEO||e.type===L.CHARACTER)){e.executionPhase=I.POLLING,await C.saveTask(e),this.broadcastToClients({type:"TASK_STATUS",taskId:e.id,status:e.status,phase:e.executionPhase,updatedAt:e.updatedAt}),this.executeResume(e,e.remoteId);return}const t={geminiConfig:this.geminiConfig,videoConfig:this.videoConfig,onProgress:async(o,r,n)=>{const a=this.tasks.get(o);if(a&&a.status!==A.COMPLETED&&a.status!==A.FAILED&&a.status!==A.CANCELLED){const i=a.status;a.progress=r,n&&(a.executionPhase=n),a.updatedAt=Date.now(),this.tasks.set(o,a),await C.saveTask(a);const c=this.tasks.get(o);c&&c.status===i&&this.broadcastToClients({type:"TASK_STATUS",taskId:o,status:i,progress:r,phase:n,updatedAt:a.updatedAt})}},onRemoteId:async(o,r)=>{const n=this.tasks.get(o);n&&(n.remoteId=r,n.executionPhase=I.POLLING,n.updatedAt=Date.now(),this.tasks.set(o,n),await C.saveTask(n),this.broadcastToClients({type:"TASK_SUBMITTED",taskId:o,remoteId:r}))}};try{const o=this.getHandler(e.type);if(!o)throw new Error(`No handler for task type: ${e.type}`);const r=this.config.timeouts[e.type]||600*1e3,n=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(r/6e4)} minutes`))},r)})]);await this.handleTaskSuccess(e.id,n)}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(r,n,a)=>{const i=this.tasks.get(r);if(i&&i.status!==A.COMPLETED&&i.status!==A.FAILED&&i.status!==A.CANCELLED){const c=i.status;i.progress=n,a&&(i.executionPhase=a),i.updatedAt=Date.now(),this.tasks.set(r,i),await C.saveTask(i);const l=this.tasks.get(r);l&&l.status===c&&this.broadcastToClients({type:"TASK_STATUS",taskId:r,status:c,progress:n,phase:a,updatedAt:i.updatedAt})}},onRemoteId:()=>{}};try{const r=this.getHandler(e.type);if(!r||typeof r.resume!="function")throw new Error(`Handler does not support resume: ${e.type}`);e.remoteId=t;const n=await r.resume(e,o);await this.handleTaskSuccess(e.id,n)}catch(r){console.error(`[SWTaskQueue] executeResume: 任务 ${e.id} 恢复失败`,r),await this.handleTaskError(e.id,r)}}async handleTaskSuccess(e,t){var r;const o=this.tasks.get(e);o&&(o.status=A.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 C.saveTask(o),this.broadcastToClients({type:"TASK_COMPLETED",taskId:e,result:t,completedAt:o.completedAt}),(r=this.onTaskStatusChange)==null||r.call(this,e,"completed",t),this.processQueue())}async handleTaskError(e,t){var n;const o=this.tasks.get(e);if(!o)return;this.runningTasks.delete(e);const r={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=A.FAILED,o.error=r,o.updatedAt=Date.now(),this.tasks.set(e,o),await C.saveTask(o),this.broadcastToClients({type:"TASK_FAILED",taskId:e,error:r}),(n=this.onTaskStatusChange)==null||n.call(this,e,"failed",void 0,r.message),this.processQueue()}async markTaskFailed(e,t){const o=this.tasks.get(e);o&&(o.status=A.FAILED,o.error=t,o.updatedAt=Date.now(),this.tasks.set(e,o),await C.saveTask(o),this.broadcastToClients({type:"TASK_FAILED",taskId:e,error:t}))}getHandler(e){switch(e){case L.IMAGE:case L.INSPIRATION_BOARD:return this.imageHandler;case L.VIDEO:return this.videoHandler;case L.CHARACTER:return this.characterHandler;case L.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)xt(o,e)}catch(t){console.error("[SWTaskQueue] Failed to broadcast:",t)}}}let Ue=null;function co(s,e){return Ue||(Ue=new io(s,e)),Ue}function lt(){return Ue}function lo(s,e){var o,r;const t=lt();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:(r=s.filters)==null?void 0:r.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 n=t==null?void 0:t.getCachedChatResult(s.chatId);n?xe(e,{type:"CHAT_CACHED_RESULT",chatId:s.chatId,fullContent:n.fullContent,found:!0}).then(a=>{a||console.warn("[SWTaskQueue] Failed to send CHAT_CACHED_RESULT to client:",e)}):xe(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(()=>jr).then(({executeMCPTool:n})=>{const a=lt(),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?n(s.requestId,s.toolName,s.args,i,c,e,l):l==null||l.clients.get(e).then(u=>{u&&u.postMessage({type:"MCP_TOOL_RESULT",requestId:s.requestId,success:!1,error:"Task queue not initialized",resultType:"error"})})});break}}}const uo={name:"generate_image",description:"Generate images using AI",async execute(s,e){const{geminiConfig:t,onProgress:o,signal:r}=e,{prompt:n,size:a,referenceImages:i,quality:c,model:l,count:u=1}=s;if(!n)return{success:!1,error:"缺少必填参数 prompt",type:"error"};try{o==null||o(0,I.SUBMITTING);const p=at({prompt:n,model:l,size:a,referenceImages:i,quality:c,n:Math.min(Math.max(1,u),10)},t.modelName);o==null||o(10,I.SUBMITTING);const{debugFetch:w}=await Promise.resolve().then(()=>N),m=await w(`${t.baseUrl}/images/generations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`},body:JSON.stringify(p),signal:r},{label:`🎨 生成图片 (${t.modelName})`,logRequestBody:!0,logResponseBody:!0});if(!m.ok){const h=await m.text();throw console.error("[SW:generateImage] ✗ API error:",m.status,h.substring(0,200)),new Error(`Image generation failed: ${m.status} - ${h}`)}o==null||o(80,I.DOWNLOADING);const d=await m.json(),{url:y,urls:S}=await it(d);return o==null||o(100),{success:!0,type:"image",data:{url:y,urls:S,format:"png",prompt:n,size:a||"1x1"}}}catch(p){return console.error("[SW:generateImage] Error:",p),{success:!1,error:p.message||"图片生成失败",type:"error"}}}},ho={name:"generate_video",description:"Generate videos using AI",async execute(s,e){const{videoConfig:t,onProgress:o,onRemoteId:r,signal:n}=e,{prompt:a,model:i="veo3",seconds:c="8",size:l="1280x720",inputReference:u,inputReferences:p,referenceImages:w}=s;if(!a)return{success:!1,error:"缺少必填参数 prompt",type:"error"};try{o==null||o(0,I.SUBMITTING);const m={model:i,prompt:a,seconds:c,size:l},d=[];p&&p.length>0?p.forEach(T=>{const _=typeof T=="string"?T:T==null?void 0:T.url;_&&d.push(_)}):w&&w.length>0?d.push(...w):u&&d.push(u),d.length>0&&(d.length===1?m.input_reference=d[0]:m.input_references=d);const{debugFetch:y}=await Promise.resolve().then(()=>N),S=await y(`${t.baseUrl}/videos/generations`,{method:"POST",headers:{"Content-Type":"application/json",...t.apiKey?{Authorization:`Bearer ${t.apiKey}`}:{}},body:JSON.stringify(m),signal:n},{label:`🎬 提交视频生成 (${t.model||"default"})`,logRequestBody:!0,logResponseBody:!0});if(!S.ok){const T=await S.text();throw console.error("[SW:generateVideo] ✗ Submit failed:",S.status,T.substring(0,200)),new Error(`Video submission failed: ${S.status} - ${T}`)}const h=await S.json(),f=h.id||h.video_id;if(!f)throw console.error("[SW:generateVideo] ✗ No video ID in response:",h),new Error("No video ID in response");r==null||r(f),o==null||o(10,I.POLLING);const g=await et(t.baseUrl,f,{onProgress:o,signal:n,apiKey:t.apiKey});return{success:!0,type:"video",data:{url:g.video_url||g.url,format:"mp4",prompt:a,duration:parseInt(g.seconds||"")||parseInt(c)}}}catch(m){return console.error("[SW:generateVideo] ✗ Error:",m.message),{success:!1,error:m.message||"视频生成失败",type:"error"}}}},jt=new Map([["generate_image",uo],["generate_video",ho]]);function Vt(s){return jt.get(s)}async function ut(s,e,t){const o=jt.get(s);return o?o.execute(e,t):{success:!1,error:`Unknown tool: ${s}`,type:"error"}}function dt(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 fo{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 C.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 C.saveWorkflow(e),await C.deletePendingToolRequestsByWorkflow(e.id)}updateConfig(e){this.config={...this.config,...e}}async handleMainThreadToolResponse(e){const t=this.pendingToolRequests.get(e.requestId);if(t)this.pendingToolRequests.delete(e.requestId),t.resolve(e);else{const o=await C.getPendingToolRequest(e.requestId);if(!o)return;let r=this.workflows.get(o.workflowId);if(r||(r=await C.getWorkflow(o.workflowId),r&&this.workflows.set(r.id,r)),!r){await C.deletePendingToolRequest(e.requestId);return}const n=r.steps.find(a=>a.id===o.stepId);if(!n){await C.deletePendingToolRequest(e.requestId);return}if(e.success){n.status="completed",n.result={success:!0,type:"text",data:e.result};const a=e.addSteps;if(a&&a.length>0){const i=[];for(const c of a)r.steps.find(l=>l.id===c.id)||(r.steps.push({id:c.id,mcp:c.mcp,args:c.args,description:c.description,status:c.status||"pending"}),i.push(c));i.length>0&&this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:r.id,steps:i})}await C.saveWorkflow(r),this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:r.id,stepId:n.id,status:"completed",result:n.result})}else{n.status="failed",n.error=e.error||"Unknown error",n.result={success:!1,type:"error",error:n.error},await C.saveWorkflow(r),this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:r.id,stepId:n.id,status:"failed",error:n.error}),this.config.broadcast({type:"WORKFLOW_FAILED",workflowId:r.id,error:n.error}),await C.deletePendingToolRequest(e.requestId);return}await C.deletePendingToolRequest(e.requestId),await this.executeWorkflow(r)}}async updateWorkflowStepForTask(e,t,o,r){for(const n of this.workflows.values()){const a=n.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=r,a.result={...a.result,success:!1,error:r}),a.updatedAt=Date.now(),n.updatedAt=Date.now(),await C.saveWorkflow(n),this.broadcastStepStatus(n.id,a),n.status==="running"&&this.executeWorkflow(n.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=[];for(const[,t]of this.pendingToolRequests){const{requestInfo:o}=t;e.includes(o.toolName)||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){const t=this.workflows.get(e.id);if(t){if(t.status==="running"||t.status==="pending"){this.broadcastWorkflowStatus(t),t.steps.forEach(o=>this.broadcastStepStatus(t.id,o));return}console.warn(`[SW-WorkflowExecutor] Workflow ${e.id} already exists with terminal status ${t.status}, skipping`),this.broadcastWorkflowStatus(t);return}e.status="pending",e.updatedAt=Date.now(),this.workflows.set(e.id,e),await C.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 C.saveWorkflow(t),await C.deletePendingToolRequestsByWorkflow(e),this.broadcastWorkflowStatus(t)}getWorkflow(e){return this.workflows.get(e)}getAllWorkflows(){return Array.from(this.workflows.values())}async executeWorkflow(e){const t=this.workflows.get(e);if(!t){console.error(`[WorkflowExecutor] ✗ Workflow ${e} not found`);return}if(this.runningWorkflows.has(e))return;this.runningWorkflows.add(e);const o=new AbortController;this.abortControllers.set(e,o),t.status="running",t.updatedAt=Date.now(),await C.saveWorkflow(t),this.broadcastWorkflowStatus(t);try{let r=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 u=t.steps.find(p=>p.id===l);return u&&(u.status==="completed"||u.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(r++,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 C.saveWorkflow(t),this.config.broadcast({type:"WORKFLOW_COMPLETED",workflowId:e,workflow:t})):await C.saveWorkflow(t)}catch(r){console.error(`[WorkflowExecutor] ✗ Workflow ${e} failed:`,r),t.status="failed",t.error=r.message,t.updatedAt=Date.now(),await C.saveWorkflow(t),this.config.broadcast({type:"WORKFLOW_FAILED",workflowId:e,error:r.message})}finally{this.runningWorkflows.delete(e),this.abortControllers.delete(e)}}replaceImagePlaceholders(e,t){if(!t||t.length===0)return e;const o=r=>{if(typeof r=="string"){let n=r.replace(/\[图片(\d+)\]/g,(a,i)=>{const c=parseInt(i,10)-1;return c>=0&&c<t.length?t[c]:a});return n=n.replace(/\[Image\s*(\d+)\]/gi,(a,i)=>{const c=parseInt(i,10)-1;return c>=0&&c<t.length?t[c]:a}),n}if(Array.isArray(r))return r.map(n=>o(n));if(r&&typeof r=="object"){const n={};for(const[a,i]of Object.entries(r))n[a]=o(i);return n}return r};return o(e)}async executeStep(e,t,o){var l,u,p,w;const r=Date.now(),n=((l=e.context)==null?void 0:l.referenceImages)||[];t.mcp==="generate_image"||t.mcp;const a=this.replaceImagePlaceholders(t.args,n),i=JSON.stringify(t.args),c=JSON.stringify(a);i!==c?t.args=a:n.length>0&&(t.mcp==="generate_image"||t.mcp),t.status="running",await C.saveWorkflow(e),this.broadcastStepStatus(e.id,t);try{if(dt(t.mcp)||!Vt(t.mcp)){const m=await this.requestMainThreadTool(e.id,t.id,t.mcp,t.args);if(!m.success)throw new Error(m.error||"Main thread tool execution failed");if(m.addSteps&&m.addSteps.length>0){const S=[];for(const h of m.addSteps)e.steps.find(f=>f.id===h.id)||(e.steps.push({id:h.id,mcp:h.mcp,args:h.args,description:h.description,status:h.status}),S.push(h));S.length>0&&(await C.saveWorkflow(e),this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:e.id,steps:S}))}const d=m.result;if(["generate_image","generate_video","generate_grid_image","generate_inspiration_board"].includes(t.mcp)&&m.taskId){const S={generate_image:"image",generate_grid_image:"image",generate_inspiration_board:"image",generate_video:"video"};t.result={success:!0,type:S[t.mcp]||"image",data:d,taskId:m.taskId,taskIds:m.taskIds},t.status="running",t.duration=Date.now()-r,this.broadcastStepStatus(e.id,t);return}t.result={success:!0,type:(d==null?void 0:d.type)||"text",data:d}}else{const m={geminiConfig:this.config.geminiConfig,videoConfig:this.config.videoConfig,signal:o,onProgress:(y,S)=>{},onRemoteId:y=>{}},d=await ut(t.mcp,t.args,m);if(d.success&&d.type==="canvas"&&((u=d.data)!=null&&u.delegateToMainThread)){const y=await this.requestCanvasOperation(d.data.operation,d.data.args);if(!y.success)throw new Error(y.error||"Canvas operation failed");t.result={success:!0,type:"canvas",data:{completed:!0}}}else if(d.success&&d.type==="image"&&((p=d.data)!=null&&p.url)){const y=d.data,S=await this.requestCanvasOperation("canvas_insert",{items:[{type:"image",url:y.url}]});S.success||console.warn("[WorkflowExecutor] Failed to insert image to canvas:",S.error),t.result={success:!0,type:"image",data:d.data}}else if(d.success&&d.type==="video"&&((w=d.data)!=null&&w.url)){const y=d.data,S=await this.requestCanvasOperation("canvas_insert",{items:[{type:"video",url:y.url}]});S.success||console.warn("[WorkflowExecutor] Failed to insert video to canvas:",S.error),t.result={success:!0,type:"video",data:d.data}}else if(t.result={success:d.success,type:d.type||"text",data:d.data,error:d.error},!d.success)throw new Error(d.error||"Step execution failed");if(d.addSteps&&d.addSteps.length>0){const y=[];for(const S of d.addSteps)e.steps.find(h=>h.id===S.id)||(e.steps.push({id:S.id,mcp:S.mcp,args:S.args,description:S.description,status:S.status}),y.push(S));y.length>0&&this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:e.id,steps:y})}}t.status="completed",t.duration=Date.now()-r}catch(m){t.status="failed",t.error=m.message,t.duration=Date.now()-r,t.result={success:!1,type:"error",error:m.message}}await C.saveWorkflow(e),this.broadcastStepStatus(e.id,t)}async requestMainThreadTool(e,t,o,r){if(this.config.requestMainThreadTool)return this.config.requestMainThreadTool(e,t,o,r);const n=`tool_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return new Promise((a,i)=>{const c=setTimeout(()=>{this.pendingToolRequests.delete(n),i(new Error(`Main thread tool request timed out: ${o}`))},3e5);this.pendingToolRequests.set(n,{resolve:l=>{clearTimeout(c),C.deletePendingToolRequest(n),a(l)},reject:l=>{clearTimeout(c),C.deletePendingToolRequest(n),i(l)},requestInfo:{requestId:n,workflowId:e,stepId:t,toolName:o,args:r},timeout:c}),C.savePendingToolRequest({requestId:n,workflowId:e,stepId:t,toolName:o,args:r,createdAt:Date.now()}),this.config.broadcast({type:"MAIN_THREAD_TOOL_REQUEST",requestId:n,workflowId:e,stepId:t,toolName:o,args:r})})}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 Qt(s=0){return`tc_${Date.now()}_${s}_${Math.random().toString(36).substr(2,9)}`}function ae(s){const e=s.trim();try{return JSON.parse(e)}catch{try{return JSON.parse(wo(e))}catch{return null}}}function Jt(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 go(s){const e=s.trim();if(!e.startsWith("{")||!e.endsWith("}")||!e.includes('"content"')||!e.includes('"next"'))return!1;let t=0,o=0,r=!1,n=!1;for(const a of e){if(n){n=!1;continue}if(a==="\\"){n=!0;continue}if(a==='"'){r=!r;continue}r||(a==="{"?t++:a==="}"?t--:a==="["?o++:a==="]"&&o--)}return t===0&&o===0}function Xt(s){const e=Jt(s);if(!go(e))return null;let t=ae(e);if(!t){const n=e.match(/\{\s*"content"\s*:\s*"[^"]*"\s*,\s*"next"\s*:\s*\[[\s\S]*?\]\s*\}/);n&&(t=ae(n[0]))}if(!t){const n=e.match(/\{[\s\S]*"content"[\s\S]*"next"[\s\S]*\}/);n&&(t=ae(n[0]))}if(!t||typeof t.content!="string")return null;const r=(Array.isArray(t.next)?t.next:[]).filter(n=>typeof n=="object"&&n!==null&&typeof n.mcp=="string"&&typeof n.args=="object").map(n=>({mcp:n.mcp,args:n.args}));return{content:t.content,next:r}}function po(s){const e=Xt(s);if(e&&e.next.length>0)return e.next.map((a,i)=>({id:Qt(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:Qt(),name:a.name,arguments:typeof i=="object"&&i!==null?i:{}}},r=/```tool_call\s*\n?([\s\S]*?)\n?```/gi;let n;for(;(n=r.exec(s))!==null;){const a=ae(n[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(;(n=a.exec(s))!==null;){const i=ae(n[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(;(n=a.exec(s))!==null;){const i=ae(n[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(;(n=a.exec(s))!==null;){const i=ae(n[0]);if(i){const c=o(i);if(c){t.push(c);break}}}}return t}function mo(s){const e=Xt(s);if(e)return e.content;let t=Jt(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,`
1
+ (function(){"use strict";var R=(s=>(s.PENDING="pending",s.PROCESSING="processing",s.COMPLETED="completed",s.FAILED="failed",s.CANCELLED="cancelled",s))(R||{}),L=(s=>(s.IMAGE="image",s.VIDEO="video",s.CHARACTER="character",s.INSPIRATION_BOARD="inspiration_board",s.CHAT="chat",s))(L||{}),I=(s=>(s.SUBMITTING="submitting",s.POLLING="polling",s.DOWNLOADING="downloading",s))(I||{});const Ms={timeouts:{image:600*1e3,video:1200*1e3,character:600*1e3,inspiration_board:600*1e3,chat:600*1e3}},xs=["apikey","api_key","password","token","secret","authorization","bearer","credential","key"];function je(s){if(!s)return s;if(typeof s=="string")return s.toLowerCase().startsWith("bearer ")?"[REDACTED]":s;if(Array.isArray(s))return s.map(e=>je(e));if(typeof s=="object"){const e={};for(const[t,o]of Object.entries(s)){const r=t.toLowerCase();xs.some(n=>r.includes(n))?e[t]="[REDACTED]":e[t]=je(o)}return e}return s}function Dt(s){if(!s)return s;try{const e=JSON.parse(s),t=je(e);return JSON.stringify(t)}catch{let e=s;return e=e.replace(/Bearer\s+[a-zA-Z0-9-_]+/gi,"Bearer [REDACTED]"),e=e.replace(/"(api[_-]?key|apikey|authorization|token|secret|password|credential)"\s*:\s*"[^"]+"/gi,(t,o)=>`"${o}": "[REDACTED]"`),e}}function Ve(s){return s instanceof Error?s.name||"Error":"Unknown error"}const Qe="sw-task-queue",Lt=2,k="tasks",j="config",B="workflows",U="chat-workflows",F="pending-tool-requests",vs=[k,j,B,U,F];function Ns(){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 Bs(s){const e=[];for(const t of vs)s.objectStoreNames.contains(t)||e.push(t);return e}function Us(s){return new Promise((e,t)=>{const o=s+1;console.log(`[SWStorage] Repairing database: upgrading from v${s} to v${o}`);const r=indexedDB.open(Qe,o);r.onerror=()=>{console.error("[SWStorage] Failed to repair DB:",r.error),t(r.error)},r.onsuccess=()=>{e(r.result)},r.onupgradeneeded=n=>{const a=n.target.result;It(a)}})}function It(s){if(!s.objectStoreNames.contains(k)){const e=s.createObjectStore(k,{keyPath:"id"});e.createIndex("status","status",{unique:!1}),e.createIndex("type","type",{unique:!1}),e.createIndex("createdAt","createdAt",{unique:!1})}if(s.objectStoreNames.contains(j)||s.createObjectStore(j,{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(U)){const e=s.createObjectStore(U,{keyPath:"id"});e.createIndex("status","status",{unique:!1}),e.createIndex("createdAt","createdAt",{unique:!1})}s.objectStoreNames.contains(F)||s.createObjectStore(F,{keyPath:"requestId"}).createIndex("workflowId","workflowId",{unique:!1})}async function Fs(){const s=await Ns();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 r=o.result,n=Bs(r);if(n.length>0){console.warn(`[SWStorage] Missing object stores: ${n.join(", ")}. Repairing...`),r.close(),Us(r.version).then(e).catch(t);return}e(r)},o.onupgradeneeded=r=>{const n=r.target.result;It(n)}})}class qs{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((r,n)=>{const a=o.transaction(k,"readwrite"),i=a.objectStore(k);for(const c of e)i.put(c);a.oncomplete=()=>{t.forEach(({resolve:c})=>c()),r()},a.onerror=()=>{const c=a.error;t.forEach(({reject:l})=>l(c)),n(c)}})}catch(o){console.error("[SWStorage] Failed to batch save tasks:",o),t.forEach(({reject:r})=>r(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((r,n)=>{const c=o.transaction(k,"readwrite").objectStore(k).put(e);c.onerror=()=>n(c.error),c.onsuccess=()=>r()}),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,r)=>{const i=t.transaction(k,"readonly").objectStore(k).get(e);i.onerror=()=>r(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(k,"readonly").objectStore(k).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,r)=>{const c=t.transaction(k,"readonly").objectStore(k).index("status").getAll(e);c.onerror=()=>r(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:r,type:n,sortOrder:a="desc"}=e;try{const i=await this.getDB();return new Promise((c,l)=>{const g=i.transaction(k,"readonly").objectStore(k),w=g.index("createdAt"),p=g.count();let d=0;p.onsuccess=()=>{d=p.result};const y=a==="desc"?"prev":"next",S=w.openCursor(null,y),h=[];let f=0,m=0;S.onerror=()=>l(S.error),S.onsuccess=T=>{const _=T.target.result;if(!_){c({tasks:h,total:m,hasMore:m>t+h.length});return}const C=_.value,A=!r||C.status===r,b=!n||C.type===n;A&&b&&(m++,f<t?f++:h.length<o&&h.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,r)=>{const i=t.transaction(k,"readwrite").objectStore(k).delete(e);i.onerror=()=>r(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((r,n)=>{const a=o.transaction(j,"readwrite"),i=a.objectStore(j);e&&i.put({key:"gemini",...e}),t&&i.put({key:"video",...t}),a.oncomplete=()=>r(),a.onerror=()=>n(a.error)})}catch(o){console.error("[SWStorage] Failed to save config:",Ve(o))}}async loadConfig(){try{const e=await this.getDB();return new Promise((t,o)=>{const r=e.transaction(j,"readonly"),n=r.objectStore(j),a=n.get("gemini"),i=n.get("video");r.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})},r.onerror=()=>o(r.error)})}catch(e){return console.error("[SWStorage] Failed to load config:",Ve(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,r)=>{const n=t.transaction(j,"readwrite");n.objectStore(j).put({key:"systemPrompt",value:e,updatedAt:Date.now()}),n.oncomplete=()=>o(),n.onerror=()=>r(n.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(j,"readonly").objectStore(j).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,r)=>{const i=t.transaction(B,"readwrite").objectStore(B).put(e);i.onerror=()=>r(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,r)=>{const i=t.transaction(B,"readonly").objectStore(B).get(e);i.onerror=()=>r(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,r)=>{const c=t.transaction(B,"readonly").objectStore(B).index("status").getAll(e);c.onerror=()=>r(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,r)=>{const i=t.transaction(B,"readwrite").objectStore(B).delete(e);i.onerror=()=>r(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,r)=>{const i=t.transaction(U,"readwrite").objectStore(U).put(e);i.onerror=()=>r(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,r)=>{const i=t.transaction(U,"readonly").objectStore(U).get(e);i.onerror=()=>r(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(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 chat workflows:",e),[]}}async getChatWorkflowsByStatus(e){try{const t=await this.getDB();return new Promise((o,r)=>{const c=t.transaction(U,"readonly").objectStore(U).index("status").getAll(e);c.onerror=()=>r(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,r)=>{const i=t.transaction(U,"readwrite").objectStore(U).delete(e);i.onerror=()=>r(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,r)=>{const i=t.transaction(F,"readwrite").objectStore(F).put(e);i.onerror=()=>r(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(F,"readonly").objectStore(F).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,r)=>{const c=t.transaction(F,"readonly").objectStore(F).index("workflowId").getAll(e);c.onerror=()=>r(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,r)=>{const i=t.transaction(F,"readonly").objectStore(F).get(e);i.onerror=()=>r(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,r)=>{const i=t.transaction(F,"readwrite").objectStore(F).delete(e);i.onerror=()=>r(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 E=new qs;let Pe=!1;const $s=500,oe=[];let Me=0;function Gs(){return Pe}const Hs=["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"],Ae=new Map;function Ot(s){const e=Pe;Pe=s,!s&&e&&(oe.length=0,Ae.clear(),Me=0)}function Je(){return Pe}function Wt(s){return Gs()?!Hs.includes(s):!1}function zs(s,e,t){if(!Wt(s))return"";const o=`pm-recv-${Date.now()}-${++Me}`,r={id:o,timestamp:Date.now(),direction:"receive",messageType:s,data:Xe(e),clientId:t};if(Pt(r),js(s)){const n=Mt(e);n&&Ae.set(n,{entry:r,startTime:Date.now()})}return o}function kt(s,e,t){if(!Wt(s))return"";const o=`pm-send-${Date.now()}-${++Me}`,r={id:o,timestamp:Date.now(),direction:"send",messageType:s,data:Xe(e),clientId:t};if(Vs(s)){const n=Mt(e);if(n){const a=Ae.get(n);a&&(r.duration=Date.now()-a.startTime,a.entry.response=Xe(e),a.entry.duration=r.duration,Ae.delete(n))}}return Pt(r),o}function Pt(s){oe.unshift(s),oe.length>$s&&oe.pop()}function Re(){return[...oe]}function Ks(){oe.length=0,Ae.clear(),Me=0}function js(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 Vs(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 Mt(s){if(!s||typeof s!="object")return null;const e=s;return e.requestId||e.taskId||e.workflowId||e.chatId||null}function Xe(s){if(!s)return s;try{const e=JSON.parse(JSON.stringify(s));return xt(e),e}catch{return"[Non-serializable data]"}}function xt(s){if(!s||typeof s!="object")return;const e=["apiKey","password","token","secret","key"],t=s;for(const o in t)e.some(r=>o.toLowerCase().includes(r))?t[o]="[REDACTED]":typeof t[o]=="object"&&xt(t[o])}function Qs(){const s={total:oe.length,sent:0,received:0,byType:{}};for(const e of oe)e.direction==="send"?s.sent++:s.received++,s.byType[e.messageType]||(s.byType[e.messageType]=0),s.byType[e.messageType]++;return s}let xe=!1,he=null;function Ye(s){xe=s,Ot(s)}function Js(s){he=s}function vt(s,e){if(!s){console.warn("[MessageBus] No client provided");return}let t="";if(Je()){const o=(e==null?void 0:e.type)||"unknown";t=kt(o,e,s.id)}try{s.postMessage(e)}catch(o){console.warn("[MessageBus] Failed to postMessage to client:",s.id,o);return}if(t&&xe&&he){const r=Re().find(n=>n.id===t);r&&he(r)}}function Nt(s){const e=self,t=(s==null?void 0:s.type)||"unknown";e.clients.matchAll().then(o=>{o.forEach(r=>{let n="";if(Je()&&(n=kt(t,s,r.id)),r.postMessage(s),n&&xe&&he){const i=Re().find(c=>c.id===n);i&&he(i)}})})}async function ve(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?(vt(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 Xs(s,e){xe=!1,Ot(!1),he=null}const Ys={"1x1":"1024x1024","16x9":"1792x1024","9x16":"1024x1792","4x3":"1536x1152","3x4":"1152x1536","3x2":"1536x1024","2x3":"1024x1536","4x5":"1024x1280","5x4":"1280x1024","21x9":"1792x768"};function Ze(s){return!s||s==="auto"?void 0:{"1:1":"1x1","2:3":"2x3","3:2":"3x2","3:4":"3x4","4:3":"4x3","4:5":"4x5","5:4":"5x4","9:16":"9x16","16:9":"16x9","21:9":"21x9"}[s]||Ys[s]||s}function Bt(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 Ut(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 Ft extends Error{constructor(e){super(e),this.name="VideoGenerationFailedError"}}async function et(s,e,t={}){var w,p;const{onProgress:o,signal:r,apiKey:n,interval:a=5e3,maxAttempts:i=1080}=t;let c=0,l=0;const u=10,{debugFetch:g}=await Promise.resolve().then(()=>N);for(;c<i;){if(r!=null&&r.aborted)throw new Error("Video generation cancelled");try{const d=await g(`${s}/videos/${e}`,{headers:n?{Authorization:`Bearer ${n}`}:{},signal:r},{label:`🔄 查询视频状态 #${c+1}`,logResponseBody:!0});if(!d.ok){if(l++,console.warn(`[VideoPolling] Status query failed (${d.status}), attempt ${l}/${u}, will retry with longer interval`),l>=u)throw new Error(`Failed to get video status after ${u} consecutive errors: ${d.status}`);const f=Math.min(a*Math.pow(1.5,l),6e4);await new Promise(m=>setTimeout(m,f)),c++;continue}l=0;const y=await d.json(),S=(w=y.status)==null?void 0:w.toLowerCase(),h=y.progress??Math.min(10+c*2,90);if(o==null||o(h,"polling"),S==="completed"||S==="succeeded")return o==null||o(100),y;if(S==="failed"||S==="error"){const f=typeof y.error=="string"?y.error:((p=y.error)==null?void 0:p.message)||y.message||"Video generation failed";throw new Ft(f)}await new Promise(f=>setTimeout(f,a)),c++}catch(d){if(d instanceof Ft){if((d.message.includes("429")||d.message.toLowerCase().includes("too many requests"))&&l<u){l++,console.warn(`[VideoPolling] Business error looks like rate limit (#${l}): ${d.message}, retrying...`);const h=Math.min(a*Math.pow(1.5,l),6e4);await new Promise(f=>setTimeout(f,h)),c++;continue}throw d}if(r!=null&&r.aborted)throw new Error("Video generation cancelled");if(l++,console.warn(`[VideoPolling] Network error during status query, attempt ${l}/${u}:`,d),l>=u)throw d;const y=Math.min(a*Math.pow(1.5,l),6e4);await new Promise(S=>setTimeout(S,y)),c++}}throw new Error("Video generation timed out")}const tt="drawnix-images",Zs=720*60*1e3,eo="drawnix-unified-cache",st="media";async function to(s){return new Promise(e=>{try{const t=indexedDB.open(eo);t.onerror=()=>{console.warn("[MediaUtils] Failed to open IndexedDB:",t.error),e(null)},t.onsuccess=()=>{try{const o=t.result;if(!o.objectStoreNames.contains(st)){o.close(),e(null);return}const a=o.transaction(st,"readonly").objectStore(st).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 ot(s,e){try{if(s.startsWith("data:"))return rt(s);const t=await caches.open(tt),o=await t.match(s);if(o)return await o.blob();const r=await fetch(s,{signal:e});if(r.ok){const n=await r.blob();try{const a=new Response(n.slice(),{headers:{"Content-Type":n.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 n}return console.warn(`[MediaUtils] Network fetch failed: ${s.substring(0,50)}...`,r.status),null}catch(t){return console.warn(`[MediaUtils] Error in fetchImageWithCache: ${s.substring(0,50)}...`,t),null}}function rt(s){try{const[e,t]=s.split(",");if(!t)return null;const o=e.match(/data:([^;]+)/),r=o?o[1]:"image/png",n=atob(t),a=new Uint8Array(n.length);for(let i=0;i<n.length;i++)a[i]=n.charCodeAt(i);return new Blob([a],{type:r})}catch(e){return console.warn("[MediaUtils] Failed to convert data URL to Blob:",e),null}}async function qt(s){return new Promise((e,t)=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.onerror=t,o.readAsDataURL(s)})}const nt=1024*1024,Ne=.1,Be=2048;async function $t(s,e=nt){if(s.size<=e)return s;try{const t=await createImageBitmap(s);let{width:o,height:r}=t;const n={width:o,height:r};if(o>Be||r>Be){const y=Math.min(Be/o,Be/r);o=Math.round(o*y),r=Math.round(r*y)}const a=new OffscreenCanvas(o,r),i=a.getContext("2d");if(!i)return console.warn("[MediaUtils] Failed to get 2d context from OffscreenCanvas"),s;i.drawImage(t,0,0,o,r),t.close();let c=Ne,l=.95,u=null,g=0;const w=8;for(let y=0;y<w;y++){const S=(c+l)/2,h=await a.convertToBlob({type:"image/jpeg",quality:S});if(h.size<=e?(u=h,g=S,c=S):l=S,l-c<.02)break}if(u)return u;let p=await a.convertToBlob({type:"image/jpeg",quality:Ne}),d=.8;for(;d>=.3&&p.size>e;){const y=Math.round(o*d),S=Math.round(r*d),h=new OffscreenCanvas(y,S),f=h.getContext("2d");if(!f)break;const m=await createImageBitmap(s);f.drawImage(m,0,0,y,S),m.close();let T=Ne,_=.95,C=null;for(let A=0;A<6;A++){const b=(T+_)/2,W=await h.convertToBlob({type:"image/jpeg",quality:b});if(W.size<=e?(C=W,T=b):_=b,_-T<.02)break}if(C)return C;p=await h.convertToBlob({type:"image/jpeg",quality:Ne}),d-=.1}return p}catch(t){return console.warn("[MediaUtils] Image compression failed, returning original:",t),s}}async function ne(s,e=nt){const t=await $t(s,e);return qt(t)}function Gt(s){if(!s)return null;const e=s.match(/^(\d+)x(\d+)$/);return e?{width:parseInt(e[1],10),height:parseInt(e[2],10)}:null}async function Ht(s,e,t){try{const o=await createImageBitmap(s),{width:r,height:n}=o,a=e/t,i=r/n;if(Math.abs(i-a)<.01)return o.close(),s;let c,l;const u=r/a,g=n*a;u<=n?(c=r,l=Math.round(u)):(c=Math.round(g),l=n);const w=Math.round((r-c)/2),p=Math.round((n-l)/2),d=new OffscreenCanvas(c,l),y=d.getContext("2d");if(!y)return console.warn("[MediaUtils] Failed to get 2d context for cropping"),o.close(),s;y.drawImage(o,w,p,c,l,0,0,c,l),o.close();const S=s.type||"image/png",h=S==="image/jpeg"?.92:void 0,f=await d.convertToBlob({type:S,quality:h});return console.log(`[MediaUtils] Cropped image from ${r}x${n} to ${c}x${l} (target ratio: ${a.toFixed(3)}, crop offset: ${w},${p})`),f}catch(o){return console.warn("[MediaUtils] Image cropping failed, returning original:",o),s}}async function so(s,e){let t=null,o="";if(typeof s=="string"?(o=s,t=await ot(s,e)):t=s,!t)throw new Error("Failed to fetch image for info");const r=t.size,n=await createImageBitmap(t),a=n.width,i=n.height;return n.close(),o||(o=await ne(t,200*1024)),{width:a,height:i,size:r,url:o}}async function zt(s,e){if(s.startsWith("data:")){if((s.split(",")[1]||"").length*3/4>nt){const r=rt(s);if(r){const n=await ne(r);return{originalUrl:s,value:n,isBase64:!0}}}return{originalUrl:s,value:s,isBase64:!0}}try{const t=await caches.open(tt);if(s.startsWith("/asset-library/")){const o=await t.match(s);if(o){const r=await o.blob(),n=await ne(r);return{originalUrl:s,value:n,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}`,r=await t.match(o);if(r){const n=await r.blob(),a=await ne(n);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 n=await to(s),a=o.headers.get("sw-cache-date"),i=a?parseInt(a,10):0,c=n??i,l=Date.now(),u=c?l-c:1/0,g=u/(3600*1e3);if(c>0&&u<Zs)return{originalUrl:s,value:s,isBase64:!1};const w=await o.blob(),p=await ne(w);return{originalUrl:s,value:p,isBase64:!0}}const r=await fetch(s,{signal:e});if(r.ok){const n=await r.blob();try{const i=new Response(n.slice(),{headers:{"Content-Type":n.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 ne(n);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 Kt(s,e){return!s||s.length===0?[]:(await Promise.all(s.map(o=>zt(o,e)))).map(o=>o.value)}function at(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=Ze(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 oo(s){return s.startsWith("data:image/")&&s.includes(";base64,")}function ro(s){const e=s.match(/^data:(image\/[^;]+);base64,(.+)$/);return e?{mimeType:e[1],base64:e[2]}:null}async function jt(s,e="image/png"){try{const t=atob(s),o=new Uint8Array(t.length);for(let u=0;u<t.length;u++)o[u]=t.charCodeAt(u);const r=new Blob([o],{type:e}),n=`img-${Date.now()}-${Math.random().toString(36).substring(2,10)}`,a=e.split("/")[1]||"png",i=`/__aitu_cache__/image/${n}.${a}`,c=await caches.open(tt),l=new Response(r,{status:200,headers:{"Content-Type":e,"Content-Length":r.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 it(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 jt(c.b64_json,"image/png"):null}const o=s.data[0],r=await t(o);if(!r)throw(i=o.revised_prompt)!=null&&i.includes("PROHIBITED_CONTENT")?new Error("内容被拒绝:包含违禁内容"):new Error("No image URL in response");const n=s.data.map((c,l)=>t(c)),a=(await Promise.all(n)).filter(Boolean);return{url:r,urls:a.length>1?a:void 0}}async function Vt(s){if(!oo(s))return{url:s,migrated:!1};const e=ro(s);if(!e)return{url:s,migrated:!1};try{return{url:await jt(e.base64,e.mimeType),migrated:!0}}catch(t){return console.error("[Migration] Failed to migrate Base64 URL:",t),{url:s,migrated:!1}}}const ct=Object.freeze(Object.defineProperty({__proto__:null,blobToBase64:qt,blobToCompressedBase64:ne,buildImageGenerationRequestBody:at,compressImageBlob:$t,convertAspectRatioToSize:Ze,cropImageToAspectRatio:Ht,dataUrlToBlob:rt,extractUrlsFromUploadedImages:Bt,fetchImageWithCache:ot,getImageInfo:so,mergeReferenceImages:Ut,migrateBase64UrlIfNeeded:Vt,parseImageGenerationResponse:it,parseSize:Gt,pollVideoUntilComplete:et,processReferenceImage:zt,processReferenceImages:Kt},Symbol.toStringTag,{value:"Module"}));class no{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,I.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:r}=t,{params:n}=e,a=n.referenceImages||Bt(n.uploadedImages);let i;const{getImageInfo:c}=await Promise.resolve().then(()=>ct),{startLLMApiLog:l,completeLLMApiLog:u,failLLMApiLog:g}=await Promise.resolve().then(()=>O),{debugFetch:w}=await Promise.resolve().then(()=>N);let p;a&&a.length>0&&(i=await Kt(a,o),p=await Promise.all(a.map(async C=>{try{const A=await c(C,o);return{url:A.url,size:A.size,width:A.width,height:A.height}}catch(A){return console.warn(`[ImageHandler] Failed to get image info for log: ${C}`,A),{url:C,size:0,width:0,height:0}}})));const d=n.size||Ze(n.aspectRatio),y=at({prompt:n.prompt,model:n.model,size:d,referenceImages:i,isInspirationBoard:n.isInspirationBoard,inspirationBoardImageCount:n.inspirationBoardImageCount},r.modelName);t.onProgress(e.id,10,I.SUBMITTING);const S=Date.now(),h=l({endpoint:"/images/generations",model:r.modelName||"unknown",taskType:"image",prompt:n.prompt,hasReferenceImages:!!i&&i.length>0,referenceImageCount:i==null?void 0:i.length,referenceImages:p,taskId:e.id}),f=await w(`${r.baseUrl}/images/generations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r.apiKey}`},body:JSON.stringify(y),signal:o},{label:`🎨 生成图片 (${r.modelName})`,logRequestBody:!0,logResponseBody:!0});if(!f.ok){const C=await f.text();throw g(h,{httpStatus:f.status,duration:Date.now()-S,errorMessage:C,responseBody:C}),new Error(`Image generation failed: ${f.status} - ${C}`)}t.onProgress(e.id,80,I.DOWNLOADING);const m=await f.json(),T=JSON.stringify(m),{url:_}=await it(m,e.id);return u(h,{httpStatus:f.status,duration:Date.now()-S,resultType:"image",resultCount:1,resultUrl:_,responseBody:T}),t.onProgress(e.id,100),{url:_,format:"png",size:0,width:n.width,height:n.height}}}class ao{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,I.SUBMITTING);const{response:r,logId:n}=await this.submitVideoGeneration(e,t,o.signal);return t.onRemoteId(e.id,r.id),t.onProgress(e.id,5,I.POLLING),await this.pollUntilComplete(r.id,e.id,t,o.signal,n)}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:r}=await Promise.resolve().then(()=>O),n=r({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,I.POLLING),await this.pollUntilComplete(e.remoteId,e.id,t,o.signal,n)}finally{this.cleanup(e.id)}}cancel(e){this.cleanup(e)}async submitVideoGeneration(e,t,o){const{videoConfig:r}=t,{params:n}=e,a=new FormData;a.append("model",n.model||"veo3"),a.append("prompt",n.prompt),n.duration&&a.append("seconds",String(n.duration)),n.size&&a.append("size",n.size);const i=Ut({referenceImages:n.referenceImages,uploadedImages:n.uploadedImages,inputReference:n.inputReference,inputReferences:n.inputReferences}),{getImageInfo:c}=await Promise.resolve().then(()=>ct),l=[];if(i.length>0){const m=n.size?Gt(n.size):null;for(let T=0;T<i.length;T++){const _=i[T];try{let C=await ot(_,o);if(C){m&&(C=await Ht(C,m.width,m.height));try{const A=await c(C,o);l.push({url:A.url,size:A.size,width:A.width,height:A.height})}catch(A){console.warn("[VideoHandler] Failed to get cropped image info for log",A),l.push({url:_,size:C.size,width:0,height:0})}a.append("input_reference",C,`reference-${T+1}.png`)}else console.warn(`[VideoHandler] Failed to get reference image: ${_}`),a.append("input_reference",_),l.push({url:_,size:0,width:0,height:0})}catch(C){console.warn(`[VideoHandler] Error fetching reference image: ${_}`,C),a.append("input_reference",_),l.push({url:_,size:0,width:0,height:0})}}}const{debugFetch:u}=await Promise.resolve().then(()=>N),{startLLMApiLog:g,completeLLMApiLog:w,failLLMApiLog:p}=await Promise.resolve().then(()=>O),d=Date.now(),y=n.model||"veo3",S=g({endpoint:"/videos",model:y,taskType:"video",prompt:n.prompt,hasReferenceImages:i.length>0,referenceImageCount:i.length,referenceImages:l,taskId:e.id}),h=await u(`${r.baseUrl}/videos`,{method:"POST",headers:r.apiKey?{Authorization:`Bearer ${r.apiKey}`}:void 0,body:a,signal:o},{label:`🎬 提交视频生成 (${y})`,logResponseBody:!0});if(!h.ok){const m=await h.text();throw p(S,{httpStatus:h.status,duration:Date.now()-d,errorMessage:m,responseBody:m}),new Error(`Video submission failed: ${h.status} - ${m}`)}const f=await h.json();if(f.id){const{updateLLMApiLogMetadata:m}=await Promise.resolve().then(()=>O);m(S,{remoteId:f.id,responseBody:JSON.stringify(f),httpStatus:h.status})}return{response:f,logId:S}}async pollUntilComplete(e,t,o,r,n){const{videoConfig:a}=o,i=Date.now();try{const c=await et(a.baseUrl,e,{onProgress:(u,g)=>{o.onProgress(t,u,g)},signal:r,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(n){const{completeLLMApiLog:u}=await Promise.resolve().then(()=>O);u(n,{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(n){const{failLLMApiLog:l}=await Promise.resolve().then(()=>O);l(n,{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 io{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,I.SUBMITTING);const{response:r,logId:n}=await this.createCharacter(e,t,o.signal);return t.onRemoteId(e.id,r.id),t.onProgress(e.id,10,I.POLLING),await this.pollUntilComplete(r.id,e.id,t,o.signal,n)}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:r}=await Promise.resolve().then(()=>O),n=r({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,I.POLLING),await this.pollUntilComplete(e.remoteId,e.id,t,o.signal,n)}finally{this.cleanup(e.id)}}cancel(e){this.cleanup(e)}async createCharacter(e,t,o){const{videoConfig:r}=t,{params:n}=e,a=this.getCharacterModel(n.model),i=new FormData;i.append("character_from_task",n.sourceVideoTaskId||""),i.append("model",a),n.characterTimestamps&&i.append("character_timestamps",n.characterTimestamps);const{debugFetch:c}=await Promise.resolve().then(()=>N),{startLLMApiLog:l,completeLLMApiLog:u,failLLMApiLog:g}=await Promise.resolve().then(()=>O),w=Date.now(),p=l({endpoint:"/videos",model:a,taskType:"character",prompt:`角色提取: ${n.sourceVideoTaskId}`,taskId:e.id}),d=await c(`${r.baseUrl}/videos`,{method:"POST",headers:{...r.apiKey?{Authorization:`Bearer ${r.apiKey}`}:{}},body:i,signal:o},{label:`👤 创建角色视频 (${a})`,logResponseBody:!0});if(!d.ok){const S=await d.text();throw g(p,{httpStatus:d.status,duration:Date.now()-w,errorMessage:S,responseBody:S}),new Error(`Character creation failed: ${d.status} - ${S}`)}const y=await d.json();if(y.id){const{updateLLMApiLogMetadata:S}=await Promise.resolve().then(()=>O);S(p,{remoteId:y.id,responseBody:JSON.stringify(y),httpStatus:d.status})}return{response:y,logId:p}}async pollUntilComplete(e,t,o,r,n){const{videoConfig:a}=o,i=3e3,c=60,l=Date.now();let u=0;return new Promise((g,w)=>{const p=async()=>{if(r.aborted){if(n){const{failLLMApiLog:d}=await Promise.resolve().then(()=>O);d(n,{duration:Date.now()-l,errorMessage:"Task cancelled"})}w(new Error("Task cancelled"));return}if(u++,u>c){if(n){const{failLLMApiLog:d}=await Promise.resolve().then(()=>O);d(n,{duration:Date.now()-l,errorMessage:"Character creation timeout"})}w(new Error("Character creation timeout"));return}try{const d=await this.queryCharacter(e,a,r),y=Math.min(10+u/c*90,99);if(o.onProgress(t,y,I.POLLING),d.username){if(o.onProgress(t,100),n){const{completeLLMApiLog:h}=await Promise.resolve().then(()=>O);h(n,{httpStatus:200,duration:Date.now()-l,resultType:"character",resultCount:1,resultUrl:d.profile_picture_url,responseBody:JSON.stringify(d)})}g({url:d.profile_picture_url,format:"png",size:0,characterUsername:d.username,characterProfileUrl:d.profile_picture_url,characterPermalink:d.permalink});return}const S=setTimeout(p,i);this.pollingIntervals.set(t,S)}catch(d){if(d instanceof Error&&d.message.includes("404")){const y=setTimeout(p,i);this.pollingIntervals.set(t,y)}else if(u<c){const y=setTimeout(p,i);this.pollingIntervals.set(t,y)}else{if(n){const{failLLMApiLog:y}=await Promise.resolve().then(()=>O);y(n,{duration:Date.now()-l,errorMessage:d instanceof Error?d.message:String(d)})}w(d)}}};p()})}async queryCharacter(e,t,o){const{debugFetch:r}=await Promise.resolve().then(()=>N),n=await r(`${t.baseUrl}/videos/${e}`,{method:"GET",headers:t.apiKey?{Authorization:`Bearer ${t.apiKey}`}:void 0,signal:o},{label:"👤 查询角色状态",logResponseBody:!0});if(!n.ok)throw new Error(`Character query failed: ${n.status}`);return n.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 co{constructor(){this.abortControllers=new Map}async execute(e,t){const o=e.params,r=new AbortController;this.abortControllers.set(e.id,r);try{const n=this.convertToGeminiMessages(o),a=await this.streamChat(n,t.geminiConfig,o.temporaryModel,o.systemPrompt,r.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,r){const n=new AbortController;this.abortControllers.set(e,n);try{const a=this.convertToGeminiMessages(t);return await this.streamChat(a,o,t.temporaryModel,t.systemPrompt,n.signal,r)}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 r of e.messages){const n=[];if(r.content&&n.push({type:"text",text:r.content}),r.attachments)for(const a of r.attachments)a.type==="image"&&n.push({type:"image_url",image_url:{url:`data:${a.mimeType};base64,${a.data}`}});t.push({role:r.role,content:n})}if(e.newContent||(o=e.attachments)!=null&&o.length){const r=[];if(e.newContent&&r.push({type:"text",text:e.newContent}),e.attachments)for(const n of e.attachments)n.type==="image"&&r.push({type:"image_url",image_url:{url:`data:${n.mimeType};base64,${n.data}`}});t.push({role:"user",content:r})}return t}async streamChat(e,t,o,r,n,a){var ee,We,ke,As,Rs,Ds,Ls,Is,Os;const i=o||t.modelName||"gemini-2.5-flash",c={model:i,messages:e,stream:!0},{debugFetch:l}=await Promise.resolve().then(()=>N),{startLLMApiLog:u,completeLLMApiLog:g,failLLMApiLog:w}=await Promise.resolve().then(()=>O),p=Date.now(),d=e.filter(x=>x.role==="user").pop(),y=((We=(ee=d==null?void 0:d.content)==null?void 0:ee[0])==null?void 0:We.text)||"",{getImageInfo:S}=await Promise.resolve().then(()=>ct),h=[];for(const x of e)if(x.role==="user"&&x.content){for(const de of x.content)if(de.type==="image_url"&&((ke=de.image_url)!=null&&ke.url))try{const K=await S(de.image_url.url,n);h.push({url:K.url,size:K.size,width:K.width,height:K.height})}catch(K){console.warn("[ChatHandler] Failed to get image info for log",K),h.push({url:de.image_url.url,size:0,width:0,height:0})}}const f=u({endpoint:"/chat/completions",model:i,taskType:"chat",prompt:y,requestBody:JSON.stringify(c,null,2),hasReferenceImages:h.length>0,referenceImageCount:h.length,referenceImages:h}),m=await l(`${t.baseUrl}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`},body:JSON.stringify(c),signal:n},{label:`💬 对话请求 (${i})`,logRequestBody:!0,isStreaming:!0});if(!m.ok){const x=await m.text();throw w(f,{httpStatus:m.status,duration:Date.now()-p,errorMessage:x}),new Error(`Chat request failed: ${m.status} - ${x}`)}const T=p,_=f;if(!m.body)throw new Error("No response body");const C=m.body.getReader(),A=new TextDecoder;let b="",W="";try{for(;;){const{done:x,value:de}=await C.read();if(x)break;W+=A.decode(de,{stream:!0});const K=W.split(`
2
+ `);W=K.pop()||"";for(const Ws of K)if(Ws.startsWith("data: ")){const ks=Ws.slice(6).trim();if(ks==="[DONE]")continue;try{const Ps=(Ds=(Rs=(As=JSON.parse(ks).choices)==null?void 0:As[0])==null?void 0:Rs.delta)==null?void 0:Ds.content;Ps&&(b+=Ps,a==null||a(b))}catch{}}}if(W.startsWith("data: ")){const x=W.slice(6).trim();if(x&&x!=="[DONE]")try{const K=(Os=(Is=(Ls=JSON.parse(x).choices)==null?void 0:Ls[0])==null?void 0:Is.delta)==null?void 0:Os.content;K&&(b+=K,a==null||a(b))}catch{}}}finally{C.releaseLock()}if(m.__debugLogId&&b){const{updateLogResponseBody:x}=await Promise.resolve().then(()=>N);x(m.__debugLogId,b)}const{completeLLMApiLog:Z}=await Promise.resolve().then(()=>O);return Z(_,{httpStatus:m.status,duration:Date.now()-T,resultType:"text",resultCount:1,resultText:b}),b}}class lo{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.hadSavedConfig=!1,this.sw=e,this.config={...Ms,...t},this.imageHandler=new no,this.videoHandler=new ao,this.characterHandler=new io,this.chatHandler=new co,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 E.loadConfig();t&&o&&(this.geminiConfig=t,this.videoConfig=o,this.initialized=!0,this.hadSavedConfig=!0);const r=await E.getAllTasks();let n=0;for(const a of r){if(a.status===R.COMPLETED&&((e=a.result)!=null&&e.url)&&a.result.url.startsWith("data:image/")){const{url:i,migrated:c}=await Vt(a.result.url);c&&(a.result.url=i,await E.saveTask(a),n++)}if(this.tasks.set(a.id,a),a.type===L.CHAT&&a.status===R.PROCESSING){await this.markTaskFailed(a.id,{code:"INTERRUPTED",message:"Chat 请求被中断(页面刷新),请重试"});continue}this.shouldResumeTask(a)&&this.resumeTaskExecution(a)}n>0}catch(t){console.error("[SWTaskQueue] Failed to restore from storage:",t)}}shouldResumeTask(e){return e.type===L.CHAT&&e.status===R.PROCESSING?!1:!!(e.status===R.PROCESSING||e.status===R.PENDING||(e.type===L.VIDEO||e.type===L.CHARACTER)&&e.status===R.FAILED&&e.remoteId&&this.isNetworkError(e))}isNetworkError(e){var i,c,l,u;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)||"",r=((u=e.error)==null?void 0:u.code)||"",n=`${t} ${o}`.toLowerCase();return n.includes("generation_failed")||n.includes("invalid_argument")||n.includes("prohibited")||n.includes("content policy")||n.includes("视频生成失败")||r.includes("generation_failed")||r.includes("INVALID")?!1:n.includes("failed to fetch")||n.includes("network")||n.includes("fetch")||n.includes("timeout")||n.includes("aborted")||n.includes("connection")||n.includes("status query failed")||n.includes("429")||n.includes("too many requests")}async resumeTaskExecution(e){if(this.initialized){if(e.remoteId&&(e.type===L.VIDEO||e.type===L.CHARACTER))e.status===R.FAILED&&(e.status=R.PROCESSING,e.error=void 0,e.executionPhase=I.POLLING,e.updatedAt=Date.now(),this.tasks.set(e.id,e),await E.saveTask(e)),this.runningTasks.add(e.id),this.broadcastToClients({type:"TASK_STATUS",taskId:e.id,status:R.PROCESSING,progress:e.progress,phase:I.POLLING,updatedAt:e.updatedAt}),this.executeResume(e,e.remoteId);else if(e.status===R.PENDING)this.processQueue();else if((e.type===L.VIDEO||e.type===L.CHARACTER)&&e.status===R.PROCESSING&&!e.remoteId){const{findSuccessLogByTaskId:t,findLatestLogByTaskId:o}=await Promise.resolve().then(()=>O),r=await t(e.id);if(r&&r.resultUrl){let i,c,l;if(r.responseBody)try{const u=JSON.parse(r.responseBody);i=u.width,c=u.height,l=parseInt(u.seconds||"0")||0}catch{}await this.handleTaskSuccess(e.id,{url:r.resultUrl,format:e.type===L.VIDEO?"mp4":"png",size:0,width:i,height:c,duration:l});return}const n=await o(e.id);let a=n==null?void 0:n.remoteId;if(!a&&(n!=null&&n.responseBody))try{const i=JSON.parse(n.responseBody);i.id&&(a=i.id)}catch{}if(a){e.remoteId=a,e.executionPhase=I.POLLING,e.updatedAt=Date.now(),this.tasks.set(e.id,e),await E.saveTask(e),this.resumeTaskExecution(e);return}await this.handleTaskError(e.id,new Error("任务中断且无法恢复(未找到已完成的结果)"))}else if((e.type===L.IMAGE||e.type===L.INSPIRATION_BOARD)&&e.status===R.PROCESSING){const{findSuccessLogByTaskId:t}=await Promise.resolve().then(()=>O),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){if(await this.storageRestorePromise,!this.hadSavedConfig){const o=[];for(const r of this.tasks.values())r.status===R.PENDING&&o.push(r.id);if(o.length>0){console.log(`[SWTaskQueue] First-time init: clearing ${o.length} orphan PENDING tasks created without API key`);for(const r of o)this.tasks.delete(r),await E.deleteTask(r)}}this.geminiConfig=e,this.videoConfig=t,this.initialized=!0,this.hadSavedConfig=!0,await E.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 E.saveConfig(this.geminiConfig,this.videoConfig)}async submitTask(e,t,o,r){if(!this.initialized){console.warn(`[SWTaskQueue] Cannot submit task ${e}: queue not initialized (no API key)`),this.broadcastToClients({type:"TASK_REJECTED",taskId:e,reason:"NO_API_KEY"});return}if(this.tasks.has(e)){console.warn(`[SWTaskQueue] Task ${e} already exists`);return}const n=Date.now(),a={id:e,type:t,status:R.PENDING,params:o,createdAt:n,updatedAt:n};this.tasks.set(e,a),await E.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=R.CANCELLED,t.updatedAt=Date.now(),this.tasks.set(e,t),await E.saveTask(t),this.broadcastToClients({type:"TASK_CANCELLED",taskId:e}))}async retryTask(e){const t=this.tasks.get(e);if(!(!t||t.status!==R.FAILED&&t.status!==R.CANCELLED)){if(!t.remoteId&&(t.type===L.VIDEO||t.type===L.CHARACTER))try{const{findLatestLogByTaskId:o}=await Promise.resolve().then(()=>O),r=await o(t.id);if(r!=null&&r.remoteId)t.remoteId=r.remoteId;else if(r!=null&&r.responseBody){const n=JSON.parse(r.responseBody);n.id&&(t.remoteId=n.id)}}catch(o){console.warn(`[SWTaskQueue] Failed to recover remoteId for retry: ${t.id}`,o)}t.status=R.PENDING,t.error=void 0,t.updatedAt=Date.now(),this.tasks.set(e,t),await E.saveTask(t),this.broadcastToClients({type:"TASK_STATUS",taskId:t.id,status:t.status,updatedAt:t.updatedAt}),this.processQueue()}}async resumeTask(e,t,o,r){let n=this.tasks.get(e);if(!n){const a=Date.now();n={id:e,type:o,status:R.PROCESSING,params:{prompt:""},createdAt:a,updatedAt:a,remoteId:t,executionPhase:I.POLLING},this.tasks.set(e,n),await E.saveTask(n)}(o===L.VIDEO||o===L.CHARACTER)&&(this.runningTasks.add(e),this.executeResume(n,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 E.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 E.saveTask(o)}async restoreTasks(e){for(const t of e)t.status!==R.COMPLETED&&t.status!==R.CANCELLED&&(this.tasks.set(t.id,t),await E.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 r=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:r,timestamp:Date.now(),delivered:!1}),this.broadcastToClients({type:"CHAT_DONE",chatId:e,fullContent:r});const n=this.chatResultCache.get(e);n&&(n.delivered=!0),this.cleanupChatCache()}catch(r){this.broadcastToClients({type:"CHAT_ERROR",chatId:e,error:r instanceof Error?r.message:String(r)})}}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 E.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===R.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}if(this.runningTasks.add(e.id),e.status=R.PROCESSING,e.startedAt=Date.now(),e.updatedAt=Date.now(),e.executionPhase=I.SUBMITTING,this.tasks.set(e.id,e),await E.saveTask(e),this.broadcastToClients({type:"TASK_STATUS",taskId:e.id,status:e.status,phase:e.executionPhase,updatedAt:e.updatedAt}),e.remoteId&&(e.type===L.VIDEO||e.type===L.CHARACTER)){e.executionPhase=I.POLLING,await E.saveTask(e),this.broadcastToClients({type:"TASK_STATUS",taskId:e.id,status:e.status,phase:e.executionPhase,updatedAt:e.updatedAt}),this.executeResume(e,e.remoteId);return}const t={geminiConfig:this.geminiConfig,videoConfig:this.videoConfig,onProgress:async(o,r,n)=>{const a=this.tasks.get(o);if(a&&a.status!==R.COMPLETED&&a.status!==R.FAILED&&a.status!==R.CANCELLED){const i=a.status;a.progress=r,n&&(a.executionPhase=n),a.updatedAt=Date.now(),this.tasks.set(o,a),await E.saveTask(a);const c=this.tasks.get(o);c&&c.status===i&&this.broadcastToClients({type:"TASK_STATUS",taskId:o,status:i,progress:r,phase:n,updatedAt:a.updatedAt})}},onRemoteId:async(o,r)=>{const n=this.tasks.get(o);n?(n.remoteId=r,n.executionPhase=I.POLLING,n.updatedAt=Date.now(),this.tasks.set(o,n),await E.saveTask(n),this.broadcastToClients({type:"TASK_SUBMITTED",taskId:o,remoteId:r})):console.warn(`[SW:TaskQueue] onRemoteId: task ${o} not found in tasks map`)}};try{const o=this.getHandler(e.type);if(!o)throw new Error(`No handler for task type: ${e.type}`);const r=this.config.timeouts[e.type]||600*1e3,n=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(r/6e4)} minutes`))},r)})]);await this.handleTaskSuccess(e.id,n)}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(r,n,a)=>{const i=this.tasks.get(r);if(i&&i.status!==R.COMPLETED&&i.status!==R.FAILED&&i.status!==R.CANCELLED){const c=i.status;i.progress=n,a&&(i.executionPhase=a),i.updatedAt=Date.now(),this.tasks.set(r,i),await E.saveTask(i);const l=this.tasks.get(r);l&&l.status===c&&this.broadcastToClients({type:"TASK_STATUS",taskId:r,status:c,progress:n,phase:a,updatedAt:i.updatedAt})}},onRemoteId:()=>{}};try{const r=this.getHandler(e.type);if(!r||typeof r.resume!="function")throw new Error(`Handler does not support resume: ${e.type}`);e.remoteId=t;const n=await r.resume(e,o);await this.handleTaskSuccess(e.id,n)}catch(r){console.error(`[SWTaskQueue] executeResume: 任务 ${e.id} 恢复失败`,r),await this.handleTaskError(e.id,r)}}async handleTaskSuccess(e,t){var r;const o=this.tasks.get(e);o&&(o.status=R.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 E.saveTask(o),this.broadcastToClients({type:"TASK_COMPLETED",taskId:e,result:t,completedAt:o.completedAt,remoteId:o.remoteId}),(r=this.onTaskStatusChange)==null||r.call(this,e,"completed",t),this.processQueue())}async handleTaskError(e,t){var n;const o=this.tasks.get(e);if(!o)return;this.runningTasks.delete(e);const r={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=R.FAILED,o.error=r,o.updatedAt=Date.now(),this.tasks.set(e,o),await E.saveTask(o),this.broadcastToClients({type:"TASK_FAILED",taskId:e,error:r}),(n=this.onTaskStatusChange)==null||n.call(this,e,"failed",void 0,r.message),this.processQueue()}async markTaskFailed(e,t){const o=this.tasks.get(e);o&&(o.status=R.FAILED,o.error=t,o.updatedAt=Date.now(),this.tasks.set(e,o),await E.saveTask(o),this.broadcastToClients({type:"TASK_FAILED",taskId:e,error:t}))}getHandler(e){switch(e){case L.IMAGE:case L.INSPIRATION_BOARD:return this.imageHandler;case L.VIDEO:return this.videoHandler;case L.CHARACTER:return this.characterHandler;case L.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)vt(o,e)}catch(t){console.error("[SWTaskQueue] Failed to broadcast:",t)}}}let Ue=null;function uo(s,e){return Ue||(Ue=new lo(s,e)),Ue}function lt(){return Ue}function ho(s,e){var o,r;const t=lt();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:(r=s.filters)==null?void 0:r.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 n=t==null?void 0:t.getCachedChatResult(s.chatId);n?ve(e,{type:"CHAT_CACHED_RESULT",chatId:s.chatId,fullContent:n.fullContent,found:!0}).then(a=>{a||console.warn("[SWTaskQueue] Failed to send CHAT_CACHED_RESULT to client:",e)}):ve(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(()=>Qr).then(({executeMCPTool:n})=>{const a=lt(),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?n(s.requestId,s.toolName,s.args,i,c,e,l):l==null||l.clients.get(e).then(u=>{u&&u.postMessage({type:"MCP_TOOL_RESULT",requestId:s.requestId,success:!1,error:"Task queue not initialized",resultType:"error"})})});break}}}const fo={name:"generate_image",description:"Generate images using AI",async execute(s,e){const{geminiConfig:t,onProgress:o,signal:r}=e,{prompt:n,size:a,referenceImages:i,quality:c,model:l,count:u=1}=s;if(!n)return{success:!1,error:"缺少必填参数 prompt",type:"error"};try{o==null||o(0,I.SUBMITTING);const g=at({prompt:n,model:l,size:a,referenceImages:i,quality:c,n:Math.min(Math.max(1,u),10)},t.modelName);o==null||o(10,I.SUBMITTING);const{debugFetch:w}=await Promise.resolve().then(()=>N),p=await w(`${t.baseUrl}/images/generations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`},body:JSON.stringify(g),signal:r},{label:`🎨 生成图片 (${t.modelName})`,logRequestBody:!0,logResponseBody:!0});if(!p.ok){const h=await p.text();throw console.error("[SW:generateImage] ✗ API error:",p.status,h.substring(0,200)),new Error(`Image generation failed: ${p.status} - ${h}`)}o==null||o(80,I.DOWNLOADING);const d=await p.json(),{url:y,urls:S}=await it(d);return o==null||o(100),{success:!0,type:"image",data:{url:y,urls:S,format:"png",prompt:n,size:a||"1x1"}}}catch(g){return console.error("[SW:generateImage] Error:",g),{success:!1,error:g.message||"图片生成失败",type:"error"}}}},go={name:"generate_video",description:"Generate videos using AI",async execute(s,e){const{videoConfig:t,onProgress:o,onRemoteId:r,signal:n}=e,{prompt:a,model:i="veo3",seconds:c="8",size:l="1280x720",inputReference:u,inputReferences:g,referenceImages:w}=s;if(!a)return{success:!1,error:"缺少必填参数 prompt",type:"error"};try{o==null||o(0,I.SUBMITTING);const p={model:i,prompt:a,seconds:c,size:l},d=[];g&&g.length>0?g.forEach(T=>{const _=typeof T=="string"?T:T==null?void 0:T.url;_&&d.push(_)}):w&&w.length>0?d.push(...w):u&&d.push(u),d.length>0&&(d.length===1?p.input_reference=d[0]:p.input_references=d);const{debugFetch:y}=await Promise.resolve().then(()=>N),S=await y(`${t.baseUrl}/videos/generations`,{method:"POST",headers:{"Content-Type":"application/json",...t.apiKey?{Authorization:`Bearer ${t.apiKey}`}:{}},body:JSON.stringify(p),signal:n},{label:`🎬 提交视频生成 (${t.model||"default"})`,logRequestBody:!0,logResponseBody:!0});if(!S.ok){const T=await S.text();throw console.error("[SW:generateVideo] ✗ Submit failed:",S.status,T.substring(0,200)),new Error(`Video submission failed: ${S.status} - ${T}`)}const h=await S.json(),f=h.id||h.video_id;if(!f)throw console.error("[SW:generateVideo] ✗ No video ID in response:",h),new Error("No video ID in response");r==null||r(f),o==null||o(10,I.POLLING);const m=await et(t.baseUrl,f,{onProgress:o,signal:n,apiKey:t.apiKey});return{success:!0,type:"video",data:{url:m.video_url||m.url,format:"mp4",prompt:a,duration:parseInt(m.seconds||"")||parseInt(c)}}}catch(p){return console.error("[SW:generateVideo] ✗ Error:",p.message),{success:!1,error:p.message||"视频生成失败",type:"error"}}}},Qt=new Map([["generate_image",fo],["generate_video",go]]);function Jt(s){return Qt.get(s)}async function ut(s,e,t){const o=Qt.get(s);return o?o.execute(e,t):{success:!1,error:`Unknown tool: ${s}`,type:"error"}}function dt(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 po{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 E.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 E.saveWorkflow(e),await E.deletePendingToolRequestsByWorkflow(e.id)}updateConfig(e){this.config={...this.config,...e}}async handleMainThreadToolResponse(e){const t=this.pendingToolRequests.get(e.requestId);if(t)this.pendingToolRequests.delete(e.requestId),t.resolve(e);else{const o=await E.getPendingToolRequest(e.requestId);if(!o)return;let r=this.workflows.get(o.workflowId);if(r||(r=await E.getWorkflow(o.workflowId),r&&this.workflows.set(r.id,r)),!r){await E.deletePendingToolRequest(e.requestId);return}const n=r.steps.find(a=>a.id===o.stepId);if(!n){await E.deletePendingToolRequest(e.requestId);return}if(e.success){n.status="completed",n.result={success:!0,type:"text",data:e.result};const a=e.addSteps;if(a&&a.length>0){const i=[];for(const c of a)r.steps.find(l=>l.id===c.id)||(r.steps.push({id:c.id,mcp:c.mcp,args:c.args,description:c.description,status:c.status||"pending"}),i.push(c));i.length>0&&this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:r.id,steps:i})}await E.saveWorkflow(r),this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:r.id,stepId:n.id,status:"completed",result:n.result})}else{n.status="failed",n.error=e.error||"Unknown error",n.result={success:!1,type:"error",error:n.error},await E.saveWorkflow(r),this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:r.id,stepId:n.id,status:"failed",error:n.error}),this.config.broadcast({type:"WORKFLOW_FAILED",workflowId:r.id,error:n.error}),await E.deletePendingToolRequest(e.requestId);return}await E.deletePendingToolRequest(e.requestId),await this.executeWorkflow(r)}}async updateWorkflowStepForTask(e,t,o,r){for(const n of this.workflows.values()){const a=n.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=r,a.result={...a.result,success:!1,error:r}),a.updatedAt=Date.now(),n.updatedAt=Date.now(),await E.saveWorkflow(n),this.broadcastStepStatus(n.id,a),n.status==="running"&&this.executeWorkflow(n.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=[];for(const[,t]of this.pendingToolRequests){const{requestInfo:o}=t;e.includes(o.toolName)||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){const t=this.workflows.get(e.id);if(t){if(t.status==="running"||t.status==="pending"){this.broadcastWorkflowStatus(t),t.steps.forEach(o=>this.broadcastStepStatus(t.id,o));return}console.warn(`[SW-WorkflowExecutor] Workflow ${e.id} already exists with terminal status ${t.status}, skipping`),this.broadcastWorkflowStatus(t);return}e.status="pending",e.updatedAt=Date.now(),this.workflows.set(e.id,e),await E.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 E.saveWorkflow(t),await E.deletePendingToolRequestsByWorkflow(e),this.broadcastWorkflowStatus(t)}getWorkflow(e){return this.workflows.get(e)}getAllWorkflows(){return Array.from(this.workflows.values())}async executeWorkflow(e){const t=this.workflows.get(e);if(!t){console.error(`[WorkflowExecutor] ✗ Workflow ${e} not found`);return}if(this.runningWorkflows.has(e))return;this.runningWorkflows.add(e);const o=new AbortController;this.abortControllers.set(e,o),t.status="running",t.updatedAt=Date.now(),await E.saveWorkflow(t),this.broadcastWorkflowStatus(t);try{let r=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 u=t.steps.find(g=>g.id===l);return u&&(u.status==="completed"||u.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(r++,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 E.saveWorkflow(t),this.config.broadcast({type:"WORKFLOW_COMPLETED",workflowId:e,workflow:t})):await E.saveWorkflow(t)}catch(r){console.error(`[WorkflowExecutor] ✗ Workflow ${e} failed:`,r),t.status="failed",t.error=r.message,t.updatedAt=Date.now(),await E.saveWorkflow(t),this.config.broadcast({type:"WORKFLOW_FAILED",workflowId:e,error:r.message})}finally{this.runningWorkflows.delete(e),this.abortControllers.delete(e)}}replaceImagePlaceholders(e,t){if(!t||t.length===0)return e;const o=r=>{if(typeof r=="string"){let n=r.replace(/\[图片(\d+)\]/g,(a,i)=>{const c=parseInt(i,10)-1;return c>=0&&c<t.length?t[c]:a});return n=n.replace(/\[Image\s*(\d+)\]/gi,(a,i)=>{const c=parseInt(i,10)-1;return c>=0&&c<t.length?t[c]:a}),n}if(Array.isArray(r))return r.map(n=>o(n));if(r&&typeof r=="object"){const n={};for(const[a,i]of Object.entries(r))n[a]=o(i);return n}return r};return o(e)}async executeStep(e,t,o){var l,u,g,w;const r=Date.now(),n=((l=e.context)==null?void 0:l.referenceImages)||[];t.mcp==="generate_image"||t.mcp;const a=this.replaceImagePlaceholders(t.args,n),i=JSON.stringify(t.args),c=JSON.stringify(a);i!==c?t.args=a:n.length>0&&(t.mcp==="generate_image"||t.mcp),t.status="running",await E.saveWorkflow(e),this.broadcastStepStatus(e.id,t);try{if(dt(t.mcp)||!Jt(t.mcp)){const p=await this.requestMainThreadTool(e.id,t.id,t.mcp,t.args);if(!p.success)throw new Error(p.error||"Main thread tool execution failed");if(p.addSteps&&p.addSteps.length>0){const S=[];for(const h of p.addSteps)e.steps.find(f=>f.id===h.id)||(e.steps.push({id:h.id,mcp:h.mcp,args:h.args,description:h.description,status:h.status}),S.push(h));S.length>0&&(await E.saveWorkflow(e),this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:e.id,steps:S}))}const d=p.result;if(["generate_image","generate_video","generate_grid_image","generate_inspiration_board"].includes(t.mcp)&&p.taskId){const S={generate_image:"image",generate_grid_image:"image",generate_inspiration_board:"image",generate_video:"video"};t.result={success:!0,type:S[t.mcp]||"image",data:d,taskId:p.taskId,taskIds:p.taskIds},t.status="running",t.duration=Date.now()-r,this.broadcastStepStatus(e.id,t);return}t.result={success:!0,type:(d==null?void 0:d.type)||"text",data:d}}else{const p={geminiConfig:this.config.geminiConfig,videoConfig:this.config.videoConfig,signal:o,onProgress:(y,S)=>{},onRemoteId:y=>{}},d=await ut(t.mcp,t.args,p);if(d.success&&d.type==="canvas"&&((u=d.data)!=null&&u.delegateToMainThread)){const y=await this.requestCanvasOperation(d.data.operation,d.data.args);if(!y.success)throw new Error(y.error||"Canvas operation failed");t.result={success:!0,type:"canvas",data:{completed:!0}}}else if(d.success&&d.type==="image"&&((g=d.data)!=null&&g.url)){const y=d.data,S=await this.requestCanvasOperation("canvas_insert",{items:[{type:"image",url:y.url}]});S.success||console.warn("[WorkflowExecutor] Failed to insert image to canvas:",S.error),t.result={success:!0,type:"image",data:d.data}}else if(d.success&&d.type==="video"&&((w=d.data)!=null&&w.url)){const y=d.data,S=await this.requestCanvasOperation("canvas_insert",{items:[{type:"video",url:y.url}]});S.success||console.warn("[WorkflowExecutor] Failed to insert video to canvas:",S.error),t.result={success:!0,type:"video",data:d.data}}else if(t.result={success:d.success,type:d.type||"text",data:d.data,error:d.error},!d.success)throw new Error(d.error||"Step execution failed");if(d.addSteps&&d.addSteps.length>0){const y=[];for(const S of d.addSteps)e.steps.find(h=>h.id===S.id)||(e.steps.push({id:S.id,mcp:S.mcp,args:S.args,description:S.description,status:S.status}),y.push(S));y.length>0&&this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:e.id,steps:y})}}t.status="completed",t.duration=Date.now()-r}catch(p){t.status="failed",t.error=p.message,t.duration=Date.now()-r,t.result={success:!1,type:"error",error:p.message}}await E.saveWorkflow(e),this.broadcastStepStatus(e.id,t)}async requestMainThreadTool(e,t,o,r){if(this.config.requestMainThreadTool)return this.config.requestMainThreadTool(e,t,o,r);const n=`tool_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return new Promise((a,i)=>{const c=setTimeout(()=>{this.pendingToolRequests.delete(n),i(new Error(`Main thread tool request timed out: ${o}`))},3e5);this.pendingToolRequests.set(n,{resolve:l=>{clearTimeout(c),E.deletePendingToolRequest(n),a(l)},reject:l=>{clearTimeout(c),E.deletePendingToolRequest(n),i(l)},requestInfo:{requestId:n,workflowId:e,stepId:t,toolName:o,args:r},timeout:c}),E.savePendingToolRequest({requestId:n,workflowId:e,stepId:t,toolName:o,args:r,createdAt:Date.now()}),this.config.broadcast({type:"MAIN_THREAD_TOOL_REQUEST",requestId:n,workflowId:e,stepId:t,toolName:o,args:r})})}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 Xt(s=0){return`tc_${Date.now()}_${s}_${Math.random().toString(36).substr(2,9)}`}function ae(s){const e=s.trim();try{return JSON.parse(e)}catch{try{return JSON.parse(So(e))}catch{return null}}}function Yt(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 mo(s){const e=s.trim();if(!e.startsWith("{")||!e.endsWith("}")||!e.includes('"content"')||!e.includes('"next"'))return!1;let t=0,o=0,r=!1,n=!1;for(const a of e){if(n){n=!1;continue}if(a==="\\"){n=!0;continue}if(a==='"'){r=!r;continue}r||(a==="{"?t++:a==="}"?t--:a==="["?o++:a==="]"&&o--)}return t===0&&o===0}function Zt(s){const e=Yt(s);if(!mo(e))return null;let t=ae(e);if(!t){const n=e.match(/\{\s*"content"\s*:\s*"[^"]*"\s*,\s*"next"\s*:\s*\[[\s\S]*?\]\s*\}/);n&&(t=ae(n[0]))}if(!t){const n=e.match(/\{[\s\S]*"content"[\s\S]*"next"[\s\S]*\}/);n&&(t=ae(n[0]))}if(!t||typeof t.content!="string")return null;const r=(Array.isArray(t.next)?t.next:[]).filter(n=>typeof n=="object"&&n!==null&&typeof n.mcp=="string"&&typeof n.args=="object").map(n=>({mcp:n.mcp,args:n.args}));return{content:t.content,next:r}}function wo(s){const e=Zt(s);if(e&&e.next.length>0)return e.next.map((a,i)=>({id:Xt(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:Xt(),name:a.name,arguments:typeof i=="object"&&i!==null?i:{}}},r=/```tool_call\s*\n?([\s\S]*?)\n?```/gi;let n;for(;(n=r.exec(s))!==null;){const a=ae(n[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(;(n=a.exec(s))!==null;){const i=ae(n[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(;(n=a.exec(s))!==null;){const i=ae(n[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(;(n=a.exec(s))!==null;){const i=ae(n[0]);if(i){const c=o(i);if(c){t.push(c);break}}}}return t}function yo(s){const e=Zt(s);if(e)return e.content;let t=Yt(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
3
 
4
- `),t.trim()}function wo(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,(r,n,a)=>`: "${n}\\n${a}"`),e=e.replace(/'([^']*?)'/g,(r,n)=>!n.includes(":")||n.length>50?`"${n}"`:r),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 yo(s){return po(s).map(t=>({...t,status:"pending"}))}class So{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 C.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 C.saveChatWorkflow(e)}updateConfig(e){this.config={...this.config,...e}}async startWorkflow(e,t,o){const r=this.workflows.get(e);if(r){if(r.status==="streaming"||r.status==="pending"||r.status==="executing_tools"){this.broadcastStatus(r);return}console.warn("[SW-ChatWorkflow] Workflow already exists, skipping:",{chatId:e,status:r.status}),this.broadcastStatus(r);return}this.workflowClients.set(e,o);const n={id:e,status:"pending",params:t,content:"",toolCalls:[],createdAt:Date.now(),updatedAt:Date.now()};this.workflows.set(e,n),await C.saveChatWorkflow(n);const a=new AbortController;this.abortControllers.set(e,a),this.executeWorkflow(n,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 C.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 C.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 C.saveChatWorkflow(e),this.broadcastStatus(e);const r=yo(o),n=mo(o);e.toolCalls=r,e.aiAnalysis=n,r.length>0&&this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_CALLS",chatId:e.id,aiAnalysis:n,toolCalls:r}),r.length>0&&(e.status="executing_tools",await C.saveChatWorkflow(e),this.broadcastStatus(e),await this.executeTools(e,t)),e.status="completed",e.completedAt=Date.now(),e.updatedAt=Date.now(),await C.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 C.saveChatWorkflow(e)}finally{this.abortControllers.delete(e.id)}}async streamChat(e,t){var d,y,S,h,f,g;const{params:o}=e,{geminiConfig:r}=this.config,n=this.convertToGeminiMessages(o),a=o.temporaryModel||r.modelName||"gemini-2.5-flash",i={model:a,messages:n,stream:!0},{debugFetch:c}=await Promise.resolve().then(()=>N),l=await c(`${r.baseUrl}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r.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 u=l.body.getReader(),p=new TextDecoder;let w="",m="";try{for(;;){const{done:T,value:_}=await u.read();if(T)break;m+=p.decode(_,{stream:!0});const E=m.split(`
5
- `);m=E.pop()||"";for(const D of E)if(D.startsWith("data: ")){const b=D.slice(6).trim();if(b==="[DONE]")continue;try{const Z=(S=(y=(d=JSON.parse(b).choices)==null?void 0:d[0])==null?void 0:y.delta)==null?void 0:S.content;Z&&(w+=Z,this.config.broadcast({type:"CHAT_WORKFLOW_STREAM",chatId:e.id,content:w}))}catch{}}}if(m.startsWith("data: ")){const T=m.slice(6).trim();if(T&&T!=="[DONE]")try{const E=(g=(f=(h=JSON.parse(T).choices)==null?void 0:h[0])==null?void 0:f.delta)==null?void 0:g.content;E&&(w+=E,this.config.broadcast({type:"CHAT_WORKFLOW_STREAM",chatId:e.id,content:w}))}catch{}}}finally{u.releaseLock()}if(l.__debugLogId&&w){const{updateLogResponseBody:T}=await Promise.resolve().then(()=>N);T(l.__debugLogId,w)}return w}async executeTools(e,t){const o=this.workflowClients.get(e.id);for(const r of e.toolCalls){if(t.aborted)throw new Error("Workflow cancelled");r.status="running",this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_START",chatId:e.id,toolCallId:r.id,toolName:r.name});try{let n;if(dt(r.name)||!Vt(r.name)){if(!o)throw new Error("No client ID found for workflow");const a=await this.config.requestMainThreadTool(o,e.id,r.id,r.name,r.arguments);n={success:a.success,data:a.result,error:a.error}}else{const a={geminiConfig:this.config.geminiConfig,videoConfig:this.config.videoConfig,signal:t},i=await ut(r.name,r.arguments,a);n={success:i.success,data:i.data,error:i.error,taskId:i.taskId}}r.status=n.success?"completed":"failed",r.result=n,await C.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_COMPLETE",chatId:e.id,toolCallId:r.id,success:n.success,result:n.data,error:n.error,taskId:n.taskId})}catch(n){r.status="failed",r.result={success:!1,error:n.message},await C.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_COMPLETE",chatId:e.id,toolCallId:r.id,success:!1,error:n.message})}}}convertToGeminiMessages(e){var o;const t=[];e.systemPrompt&&t.push({role:"system",content:[{type:"text",text:e.systemPrompt}]});for(const r of e.messages){const n=[];if(r.content&&n.push({type:"text",text:r.content}),r.attachments)for(const a of r.attachments)a.type==="image"&&n.push({type:"image_url",image_url:{url:`data:${a.mimeType};base64,${a.data}`}});t.push({role:r.role,content:n})}if(e.newContent||(o=e.attachments)!=null&&o.length){const r=[];if(e.newContent&&r.push({type:"text",text:e.newContent}),e.attachments)for(const n of e.attachments)n.type==="image"&&r.push({type:"image_url",image_url:{url:`data:${n.mimeType};base64,${n.data}`}});t.push({role:"user",content:r})}return t}broadcastStatus(e){this.config.broadcast({type:"CHAT_WORKFLOW_STATUS",chatId:e.id,status:e.status,updatedAt:e.updatedAt})}}let P=null,V=null,fe=null,ge=null;function ht(s,e,t){fe=e,ge=t,P=new fo({geminiConfig:e,videoConfig:t,broadcast:r=>me(r)});const o=lt();o&&o.setTaskStatusChangeCallback((r,n,a,i)=>{P==null||P.updateWorkflowStepForTask(r,n,a,i)}),V=new So({geminiConfig:e,videoConfig:t,broadcast:r=>me(r),sendToClient:(r,n)=>gt(r,n),requestMainThreadTool:async(r,n,a,i,c)=>{const l=`chat_tool_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return new Promise((u,p)=>{const w=setTimeout(()=>{pe.delete(l),C.deletePendingToolRequest(l),p(new Error(`Tool request timed out: ${i}`))},3e5);pe.set(l,{resolve:m=>{clearTimeout(w),C.deletePendingToolRequest(l),u(m)},reject:m=>{clearTimeout(w),C.deletePendingToolRequest(l),p(m)},requestInfo:{requestId:l,chatId:n,toolCallId:a,toolName:i,args:c,clientId:r},timeout:w}),C.savePendingToolRequest({requestId:l,workflowId:n,stepId:a,toolName:i,args:c,createdAt:Date.now(),clientId:r}),gt(r,{type:"MAIN_THREAD_TOOL_REQUEST",requestId:l,workflowId:n,stepId:a,toolName:i,args:c})})}})}const pe=new Map;function To(s,e){if(!P){console.warn("[WorkflowHandler] Not initialized");return}s&&(fe={...fe||{},...s}),e&&(ge={...ge||{},...e}),!(!fe||!ge)&&(P.updateConfig({geminiConfig:fe,videoConfig:ge}),V&&V.updateConfig({geminiConfig:fe,videoConfig:ge}))}function Co(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 ft(s,e){if(s.type.startsWith("CHAT_WORKFLOW_")){Eo(s,e);return}if(!P){console.error("[WorkflowHandler] ✗ Not initialized, ignoring message:",s.type);return}const t=s;switch(t.type){case"WORKFLOW_SUBMIT":P.submitWorkflow(t.workflow);break;case"WORKFLOW_CANCEL":P.cancelWorkflow(t.workflowId);break;case"WORKFLOW_GET_STATUS":{const o=P.getWorkflow(t.workflowId);me({type:"WORKFLOW_STATUS_RESPONSE",workflowId:t.workflowId,workflow:o||null});break}case"WORKFLOW_GET_ALL":{const o=P.getAllWorkflows();me({type:"WORKFLOW_ALL_RESPONSE",workflows:o});break}}}function Eo(s,e){if(!V){console.error("[WorkflowHandler] ✗ Chat workflow handler not initialized");return}switch(s.type){case"CHAT_WORKFLOW_START":V.startWorkflow(s.chatId,s.params,e);break;case"CHAT_WORKFLOW_CANCEL":V.cancelWorkflow(s.chatId);break;case"CHAT_WORKFLOW_GET_STATUS":{const t=V.getWorkflow(s.chatId);me({type:"CHAT_WORKFLOW_STATUS_RESPONSE",chatId:s.chatId,workflow:t||null});break}case"CHAT_WORKFLOW_GET_ALL":{const t=V.getAllWorkflows();me({type:"CHAT_WORKFLOW_ALL_RESPONSE",workflows:t});break}}}async function _o(s){const e=pe.get(s.requestId);if(e){pe.delete(s.requestId),e.resolve(s);return}if(await C.deletePendingToolRequest(s.requestId),!P){console.error("[WorkflowHandler] ✗ Not initialized, ignoring tool response");return}P.handleMainThreadToolResponse(s)}function bo(){if(P&&(P.broadcastRecoveredWorkflows(),P.resendPendingToolRequests()),V&&V.broadcastRecoveredWorkflows(),pe.size!==0)for(const[,s]of pe){const{requestInfo:e}=s;gt(e.clientId,{type:"MAIN_THREAD_TOOL_REQUEST",requestId:e.requestId,workflowId:e.chatId,stepId:e.toolCallId,toolName:e.toolName,args:e.args})}}function me(s){Nt(s)}async function gt(s,e){await xe(s,e)||Nt(e)}const De=[],Ao=100;let pt=!1,te=null;function Ro(s){pt=s}function mt(){return pt}function Yt(s){te=s}function Zt(){return[...De]}function Do(s,e){const t=De.find(o=>o.id===s);t&&(t.responseBody=e.length>5e3?e.substring(0,5e3)+"...(truncated)":e,te&&te({...t}))}async function Lo(s){return new Promise((e,t)=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.onerror=t,o.readAsDataURL(s)})}async function Io(s){const e=[];for(const[t,o]of s.entries())if(o instanceof Blob){const r={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{r.dataUrl=await Lo(o)}catch{}o instanceof File&&(r.fileName=o.name),e.push(r)}else e.push({name:t,value:String(o).length>500?String(o).substring(0,500)+"...":String(o)});return e}async function Oo(s,e,t){if(!pt)return fetch(s,e);const o=typeof s=="string"?s:s instanceof URL?s.href:s.url,r=(e==null?void 0:e.method)||"GET",n=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 Io(e.body)}catch{i="[FormData - unable to parse]"}else if(t!=null&&t.logRequestBody)try{const p=typeof e.body=="string"?e.body:JSON.stringify(e.body),w=/data:image\/([^;]+);base64,([A-Za-z0-9+/=]+)/g;let m,d=0;for(l=[];(m=w.exec(p))!==null;){const h=`image/${m[1]}`,f=m[2];f.length>1e3&&(l.push({key:`image[${d}]`,dataUrl:`data:${h};base64,${f}`,mimeType:h,size:Math.round(f.length*.75/1024)}),d++)}l.length===0&&(l=void 0);let y=p.replace(/data:image\/([^;]+);base64,[A-Za-z0-9+/=]+/g,(h,f)=>`[📷 image/${f}]`);y=Dt(y),i=!o.includes("/chat/completions")&&y.length>3e3?y.substring(0,3e3)+"...(truncated)":y}catch{i="[unable to serialize body]"}}const u={id:a,timestamp:n,url:o,method:r,requestType:"sw-internal",details:(t==null?void 0:t.label)||`SW Internal: ${r} ${new URL(o).pathname}`,requestBody:i,formData:c,base64Images:l,isStreaming:t==null?void 0:t.isStreaming};De.unshift(u),De.length>Ao&&De.pop(),te&&te({...u});try{const p=await fetch(s,e);if(u.status=p.status,u.statusText=p.statusText,u.duration=Date.now()-n,t!=null&&t.isStreaming)u.responseBody="[流式响应 - 数据通过 SSE/Stream 实时传输,无法捕获完整响应体]";else if(t!=null&&t.logResponseBody)try{const w=p.headers.get("content-type")||"";if(w.includes("application/json")||w.includes("text/")){const d=await p.clone().text();u.responseBody=d.length>2e3?d.substring(0,2e3)+"...(truncated)":d}}catch{}return te&&te({...u}),p.__debugLogId=a,p}catch(p){const w=p.message||String(p);let m="NETWORK_ERROR";throw w.includes("ERR_CONNECTION_CLOSED")?m="ERR_CONNECTION_CLOSED":w.includes("ERR_CONNECTION_REFUSED")?m="ERR_CONNECTION_REFUSED":w.includes("ERR_CONNECTION_RESET")?m="ERR_CONNECTION_RESET":w.includes("ERR_CONNECTION_TIMED_OUT")||w.includes("timeout")?m="ERR_TIMEOUT":w.includes("ERR_NAME_NOT_RESOLVED")?m="ERR_DNS_FAILED":w.includes("ERR_INTERNET_DISCONNECTED")?m="ERR_OFFLINE":w.includes("ERR_SSL")||w.includes("certificate")?m="ERR_SSL":w.includes("Failed to fetch")?m="FETCH_FAILED":(w.includes("AbortError")||w.includes("aborted"))&&(m="ABORTED"),u.status=0,u.statusText=m,u.error=w,u.duration=Date.now()-n,te&&te({...u}),p}}const N=Object.freeze(Object.defineProperty({__proto__:null,debugFetch:Oo,getInternalFetchLogs:Zt,isDebugFetchEnabled:mt,setDebugFetchBroadcast:Yt,setDebugFetchEnabled:Ro,updateLogResponseBody:Do},Symbol.toStringTag,{value:"Module"})),Wo=typeof location<"u"&&(location.hostname==="localhost"||location.hostname==="127.0.0.1"),wt={degradeTimeout:60*1e3,failThreshold:3,fetchTimeout:1500},yt=[{name:"unpkg",urlTemplate:"https://unpkg.com/aitu-app@{version}/{path}",healthCheckPath:"version.json",enabled:!0,priority:1},{name:"jsdelivr",urlTemplate:"https://cdn.jsdelivr.net/npm/aitu-app@{version}/{path}",healthCheckPath:"version.json",enabled:!0,priority:2}],we=new Map;function es(){yt.forEach(s=>{we.has(s.name)||we.set(s.name,{name:s.name,isHealthy:!0,lastCheckTime:0,failCount:0,lastSuccessTime:Date.now()})})}es();function ts(s){const e=we.get(s);e&&(e.isHealthy=!0,e.failCount=0,e.lastSuccessTime=Date.now(),e.lastCheckTime=Date.now())}function ie(s){const e=we.get(s);e&&(e.failCount++,e.lastCheckTime=Date.now(),e.failCount>=wt.failThreshold&&(e.isHealthy=!1,console.warn(`[CDN Fallback] ${s} marked as unhealthy after ${e.failCount} failures`)))}function ko(s){const e=we.get(s);return e?e.isHealthy?!0:Date.now()-e.lastCheckTime>wt.degradeTimeout?(console.log(`[CDN Fallback] Trying to recover ${s}...`),!0):!1:!1}function Po(){return yt.filter(s=>s.enabled&&ko(s.name)).sort((s,e)=>s.priority-e.priority)}function ss(s){const e=/^\/?(aitu-app@[\d.]+\/)/;return s.replace(e,"/")}function os(s,e,t){const o=ss(t);return s.urlTemplate.replace("{version}",e).replace("{path}",o.startsWith("/")?o.slice(1):o)}async function St(s,e=wt.fetchTimeout){const t=new AbortController,o=setTimeout(()=>t.abort(),e);try{return await fetch(s,{signal:t.signal,cache:"no-store"})}finally{clearTimeout(o)}}async function Mo(s,e,t){if(Wo)return console.log("[CDN Fallback] 开发模式,跳过 CDN 回退"),null;const o=Po();for(const r of o){const n=os(r,e,s);try{console.log(`[CDN Fallback] Trying ${r.name}: ${n}`);const a=await St(n);if(a.ok){const i=a.headers.get("Content-Type")||"";if(!(i.includes("javascript")||i.includes("css")||i.includes("json")||i.includes("font")||i.includes("image")||i.includes("woff")||i.includes("application/octet-stream"))){console.warn(`[CDN Fallback] ${r.name} invalid Content-Type: ${i}`),ie(r.name);continue}const l=parseInt(a.headers.get("Content-Length")||"0",10),u=i.includes("javascript")||i.includes("css")||i.includes("json");if(u&&l>0&&l<50){console.warn(`[CDN Fallback] ${r.name} response too small: ${l} bytes`),ie(r.name);continue}const p=a.clone();try{const w=await p.text().then(d=>d.slice(0,200)),m=w.includes("<!DOCTYPE")||w.includes("<html")||w.includes("<HTML")||w.includes("Not Found")||w.includes("404");if(u&&m){console.warn(`[CDN Fallback] ${r.name} returned HTML instead of ${i}`),ie(r.name);continue}}catch{}return ts(r.name),console.log(`[CDN Fallback] Success from ${r.name}`),{response:a,source:r.name}}else console.warn(`[CDN Fallback] ${r.name} returned ${a.status}`),ie(r.name)}catch(a){console.warn(`[CDN Fallback] ${r.name} failed:`,a),ie(r.name)}}try{const r=ss(s),n=`${t}/${r.startsWith("/")?r.slice(1):r}`;console.log(`[CDN Fallback] Trying local server: ${n}`);const a=await St(n);if(a.ok)return console.log("[CDN Fallback] Success from local server"),{response:a,source:"local"}}catch(r){console.warn("[CDN Fallback] Local server failed:",r)}return console.error(`[CDN Fallback] All sources failed for: ${s}`),null}async function vo(s){const e=new Map;for(const t of yt){if(!t.enabled)continue;const o=os(t,s,t.healthCheckPath);try{const n=(await St(o,5e3)).ok;e.set(t.name,n),n?ts(t.name):ie(t.name)}catch{e.set(t.name,!1),ie(t.name)}}return e}function xo(){return Array.from(we.entries()).map(([s,e])=>({name:s,status:e}))}function No(){es(),console.log("[CDN Fallback] All CDN status reset")}const R=self;co(R),Qs();const ce={log:console.log.bind(console),info:console.info.bind(console),warn:console.warn.bind(console),error:console.error.bind(console)};function Bo(){console.log=(...s)=>{ce.log(...s),mt()&&Fe("log",s)},console.info=(...s)=>{ce.info(...s),mt()&&Fe("info",s)},console.warn=(...s)=>{ce.warn(...s),Fe("warn",s)},console.error=(...s)=>{ce.error(...s),Fe("error",s)}}function Fe(s,e){const t=e.map(r=>{if(typeof r=="object")try{return JSON.stringify(r)}catch{return String(r)}return String(r)}).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;Bo(),Yt(s=>{R.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_DEBUG_LOG",entry:{...s,type:"fetch"}})})})}),Promise.resolve().then(()=>O).then(({setLLMApiLogBroadcast:s})=>{s(e=>{R.clients.matchAll().then(t=>{t.forEach(o=>{o.postMessage({type:"SW_DEBUG_LLM_API_LOG",log:e})})})})});const Q="0.5.48",qe=`drawnix-v${Q}`,M="drawnix-images",ye=`drawnix-static-v${Q}`,$e="drawnix-fonts",Uo="/__aitu_cache__/",Fo="/asset-library/",rs=location.hostname==="localhost"||location.hostname==="127.0.0.1",qo=[{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"}],$o=/\.(jpg|jpeg|png|gif|webp|svg|bmp|ico)$/i,Go=/\.(mp4|webm|ogg|mov|avi|mkv|flv|wmv|m4v)$/i,G=new Map,le=new Map,ns=30*1e3,Le=new Map,q=new Map,Ho=300*1e3,as=10,Se=new Set,Te=new Set,zo=3600*1e3,Ct=new Map;function is(s){Te.add(s),Ct.set(s,Date.now()),console.warn(`Service Worker: 标记 ${s} 为 CORS 问题域名,后续请求将跳过 SW`)}function Ko(s){if(!Te.has(s))return!1;const e=Ct.get(s);return e&&Date.now()-e>zo?(Te.delete(s),Ct.delete(s),!1):!0}const Ie=[],jo=7,J=[],Vo=500;let $=!1,Ce=0;const Qo=15e3;let X=null;function cs(){if(!$)return;const s=Date.now();Ce>0&&s-Ce>Qo?(ce.log("Service Worker: Debug heartbeat timeout, auto-disabling debug mode"),$=!1,Ce=0,Ye(!1),Promise.resolve().then(()=>N).then(({setDebugFetchEnabled:e})=>{e(!1)}),R.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_DEBUG_DISABLED"})})}),X&&(clearTimeout(X),X=null)):$&&(X=setTimeout(cs,5e3))}function H(s){if(!$)return"";const e=Math.random().toString(36).substring(2,10),t={...s,id:e,timestamp:Date.now()};return J.unshift(t),J.length>Vo&&J.pop(),ls(t),e}function x(s,e){if(!$||!s)return;const t=J.find(o=>o.id===s);t&&(Object.assign(t,e),ls(t))}async function ls(s){try{(await R.clients.matchAll()).forEach(t=>{t.postMessage({type:"SW_DEBUG_LOG",entry:s})})}catch{}}function Ge(){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 r=o.target.result;if(!r.objectStoreNames.contains("logs")){const n=r.createObjectStore("logs",{keyPath:"id"});n.createIndex("timestamp","timestamp",{unique:!1}),n.createIndex("logLevel","logLevel",{unique:!1})}}})}async function Jo(s){try{const e=await Ge(),t=e.transaction(["logs"],"readwrite");return t.objectStore("logs").add(s),new Promise((r,n)=>{t.oncomplete=()=>{e.close(),r()},t.onerror=()=>{e.close(),n(t.error)}})}catch(e){console.warn("Service Worker: 无法保存控制台日志:",e)}}async function us(){try{const s=await Ge(),o=s.transaction(["logs"],"readonly").objectStore("logs").index("timestamp");return new Promise((r,n)=>{const a=o.openCursor(null,"prev"),i=[];a.onsuccess=()=>{const c=a.result;c?(i.push(c.value),c.continue()):(s.close(),r(i))},a.onerror=()=>{s.close(),n(a.error)}})}catch(s){return console.warn("Service Worker: 无法加载控制台日志:",s),[]}}async function Xo(){try{const s=await Ge(),o=s.transaction(["logs"],"readwrite").objectStore("logs").index("timestamp"),r=Date.now()-jo*24*60*60*1e3,n=IDBKeyRange.upperBound(r);return new Promise((a,i)=>{const c=o.openCursor(n);let l=0;c.onsuccess=()=>{const u=c.result;u?(u.delete(),l++,u.continue()):(s.close(),l>0,a(l))},c.onerror=()=>{s.close(),i(c.error)}})}catch(s){return console.warn("Service Worker: 无法清理过期日志:",s),0}}async function ds(){try{const s=await Ge(),e=s.transaction(["logs"],"readwrite");return e.objectStore("logs").clear(),new Promise((o,r)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),r(e.error)}})}catch(s){console.warn("Service Worker: 无法清空控制台日志:",s)}}function hs(s){if(!$)return;const t={id:Math.random().toString(36).substring(2,10),timestamp:Date.now(),type:"console",...s};Ie.unshift(t),Jo(t),Yo(t)}Tt=hs;async function Yo(s){try{(await R.clients.matchAll()).forEach(t=>{t.postMessage({type:"SW_CONSOLE_LOG",entry:s})})}catch{}}function Zo(){let s=0;return q.forEach(e=>{e.blob&&(s+=e.blob.size)}),s}function He(){return{version:Q,cacheNames:[qe,M,ye,$e],pendingImageRequests:G.size,pendingVideoRequests:Le.size,videoBlobCacheSize:q.size,videoBlobCacheTotalBytes:Zo(),completedImageRequestsSize:le.size,failedDomainsCount:Se.size,failedDomains:Array.from(Se),corsFailedDomainsCount:Te.size,corsFailedDomains:Array.from(Te),debugLogsCount:J.length,consoleLogsCount:Ie.length,debugModeEnabled:$,workflowHandlerInitialized:ue,memoryStats:{pendingRequestsMapSize:G.size,completedRequestsMapSize:le.size,videoBlobCacheMapSize:q.size,failedDomainsSetSize:Se.size,corsFailedDomainsSetSize:Te.size,debugLogsArraySize:J.length,consoleLogsArraySize:Ie.length}}}function fs(s){for(const e of qo)if(s.hostname===e.hostname&&s.pathname.includes(e.pathPattern))return e;return null}function er(s,e){return $o.test(s.pathname)||e.destination==="image"||fs(s)!==null}function tr(s,e){return Go.test(s.pathname)||e.destination==="video"||s.pathname.includes("/video/")||s.hash.startsWith("#merged-video-")||s.hash.includes("video")}function sr(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 or(){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=>Se.add(c.domain)),e()},a.onerror=()=>t(a.error)}else e()},s.onupgradeneeded=o=>{const r=o.target.result;r.objectStoreNames.contains("failedDomains")||r.createObjectStore("failedDomains",{keyPath:"domain"})}})}catch(s){console.warn("Service Worker: 无法加载失败域名列表:",s)}}async function rr(s){try{const e=indexedDB.open("ServiceWorkerDB",1);return new Promise((t,o)=>{e.onerror=()=>o(e.error),e.onsuccess=()=>{const n=e.result.transaction(["failedDomains"],"readwrite");n.objectStore("failedDomains").put({domain:s,timestamp:Date.now()}),n.oncomplete=()=>{t()},n.onerror=()=>o(n.error)},e.onupgradeneeded=r=>{const n=r.target.result;n.objectStoreNames.contains("failedDomains")||n.createObjectStore("failedDomains",{keyPath:"domain"})}})}catch(e){console.warn("Service Worker: 无法保存失败域名:",e)}}async function nr(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 r=0,n=0;for(let a=0;a<o&&a<t.length;a++)try{await s.delete(t[a].request),r++,n+=t[a].imageSize}catch(i){console.warn("Service Worker: Error deleting cache entry:",i)}}catch(e){console.warn("Service Worker: Cache cleanup failed:",e)}}async function ar(){try{const s=await fetch("./precache-manifest.json",{cache:"reload"});if(!s.ok)return console.log("Service Worker: No precache-manifest.json found (dev mode), skipping precache"),null;const e=await s.json();return console.log(`Service Worker: Loaded precache manifest v${e.version} with ${e.files.length} files`),e.files}catch{return console.log("Service Worker: Cannot load precache-manifest.json, skipping precache"),null}}async function ir(s,e,t){try{const o=await s.match(e);if(o&&o.headers.get("x-sw-revision")===t)return{url:e,success:!0,skipped:!0};const r=e.endsWith(".html")||e==="/";let n=null,a="server";if(!r){const i=await Mo(e.startsWith("/")?e.slice(1):e,Q,location.origin);i&&i.response.ok&&(n=i.response,a=i.source)}if(n||(n=await fetch(e,{cache:"reload"}),a="server"),n.ok){const i=new Headers(n.headers);i.set("x-sw-revision",t),i.set("x-sw-cached-at",new Date().toISOString()),i.set("x-sw-source",a);const c=new Response(await n.blob(),{status:n.status,statusText:n.statusText,headers:i}),l=new URL(e,self.location.origin).href;return await s.put(l,c),{url:e,success:!0,source:a}}return{url:e,success:!1,status:n.status}}catch(o){return{url:e,success:!1,error:String(o)}}}async function cr(s,e){const o=[];for(let c=0;c<e.length;c+=6){const l=e.slice(c,c+6),u=await Promise.allSettled(l.map(({url:p,revision:w})=>ir(s,p,w)));for(const p of u)p.status==="fulfilled"?o.push({success:p.value.success,source:p.value.source}):o.push({success:!1})}const r=o.filter(c=>c.success).length,n=o.length-r,a=o.filter(c=>c.success&&c.source&&c.source!=="server").length,i=o.filter(c=>c.success&&c.source==="server").length;console.log(`Service Worker: Precached ${r}/${e.length} files (${n} failed)`),a>0&&console.log(`Service Worker: Sources - CDN: ${a}, Server: ${i}`)}R.addEventListener("install",s=>{console.log(`Service Worker v${Q} installing...`);const e=[];e.push(or()),e.push((async()=>{try{const t=await ar();if(t&&t.length>0){const o=await caches.open(ye);await cr(o,t)}}catch(t){console.warn("Service Worker: Precache failed:",t)}})()),s.waitUntil(Promise.all(e).then(async()=>{console.log(`Service Worker v${Q} installed, resources ready`);const t=await caches.keys();t.some(o=>o.startsWith("drawnix-static-v")&&o!==ye),t.some(o=>o.startsWith("drawnix-v")&&o!==qe&&o!==M&&!o.startsWith("drawnix-static-v")),R.skipWaiting()}))}),R.addEventListener("activate",s=>{s.waitUntil(caches.keys().then(async e=>{const t=e.filter(a=>a.startsWith("drawnix-images-v")&&a!==M);if(t.length>0){const a=await caches.open(M);for(const i of t)try{const c=await caches.open(i),l=await c.keys();for(const u of l){const p=await c.match(u);p&&await a.put(u,p)}await caches.delete(i)}catch(c){console.warn(`Failed to migrate cache ${i}:`,c)}}const o=e.filter(a=>a.startsWith("drawnix-static-v")&&a!==ye),r=e.filter(a=>a.startsWith("drawnix-v")&&a!==qe&&a!==M&&!a.startsWith("drawnix-static-v"));(o.length>0||r.length>0)&&setTimeout(async()=>{for(const a of[...o,...r])try{await caches.delete(a)}catch(i){console.warn("Failed to delete old cache:",a,i)}},3e4),Xo().catch(a=>{console.warn("Failed to cleanup expired console logs:",a)}),await R.clients.claim(),(await R.clients.matchAll()).forEach(a=>{a.postMessage({type:"SW_ACTIVATED",version:Q})})}))});const lr=["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 ur(s){if(!s||typeof s!="object")return!1;const e=s;return e.type?lr.includes(e.type):!1}let ue=!1,Ee=null,_e=null;const ze=[];function gs(s){$&&R.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_POSTMESSAGE_LOG",entry:s})})})}Vs(gs),R.addEventListener("message",s=>{var r,n,a,i,c,l,u,p,w,m,d,y,S;const e=((r=s.data)==null?void 0:r.type)||"unknown",t=((n=s.source)==null?void 0:n.id)||"";let o="";if(Je()&&(o=Gs(e,s.data,t),o&&$)){const f=Re().find(g=>g.id===o);f&&gs(f)}if(s.data&&ur(s.data)){const h=((a=s.source)==null?void 0:a.id)||"";if(lo(s.data,h),s.data.type==="TASK_QUEUE_INIT"){const{geminiConfig:f,videoConfig:g}=s.data;if(Ee=f,_e=g,!ue&&(ht(R,f,g),ue=!0,ze.length>0)){for(const T of ze)ft(T.message,T.clientId);ze.length=0}bo()}if(s.data.type==="TASK_QUEUE_UPDATE_CONFIG"){const{geminiConfig:f,videoConfig:g}=s.data;f&&(Ee={...Ee,...f}),g&&(_e={..._e,...g}),To(f,g)}return}if(s.data&&Co(s.data)){const h=((i=s.source)==null?void 0:i.id)||"";if(!ue&&Ee&&_e&&(ht(R,Ee,_e),ue=!0),!ue){(async()=>{try{const{geminiConfig:f,videoConfig:g}=await C.loadConfig();if(f&&g)Ee=f,_e=g,ht(R,f,g),ue=!0,ft(s.data,h);else{const T=await R.clients.matchAll({type:"window"});for(const _ of T)_.postMessage({type:"SW_REQUEST_CONFIG",reason:"workflow_handler_not_initialized",pendingMessageType:s.data.type});ze.push({message:s.data,clientId:h})}}catch(f){console.error("[SW] Failed to load config from storage:",Ve(f))}})();return}ft(s.data,h);return}if(s.data&&s.data.type==="MAIN_THREAD_TOOL_RESPONSE"){_o(s.data);return}if(s.data&&s.data.type==="SKIP_WAITING")R.skipWaiting(),R.clients.matchAll().then(h=>{h.forEach(f=>{f.postMessage({type:"SW_UPDATED"})})});else if(s.data&&s.data.type==="GET_UPGRADE_STATUS")(c=s.source)==null||c.postMessage({type:"UPGRADE_STATUS",version:Q});else if(s.data&&s.data.type==="FORCE_UPGRADE")R.skipWaiting(),R.clients.matchAll().then(h=>{h.forEach(f=>{f.postMessage({type:"SW_UPDATED"})})});else if(s.data&&s.data.type==="DELETE_CACHE"){const{url:h}=s.data;h&&Sr(h).then(()=>{R.clients.matchAll().then(f=>{f.forEach(g=>{g.postMessage({type:"CACHE_DELETED",url:h})})})}).catch(f=>{console.error("Service Worker: Failed to delete cache:",f)})}else if(s.data&&s.data.type==="DELETE_CACHE_BATCH"){const{urls:h}=s.data;h&&Array.isArray(h)&&Tr(h).then(()=>{}).catch(f=>{console.error("Service Worker: Failed to batch delete caches:",f)})}else if(s.data&&s.data.type==="CLEAR_ALL_CACHE")Cr().then(()=>{}).catch(h=>{console.error("Service Worker: Failed to clear all cache:",h)});else if(s.data&&s.data.type==="SW_DEBUG_ENABLE")$=!0,Ce=Date.now(),Promise.resolve().then(()=>N).then(({setDebugFetchEnabled:h})=>{h(!0)}),Ye(!0),ce.log("Service Worker: Debug mode enabled"),X&&clearTimeout(X),X=setTimeout(cs,5e3),R.clients.matchAll().then(h=>{h.forEach(f=>{f.postMessage({type:"SW_DEBUG_ENABLED"})})}),(l=s.source)==null||l.postMessage({type:"SW_DEBUG_STATUS",status:He()});else if(s.data&&s.data.type==="SW_DEBUG_HEARTBEAT")$&&(Ce=Date.now());else if(s.data&&s.data.type==="SW_DEBUG_DISABLE")$=!1,Ce=0,X&&(clearTimeout(X),X=null),Promise.resolve().then(()=>N).then(({setDebugFetchEnabled:h})=>{h(!1)}),Ye(!1),Ie.length=0,J.length=0,ds().catch(()=>{}),ce.log("Service Worker: Debug mode disabled, logs cleared"),R.clients.matchAll().then(h=>{h.forEach(f=>{f.postMessage({type:"SW_DEBUG_DISABLED"})})}),(u=s.source)==null||u.postMessage({type:"SW_DEBUG_STATUS",status:He()});else if(s.data&&s.data.type==="SW_DEBUG_GET_STATUS")(async()=>{var g;const h=He(),f=await yr();(g=s.source)==null||g.postMessage({type:"SW_DEBUG_STATUS",status:{...h,cacheStats:f}})})();else if(s.data&&s.data.type==="SW_DEBUG_GET_LOGS"){const{limit:h=100,offset:f=0,filter:g}=s.data,T=Zt().map(b=>({...b,type:"fetch"})),_=new Map;for(const b of J)_.set(b.id,b);for(const b of T)_.set(b.id,b);let E=Array.from(_.values()).sort((b,W)=>W.timestamp-b.timestamp);g&&(g.type&&(E=E.filter(b=>b.type===g.type)),g.requestType&&(E=E.filter(b=>b.requestType===g.requestType)),g.url&&(E=E.filter(b=>{var W;return(W=b.url)==null?void 0:W.includes(g.url)})),g.status&&(E=E.filter(b=>b.status===g.status)));const D=E.slice(f,f+h);(p=s.source)==null||p.postMessage({type:"SW_DEBUG_LOGS",logs:D,total:E.length,offset:f,limit:h})}else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_LOGS")J.length=0,(w=s.source)==null||w.postMessage({type:"SW_DEBUG_LOGS_CLEARED"});else if(s.data&&s.data.type==="SW_CDN_GET_STATUS")(m=s.source)==null||m.postMessage({type:"SW_CDN_STATUS",status:xo()});else if(s.data&&s.data.type==="SW_CDN_RESET_STATUS")No(),(d=s.source)==null||d.postMessage({type:"SW_CDN_STATUS_RESET"});else if(s.data&&s.data.type==="SW_CDN_HEALTH_CHECK")(async()=>{var f;const h=await vo(Q);(f=s.source)==null||f.postMessage({type:"SW_CDN_HEALTH_CHECK_RESULT",results:Object.fromEntries(h)})})();else if(s.data&&s.data.type==="SW_DEBUG_GET_CACHE_ENTRIES"){const{cacheName:h,limit:f=50,offset:g=0}=s.data;(async()=>{var T,_;try{const E=await caches.open(h||M),D=await E.keys(),b=[];for(let W=g;W<Math.min(g+f,D.length);W++){const Z=D[W],ee=await E.match(Z);if(ee){const We=ee.headers.get("sw-cache-date"),ke=ee.headers.get("sw-image-size")||ee.headers.get("content-length");b.push({url:Z.url,cacheDate:We?parseInt(We):void 0,size:ke?parseInt(ke):void 0})}}(T=s.source)==null||T.postMessage({type:"SW_DEBUG_CACHE_ENTRIES",cacheName:h||M,entries:b,total:D.length,offset:g,limit:f})}catch(E){(_=s.source)==null||_.postMessage({type:"SW_DEBUG_CACHE_ENTRIES",error:String(E)})}})()}else if(s.data&&s.data.type==="SW_CONSOLE_LOG_REPORT"){const{logLevel:h,logMessage:f,logStack:g,logSource:T,url:_}=s.data;hs({logLevel:h,logMessage:f,logStack:g,logSource:T,url:_})}else if(s.data&&s.data.type==="SW_DEBUG_GET_CONSOLE_LOGS")(async()=>{var h,f;try{const{limit:g=500,offset:T=0,filter:_}=s.data;let E=await us();if(_&&(_.logLevel&&(E=E.filter(b=>b.logLevel===_.logLevel)),_.search)){const b=_.search.toLowerCase();E=E.filter(W=>{var Z,ee;return((Z=W.logMessage)==null?void 0:Z.toLowerCase().includes(b))||((ee=W.logStack)==null?void 0:ee.toLowerCase().includes(b))})}const D=E.slice(T,T+g);(h=s.source)==null||h.postMessage({type:"SW_DEBUG_CONSOLE_LOGS",logs:D,total:E.length,offset:T,limit:g})}catch(g){(f=s.source)==null||f.postMessage({type:"SW_DEBUG_CONSOLE_LOGS",logs:[],total:0,error:String(g)})}})();else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_CONSOLE_LOGS")(async()=>{var h;Ie.length=0,await ds(),(h=s.source)==null||h.postMessage({type:"SW_DEBUG_CONSOLE_LOGS_CLEARED"})})();else if(s.data&&s.data.type==="SW_DEBUG_EXPORT_LOGS")(async()=>{var T;const h=await us(),f=Re(),g={exportTime:new Date().toISOString(),swVersion:Q,userAgent:"",status:He(),fetchLogs:J,consoleLogs:h,postmessageLogs:f};(T=s.source)==null||T.postMessage({type:"SW_DEBUG_EXPORT_DATA",data:g})})();else if(s.data&&s.data.type==="SW_DEBUG_GET_POSTMESSAGE_LOGS"){const{limit:h=200,offset:f=0,filter:g}=s.data;let T=Re();if(g&&(g.direction&&(T=T.filter(E=>E.direction===g.direction)),g.messageType)){const E=g.messageType.toLowerCase();T=T.filter(D=>{var b;return(b=D.messageType)==null?void 0:b.toLowerCase().includes(E)})}const _=T.slice(f,f+h);(y=s.source)==null||y.postMessage({type:"SW_DEBUG_POSTMESSAGE_LOGS",logs:_,total:T.length,offset:f,limit:h,stats:js()})}else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_POSTMESSAGE_LOGS")Hs(),(S=s.source)==null||S.postMessage({type:"SW_DEBUG_POSTMESSAGE_LOGS_CLEARED"});else if(s.data&&s.data.type==="CRASH_SNAPSHOT"){const h=s.data.snapshot;h&&(hr(h),R.clients.matchAll().then(f=>{f.forEach(g=>{g.postMessage({type:"SW_DEBUG_NEW_CRASH_SNAPSHOT",snapshot:h})})}))}else s.data&&s.data.type==="SW_DEBUG_GET_CRASH_SNAPSHOTS"?(async()=>{var h,f;try{const g=await fr();(h=s.source)==null||h.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS",snapshots:g,total:g.length})}catch(g){(f=s.source)==null||f.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS",snapshots:[],total:0,error:String(g)})}})():s.data&&s.data.type==="SW_DEBUG_CLEAR_CRASH_SNAPSHOTS"?(async()=>{var h;await gr(),(h=s.source)==null||h.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS_CLEARED"})})():s.data&&s.data.type==="SW_DEBUG_GET_LLM_API_LOGS"?(async()=>{var h,f;try{const{getAllLLMApiLogs:g}=await Promise.resolve().then(()=>O),T=await g();(h=s.source)==null||h.postMessage({type:"SW_DEBUG_LLM_API_LOGS",logs:T,total:T.length})}catch(g){(f=s.source)==null||f.postMessage({type:"SW_DEBUG_LLM_API_LOGS",logs:[],total:0,error:String(g)})}})():s.data&&s.data.type==="SW_DEBUG_CLEAR_LLM_API_LOGS"&&(async()=>{var f;const{clearAllLLMApiLogs:h}=await Promise.resolve().then(()=>O);await h(),(f=s.source)==null||f.postMessage({type:"SW_DEBUG_LLM_API_LOGS_CLEARED"})})()});const dr="MemorySnapshotDB",re="snapshots",ps=50;async function Et(){return new Promise((s,e)=>{const t=indexedDB.open(dr,1);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const r=o.target.result;if(!r.objectStoreNames.contains(re)){const n=r.createObjectStore(re,{keyPath:"id"});n.createIndex("timestamp","timestamp",{unique:!1}),n.createIndex("type","type",{unique:!1})}}})}async function hr(s){try{const e=await Et(),t=e.transaction(re,"readwrite"),o=t.objectStore(re);o.put(s);const r=o.count();r.onsuccess=()=>{const n=r.result;if(n>ps){const i=o.index("timestamp").openCursor();let c=0;const l=n-ps;i.onsuccess=u=>{const p=u.target.result;p&&c<l&&(o.delete(p.value.id),c++,p.continue())}}},await new Promise((n,a)=>{t.oncomplete=()=>{e.close(),n()},t.onerror=()=>{e.close(),a(t.error)}})}catch(e){console.warn("[SW] Failed to save crash snapshot:",e)}}async function fr(){try{const s=await Et(),o=s.transaction(re,"readonly").objectStore(re).index("timestamp");return new Promise((r,n)=>{const a=o.getAll();a.onsuccess=()=>{s.close();const i=a.result.sort((c,l)=>l.timestamp-c.timestamp);r(i)},a.onerror=()=>{s.close(),n(a.error)}})}catch(s){return console.warn("[SW] Failed to get crash snapshots:",s),[]}}async function gr(){try{const s=await Et(),e=s.transaction(re,"readwrite");e.objectStore(re).clear(),await new Promise((o,r)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),r(e.error)}})}catch(s){console.warn("[SW] Failed to clear crash snapshots:",s)}}const pr=["ConsoleLogDB","ServiceWorkerDB","sw-task-queue","aitu-workspace","drawnix-unified-cache","drawnix-kv-storage","drawnix-prompts","drawnix-chat-db","MemorySnapshotDB"];function mr(s){try{const e=JSON.stringify(s);return new Blob([e]).size}catch{return 0}}async function wr(s){return new Promise(e=>{try{const t=indexedDB.open(s);t.onerror=()=>e({count:0,totalSize:0}),t.onsuccess=()=>{const o=t.result,r=Array.from(o.objectStoreNames);if(r.length===0){o.close(),e({count:0,totalSize:0});return}let n=0,a=0,i=0,c=0;const l=10;try{const u=o.transaction(r,"readonly");for(const p of r){const w=u.objectStore(p),m=w.count();m.onsuccess=()=>{const d=m.result;if(n+=d,d>0){const y=w.openCursor();let S=0;y.onsuccess=h=>{const f=h.target.result;if(f&&S<l)a+=mr(f.value),i++,S++,f.continue();else if(c++,c===r.length){o.close();const g=i>0?a/i:0,T=Math.round(g*n);e({count:n,totalSize:T})}},y.onerror=()=>{if(c++,c===r.length){o.close();const h=i>0?a/i:0,f=Math.round(h*n);e({count:n,totalSize:f})}}}else c++,c===r.length&&(o.close(),e({count:n,totalSize:0}))},m.onerror=()=>{if(c++,c===r.length){o.close();const d=i>0?a/i:0,y=Math.round(d*n);e({count:n,totalSize:y})}}}}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 yr(){const s={},e=[qe,M,ye,$e];for(const t of e)try{const o=await caches.open(t),r=await o.keys();let n=0;const a=Math.min(r.length,100);let i=0;for(let c=0;c<a;c++){const l=await o.match(r[c]);if(l){const u=l.headers.get("sw-image-size")||l.headers.get("content-length");u&&(i+=parseInt(u))}}a>0&&r.length>a?n=Math.round(i/a*r.length):n=i,s[t]={count:r.length,totalSize:n,type:"cache"}}catch{s[t]={count:0,totalSize:0,type:"cache"}}for(const t of pr)try{const o=await wr(t);o.count>0&&(s[`[IDB] ${t}`]={...o,type:"indexeddb"})}catch{}return s}async function Sr(s){try{await(await caches.open(M)).delete(s)}catch(e){throw console.error("Service Worker: Failed to delete cache entry:",s,e),e}}async function Tr(s){try{const e=await caches.open(M);let t=0;for(const o of s)try{await e.delete(o),t++}catch(r){console.warn("Service Worker: Failed to delete cache in batch:",o,r)}}catch(e){throw console.error("Service Worker: Failed to batch delete caches:",e),e}}async function Cr(){try{const s=await caches.open(M),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 ms(s,e,t){try{(await R.clients.matchAll()).forEach(r=>{r.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 Er(){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 R.clients.matchAll()).forEach(n=>{n.postMessage({type:"QUOTA_WARNING",usage:e,quota:t})}))}}catch(s){console.warn("Service Worker: Failed to check storage quota:",s)}}R.addEventListener("fetch",s=>{const e=new URL(s.request.url),t=Date.now();if(e.protocol!=="http:"&&e.protocol!=="https:"){H({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(Uo)){const o=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"cache-url",details:"Intercepting cache URL request"});s.respondWith(br(s.request).then(r=>(x(o,{status:r.status,statusText:r.statusText,responseType:r.type,duration:Date.now()-t,cached:r.status===200}),r)).catch(r=>{throw x(o,{error:String(r),duration:Date.now()-t}),r}));return}if(e.pathname.startsWith(Fo)){const o=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"asset-library",details:"Intercepting asset library request"});s.respondWith(Ar(s.request).then(r=>(x(o,{status:r.status,statusText:r.statusText,responseType:r.type,duration:Date.now()-t,cached:r.status===200}),r)).catch(r=>{throw x(o,{error:String(r),duration:Date.now()-t}),r}));return}if(e.hostname==="cdn.i666.fun"){H({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")){H({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")){H({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(Ko(e.hostname)){H({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(tr(e,s.request)){const o=Date.now(),r=s.request.headers.get("range"),n=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"video",headers:r?{range:r}:void 0,details:r?`Video Range request: ${r}`:"Video request"});s.respondWith(Rr(s.request).then(a=>(x(n,{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 x(n,{error:String(a),duration:Date.now()-o}),a}));return}if(sr(e,s.request)){const o=Date.now(),r=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"font",details:"Font request"});s.respondWith(_r(s.request).then(n=>(x(r,{status:n.status,statusText:n.statusText,responseType:n.type,duration:Date.now()-o,cached:n.headers.has("sw-cache-date")}),n)).catch(n=>{throw x(r,{error:String(n),duration:Date.now()-o}),n}));return}if(e.origin!==location.origin&&er(e,s.request)){const o=Date.now(),r=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"image",details:"External image request"});s.respondWith(Or(s.request).then(n=>(x(r,{status:n.status,statusText:n.statusText,responseType:n.type,duration:Date.now()-o,cached:n.headers.has("sw-cache-date"),size:parseInt(n.headers.get("content-length")||"0")}),n)).catch(n=>{throw x(r,{error:String(n),duration:Date.now()-o}),n}));return}if(s.request.method==="GET"){const o=s.request.mode==="navigate",r=s.request.destination!=="";if(o||r){const n=Date.now(),a=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"static",details:o?"Navigation request":`Static resource (${s.request.destination})`});s.respondWith(Dr(s.request).then(i=>(x(a,{status:i.status,statusText:i.statusText,responseType:i.type,duration:Date.now()-n}),i)).catch(i=>{throw x(a,{error:String(i),duration:Date.now()-n}),i}));return}}if($){const o=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"xhr",details:`XHR/API request (${s.request.method})`});s.respondWith((async()=>{try{const r=s.request.clone();let n,a={};if(s.request.headers.forEach((p,w)=>{a[w]=p}),["POST","PUT","PATCH"].includes(s.request.method))try{const p=s.request.headers.get("content-type")||"";p.includes("application/json")?(n=await r.text(),n.length>2e3&&(n=n.substring(0,2e3)+"... (truncated)")):p.includes("application/x-www-form-urlencoded")?(n=await r.text(),n.length>2e3&&(n=n.substring(0,2e3)+"... (truncated)")):n=`[${p||"binary data"}]`}catch{n="[unable to read body]"}x(o,{headers:a,details:n?`XHR/API request (${s.request.method})
4
+ `),t.trim()}function So(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,(r,n,a)=>`: "${n}\\n${a}"`),e=e.replace(/'([^']*?)'/g,(r,n)=>!n.includes(":")||n.length>50?`"${n}"`:r),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 To(s){return wo(s).map(t=>({...t,status:"pending"}))}class Co{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 E.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 E.saveChatWorkflow(e)}updateConfig(e){this.config={...this.config,...e}}async startWorkflow(e,t,o){const r=this.workflows.get(e);if(r){if(r.status==="streaming"||r.status==="pending"||r.status==="executing_tools"){this.broadcastStatus(r);return}console.warn("[SW-ChatWorkflow] Workflow already exists, skipping:",{chatId:e,status:r.status}),this.broadcastStatus(r);return}this.workflowClients.set(e,o);const n={id:e,status:"pending",params:t,content:"",toolCalls:[],createdAt:Date.now(),updatedAt:Date.now()};this.workflows.set(e,n),await E.saveChatWorkflow(n);const a=new AbortController;this.abortControllers.set(e,a),this.executeWorkflow(n,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 E.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 E.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 E.saveChatWorkflow(e),this.broadcastStatus(e);const r=To(o),n=yo(o);e.toolCalls=r,e.aiAnalysis=n,r.length>0&&this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_CALLS",chatId:e.id,aiAnalysis:n,toolCalls:r}),r.length>0&&(e.status="executing_tools",await E.saveChatWorkflow(e),this.broadcastStatus(e),await this.executeTools(e,t)),e.status="completed",e.completedAt=Date.now(),e.updatedAt=Date.now(),await E.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 E.saveChatWorkflow(e)}finally{this.abortControllers.delete(e.id)}}async streamChat(e,t){var d,y,S,h,f,m;const{params:o}=e,{geminiConfig:r}=this.config,n=this.convertToGeminiMessages(o),a=o.temporaryModel||r.modelName||"gemini-2.5-flash",i={model:a,messages:n,stream:!0},{debugFetch:c}=await Promise.resolve().then(()=>N),l=await c(`${r.baseUrl}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${r.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 u=l.body.getReader(),g=new TextDecoder;let w="",p="";try{for(;;){const{done:T,value:_}=await u.read();if(T)break;p+=g.decode(_,{stream:!0});const C=p.split(`
5
+ `);p=C.pop()||"";for(const A of C)if(A.startsWith("data: ")){const b=A.slice(6).trim();if(b==="[DONE]")continue;try{const Z=(S=(y=(d=JSON.parse(b).choices)==null?void 0:d[0])==null?void 0:y.delta)==null?void 0:S.content;Z&&(w+=Z,this.config.broadcast({type:"CHAT_WORKFLOW_STREAM",chatId:e.id,content:w}))}catch{}}}if(p.startsWith("data: ")){const T=p.slice(6).trim();if(T&&T!=="[DONE]")try{const C=(m=(f=(h=JSON.parse(T).choices)==null?void 0:h[0])==null?void 0:f.delta)==null?void 0:m.content;C&&(w+=C,this.config.broadcast({type:"CHAT_WORKFLOW_STREAM",chatId:e.id,content:w}))}catch{}}}finally{u.releaseLock()}if(l.__debugLogId&&w){const{updateLogResponseBody:T}=await Promise.resolve().then(()=>N);T(l.__debugLogId,w)}return w}async executeTools(e,t){const o=this.workflowClients.get(e.id);for(const r of e.toolCalls){if(t.aborted)throw new Error("Workflow cancelled");r.status="running",this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_START",chatId:e.id,toolCallId:r.id,toolName:r.name});try{let n;if(dt(r.name)||!Jt(r.name)){if(!o)throw new Error("No client ID found for workflow");const a=await this.config.requestMainThreadTool(o,e.id,r.id,r.name,r.arguments);n={success:a.success,data:a.result,error:a.error}}else{const a={geminiConfig:this.config.geminiConfig,videoConfig:this.config.videoConfig,signal:t},i=await ut(r.name,r.arguments,a);n={success:i.success,data:i.data,error:i.error,taskId:i.taskId}}r.status=n.success?"completed":"failed",r.result=n,await E.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_COMPLETE",chatId:e.id,toolCallId:r.id,success:n.success,result:n.data,error:n.error,taskId:n.taskId})}catch(n){r.status="failed",r.result={success:!1,error:n.message},await E.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_COMPLETE",chatId:e.id,toolCallId:r.id,success:!1,error:n.message})}}}convertToGeminiMessages(e){var o;const t=[];e.systemPrompt&&t.push({role:"system",content:[{type:"text",text:e.systemPrompt}]});for(const r of e.messages){const n=[];if(r.content&&n.push({type:"text",text:r.content}),r.attachments)for(const a of r.attachments)a.type==="image"&&n.push({type:"image_url",image_url:{url:`data:${a.mimeType};base64,${a.data}`}});t.push({role:r.role,content:n})}if(e.newContent||(o=e.attachments)!=null&&o.length){const r=[];if(e.newContent&&r.push({type:"text",text:e.newContent}),e.attachments)for(const n of e.attachments)n.type==="image"&&r.push({type:"image_url",image_url:{url:`data:${n.mimeType};base64,${n.data}`}});t.push({role:"user",content:r})}return t}broadcastStatus(e){this.config.broadcast({type:"CHAT_WORKFLOW_STATUS",chatId:e.id,status:e.status,updatedAt:e.updatedAt})}}let P=null,V=null,fe=null,ge=null;function ht(s,e,t){fe=e,ge=t,P=new po({geminiConfig:e,videoConfig:t,broadcast:r=>me(r)});const o=lt();o&&o.setTaskStatusChangeCallback((r,n,a,i)=>{P==null||P.updateWorkflowStepForTask(r,n,a,i)}),V=new Co({geminiConfig:e,videoConfig:t,broadcast:r=>me(r),sendToClient:(r,n)=>gt(r,n),requestMainThreadTool:async(r,n,a,i,c)=>{const l=`chat_tool_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return new Promise((u,g)=>{const w=setTimeout(()=>{pe.delete(l),E.deletePendingToolRequest(l),g(new Error(`Tool request timed out: ${i}`))},3e5);pe.set(l,{resolve:p=>{clearTimeout(w),E.deletePendingToolRequest(l),u(p)},reject:p=>{clearTimeout(w),E.deletePendingToolRequest(l),g(p)},requestInfo:{requestId:l,chatId:n,toolCallId:a,toolName:i,args:c,clientId:r},timeout:w}),E.savePendingToolRequest({requestId:l,workflowId:n,stepId:a,toolName:i,args:c,createdAt:Date.now(),clientId:r}),gt(r,{type:"MAIN_THREAD_TOOL_REQUEST",requestId:l,workflowId:n,stepId:a,toolName:i,args:c})})}})}const pe=new Map;function Eo(s,e){if(!P){console.warn("[WorkflowHandler] Not initialized");return}s&&(fe={...fe||{},...s}),e&&(ge={...ge||{},...e}),!(!fe||!ge)&&(P.updateConfig({geminiConfig:fe,videoConfig:ge}),V&&V.updateConfig({geminiConfig:fe,videoConfig:ge}))}function _o(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 ft(s,e){if(s.type.startsWith("CHAT_WORKFLOW_")){bo(s,e);return}if(!P){console.error("[WorkflowHandler] ✗ Not initialized, ignoring message:",s.type);return}const t=s;switch(t.type){case"WORKFLOW_SUBMIT":P.submitWorkflow(t.workflow);break;case"WORKFLOW_CANCEL":P.cancelWorkflow(t.workflowId);break;case"WORKFLOW_GET_STATUS":{const o=P.getWorkflow(t.workflowId);me({type:"WORKFLOW_STATUS_RESPONSE",workflowId:t.workflowId,workflow:o||null});break}case"WORKFLOW_GET_ALL":{const o=P.getAllWorkflows();me({type:"WORKFLOW_ALL_RESPONSE",workflows:o});break}}}function bo(s,e){if(!V){console.error("[WorkflowHandler] ✗ Chat workflow handler not initialized");return}switch(s.type){case"CHAT_WORKFLOW_START":V.startWorkflow(s.chatId,s.params,e);break;case"CHAT_WORKFLOW_CANCEL":V.cancelWorkflow(s.chatId);break;case"CHAT_WORKFLOW_GET_STATUS":{const t=V.getWorkflow(s.chatId);me({type:"CHAT_WORKFLOW_STATUS_RESPONSE",chatId:s.chatId,workflow:t||null});break}case"CHAT_WORKFLOW_GET_ALL":{const t=V.getAllWorkflows();me({type:"CHAT_WORKFLOW_ALL_RESPONSE",workflows:t});break}}}async function Ao(s){const e=pe.get(s.requestId);if(e){pe.delete(s.requestId),e.resolve(s);return}if(await E.deletePendingToolRequest(s.requestId),!P){console.error("[WorkflowHandler] ✗ Not initialized, ignoring tool response");return}P.handleMainThreadToolResponse(s)}function Ro(){if(P&&(P.broadcastRecoveredWorkflows(),P.resendPendingToolRequests()),V&&V.broadcastRecoveredWorkflows(),pe.size!==0)for(const[,s]of pe){const{requestInfo:e}=s;gt(e.clientId,{type:"MAIN_THREAD_TOOL_REQUEST",requestId:e.requestId,workflowId:e.chatId,stepId:e.toolCallId,toolName:e.toolName,args:e.args})}}function me(s){Nt(s)}async function gt(s,e){await ve(s,e)||Nt(e)}const De=[],Do=100;let pt=!1,te=null;function Lo(s){pt=s}function mt(){return pt}function es(s){te=s}function ts(){return[...De]}function Io(s,e){const t=De.find(o=>o.id===s);t&&(t.responseBody=e.length>5e3?e.substring(0,5e3)+"...(truncated)":e,te&&te({...t}))}async function Oo(s){return new Promise((e,t)=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.onerror=t,o.readAsDataURL(s)})}async function Wo(s){const e=[];for(const[t,o]of s.entries())if(o instanceof Blob){const r={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{r.dataUrl=await Oo(o)}catch{}o instanceof File&&(r.fileName=o.name),e.push(r)}else e.push({name:t,value:String(o).length>500?String(o).substring(0,500)+"...":String(o)});return e}async function ko(s,e,t){if(!pt)return fetch(s,e);const o=typeof s=="string"?s:s instanceof URL?s.href:s.url,r=(e==null?void 0:e.method)||"GET",n=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 Wo(e.body)}catch{i="[FormData - unable to parse]"}else if(t!=null&&t.logRequestBody)try{const g=typeof e.body=="string"?e.body:JSON.stringify(e.body),w=/data:image\/([^;]+);base64,([A-Za-z0-9+/=]+)/g;let p,d=0;for(l=[];(p=w.exec(g))!==null;){const h=`image/${p[1]}`,f=p[2];f.length>1e3&&(l.push({key:`image[${d}]`,dataUrl:`data:${h};base64,${f}`,mimeType:h,size:Math.round(f.length*.75/1024)}),d++)}l.length===0&&(l=void 0);let y=g.replace(/data:image\/([^;]+);base64,[A-Za-z0-9+/=]+/g,(h,f)=>`[📷 image/${f}]`);y=Dt(y),i=!o.includes("/chat/completions")&&y.length>3e3?y.substring(0,3e3)+"...(truncated)":y}catch{i="[unable to serialize body]"}}const u={id:a,timestamp:n,url:o,method:r,requestType:"sw-internal",details:(t==null?void 0:t.label)||`SW Internal: ${r} ${new URL(o).pathname}`,requestBody:i,formData:c,base64Images:l,isStreaming:t==null?void 0:t.isStreaming};De.unshift(u),De.length>Do&&De.pop(),te&&te({...u});try{const g=await fetch(s,e);if(u.status=g.status,u.statusText=g.statusText,u.duration=Date.now()-n,t!=null&&t.isStreaming)u.responseBody="[流式响应 - 数据通过 SSE/Stream 实时传输,无法捕获完整响应体]";else if(t!=null&&t.logResponseBody)try{const w=g.headers.get("content-type")||"";if(w.includes("application/json")||w.includes("text/")){const d=await g.clone().text();u.responseBody=d.length>2e3?d.substring(0,2e3)+"...(truncated)":d}}catch{}return te&&te({...u}),g.__debugLogId=a,g}catch(g){const w=g.message||String(g);let p="NETWORK_ERROR";throw w.includes("ERR_CONNECTION_CLOSED")?p="ERR_CONNECTION_CLOSED":w.includes("ERR_CONNECTION_REFUSED")?p="ERR_CONNECTION_REFUSED":w.includes("ERR_CONNECTION_RESET")?p="ERR_CONNECTION_RESET":w.includes("ERR_CONNECTION_TIMED_OUT")||w.includes("timeout")?p="ERR_TIMEOUT":w.includes("ERR_NAME_NOT_RESOLVED")?p="ERR_DNS_FAILED":w.includes("ERR_INTERNET_DISCONNECTED")?p="ERR_OFFLINE":w.includes("ERR_SSL")||w.includes("certificate")?p="ERR_SSL":w.includes("Failed to fetch")?p="FETCH_FAILED":(w.includes("AbortError")||w.includes("aborted"))&&(p="ABORTED"),u.status=0,u.statusText=p,u.error=w,u.duration=Date.now()-n,te&&te({...u}),g}}const N=Object.freeze(Object.defineProperty({__proto__:null,debugFetch:ko,getInternalFetchLogs:ts,isDebugFetchEnabled:mt,setDebugFetchBroadcast:es,setDebugFetchEnabled:Lo,updateLogResponseBody:Io},Symbol.toStringTag,{value:"Module"})),Po=typeof location<"u"&&(location.hostname==="localhost"||location.hostname==="127.0.0.1"),wt={degradeTimeout:60*1e3,failThreshold:3,fetchTimeout:1500},yt=[{name:"unpkg",urlTemplate:"https://unpkg.com/aitu-app@{version}/{path}",healthCheckPath:"version.json",enabled:!0,priority:1},{name:"jsdelivr",urlTemplate:"https://cdn.jsdelivr.net/npm/aitu-app@{version}/{path}",healthCheckPath:"version.json",enabled:!0,priority:2}],we=new Map;function ss(){yt.forEach(s=>{we.has(s.name)||we.set(s.name,{name:s.name,isHealthy:!0,lastCheckTime:0,failCount:0,lastSuccessTime:Date.now()})})}ss();function os(s){const e=we.get(s);e&&(e.isHealthy=!0,e.failCount=0,e.lastSuccessTime=Date.now(),e.lastCheckTime=Date.now())}function ie(s){const e=we.get(s);e&&(e.failCount++,e.lastCheckTime=Date.now(),e.failCount>=wt.failThreshold&&(e.isHealthy=!1,console.warn(`[CDN Fallback] ${s} marked as unhealthy after ${e.failCount} failures`)))}function Mo(s){const e=we.get(s);return e?e.isHealthy?!0:Date.now()-e.lastCheckTime>wt.degradeTimeout?(console.log(`[CDN Fallback] Trying to recover ${s}...`),!0):!1:!1}function xo(){return yt.filter(s=>s.enabled&&Mo(s.name)).sort((s,e)=>s.priority-e.priority)}function rs(s){const e=/^\/?(aitu-app@[\d.]+\/)/;return s.replace(e,"/")}function ns(s,e,t){const o=rs(t);return s.urlTemplate.replace("{version}",e).replace("{path}",o.startsWith("/")?o.slice(1):o)}async function St(s,e=wt.fetchTimeout){const t=new AbortController,o=setTimeout(()=>t.abort(),e);try{return await fetch(s,{signal:t.signal,cache:"no-store"})}finally{clearTimeout(o)}}async function vo(s,e,t){if(Po)return console.log("[CDN Fallback] 开发模式,跳过 CDN 回退"),null;const o=xo();for(const r of o){const n=ns(r,e,s);try{console.log(`[CDN Fallback] Trying ${r.name}: ${n}`);const a=await St(n);if(a.ok){const i=a.headers.get("Content-Type")||"";if(!(i.includes("javascript")||i.includes("css")||i.includes("json")||i.includes("font")||i.includes("image")||i.includes("woff")||i.includes("application/octet-stream"))){console.warn(`[CDN Fallback] ${r.name} invalid Content-Type: ${i}`),ie(r.name);continue}const l=parseInt(a.headers.get("Content-Length")||"0",10),u=i.includes("javascript")||i.includes("css")||i.includes("json");if(u&&l>0&&l<50){console.warn(`[CDN Fallback] ${r.name} response too small: ${l} bytes`),ie(r.name);continue}const g=a.clone();try{const w=await g.text().then(d=>d.slice(0,200)),p=w.includes("<!DOCTYPE")||w.includes("<html")||w.includes("<HTML")||w.includes("Not Found")||w.includes("404");if(u&&p){console.warn(`[CDN Fallback] ${r.name} returned HTML instead of ${i}`),ie(r.name);continue}}catch{}return os(r.name),console.log(`[CDN Fallback] Success from ${r.name}`),{response:a,source:r.name}}else console.warn(`[CDN Fallback] ${r.name} returned ${a.status}`),ie(r.name)}catch(a){console.warn(`[CDN Fallback] ${r.name} failed:`,a),ie(r.name)}}try{const r=rs(s),n=`${t}/${r.startsWith("/")?r.slice(1):r}`;console.log(`[CDN Fallback] Trying local server: ${n}`);const a=await St(n);if(a.ok)return console.log("[CDN Fallback] Success from local server"),{response:a,source:"local"}}catch(r){console.warn("[CDN Fallback] Local server failed:",r)}return console.error(`[CDN Fallback] All sources failed for: ${s}`),null}async function No(s){const e=new Map;for(const t of yt){if(!t.enabled)continue;const o=ns(t,s,t.healthCheckPath);try{const n=(await St(o,5e3)).ok;e.set(t.name,n),n?os(t.name):ie(t.name)}catch{e.set(t.name,!1),ie(t.name)}}return e}function Bo(){return Array.from(we.entries()).map(([s,e])=>({name:s,status:e}))}function Uo(){ss(),console.log("[CDN Fallback] All CDN status reset")}const D=self;uo(D),Xs();const ce={log:console.log.bind(console),info:console.info.bind(console),warn:console.warn.bind(console),error:console.error.bind(console)};function Fo(){console.log=(...s)=>{ce.log(...s),mt()&&Fe("log",s)},console.info=(...s)=>{ce.info(...s),mt()&&Fe("info",s)},console.warn=(...s)=>{ce.warn(...s),Fe("warn",s)},console.error=(...s)=>{ce.error(...s),Fe("error",s)}}function Fe(s,e){const t=e.map(r=>{if(typeof r=="object")try{return JSON.stringify(r)}catch{return String(r)}return String(r)}).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;Fo(),es(s=>{D.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_DEBUG_LOG",entry:{...s,type:"fetch"}})})})}),Promise.resolve().then(()=>O).then(({setLLMApiLogBroadcast:s})=>{s(e=>{D.clients.matchAll().then(t=>{t.forEach(o=>{o.postMessage({type:"SW_DEBUG_LLM_API_LOG",log:e})})})})});const Q="0.5.49",qe=`drawnix-v${Q}`,M="drawnix-images",ye=`drawnix-static-v${Q}`,$e="drawnix-fonts",qo="/__aitu_cache__/",$o="/asset-library/",as=location.hostname==="localhost"||location.hostname==="127.0.0.1",Go=[{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"}],Ho=/\.(jpg|jpeg|png|gif|webp|svg|bmp|ico)$/i,zo=/\.(mp4|webm|ogg|mov|avi|mkv|flv|wmv|m4v)$/i,G=new Map,le=new Map,is=30*1e3,Le=new Map,q=new Map,Ko=300*1e3,cs=10,Se=new Set,Te=new Set,jo=3600*1e3,Ct=new Map;function ls(s){Te.add(s),Ct.set(s,Date.now()),console.warn(`Service Worker: 标记 ${s} 为 CORS 问题域名,后续请求将跳过 SW`)}function Vo(s){if(!Te.has(s))return!1;const e=Ct.get(s);return e&&Date.now()-e>jo?(Te.delete(s),Ct.delete(s),!1):!0}const Ie=[],Qo=7,J=[],Jo=500;let $=!1,Ce=0;const Xo=15e3;let X=null;function us(){if(!$)return;const s=Date.now();Ce>0&&s-Ce>Xo?(ce.log("Service Worker: Debug heartbeat timeout, auto-disabling debug mode"),$=!1,Ce=0,Ye(!1),Promise.resolve().then(()=>N).then(({setDebugFetchEnabled:e})=>{e(!1)}),D.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_DEBUG_DISABLED"})})}),X&&(clearTimeout(X),X=null)):$&&(X=setTimeout(us,5e3))}function H(s){if(!$)return"";const e=Math.random().toString(36).substring(2,10),t={...s,id:e,timestamp:Date.now()};return J.unshift(t),J.length>Jo&&J.pop(),ds(t),e}function v(s,e){if(!$||!s)return;const t=J.find(o=>o.id===s);t&&(Object.assign(t,e),ds(t))}async function ds(s){try{(await D.clients.matchAll()).forEach(t=>{t.postMessage({type:"SW_DEBUG_LOG",entry:s})})}catch{}}function Ge(){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 r=o.target.result;if(!r.objectStoreNames.contains("logs")){const n=r.createObjectStore("logs",{keyPath:"id"});n.createIndex("timestamp","timestamp",{unique:!1}),n.createIndex("logLevel","logLevel",{unique:!1})}}})}async function Yo(s){try{const e=await Ge(),t=e.transaction(["logs"],"readwrite");return t.objectStore("logs").add(s),new Promise((r,n)=>{t.oncomplete=()=>{e.close(),r()},t.onerror=()=>{e.close(),n(t.error)}})}catch(e){console.warn("Service Worker: 无法保存控制台日志:",e)}}async function hs(){try{const s=await Ge(),o=s.transaction(["logs"],"readonly").objectStore("logs").index("timestamp");return new Promise((r,n)=>{const a=o.openCursor(null,"prev"),i=[];a.onsuccess=()=>{const c=a.result;c?(i.push(c.value),c.continue()):(s.close(),r(i))},a.onerror=()=>{s.close(),n(a.error)}})}catch(s){return console.warn("Service Worker: 无法加载控制台日志:",s),[]}}async function Zo(){try{const s=await Ge(),o=s.transaction(["logs"],"readwrite").objectStore("logs").index("timestamp"),r=Date.now()-Qo*24*60*60*1e3,n=IDBKeyRange.upperBound(r);return new Promise((a,i)=>{const c=o.openCursor(n);let l=0;c.onsuccess=()=>{const u=c.result;u?(u.delete(),l++,u.continue()):(s.close(),l>0,a(l))},c.onerror=()=>{s.close(),i(c.error)}})}catch(s){return console.warn("Service Worker: 无法清理过期日志:",s),0}}async function fs(){try{const s=await Ge(),e=s.transaction(["logs"],"readwrite");return e.objectStore("logs").clear(),new Promise((o,r)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),r(e.error)}})}catch(s){console.warn("Service Worker: 无法清空控制台日志:",s)}}function gs(s){if(!$)return;const t={id:Math.random().toString(36).substring(2,10),timestamp:Date.now(),type:"console",...s};Ie.unshift(t),Yo(t),er(t)}Tt=gs;async function er(s){try{(await D.clients.matchAll()).forEach(t=>{t.postMessage({type:"SW_CONSOLE_LOG",entry:s})})}catch{}}function tr(){let s=0;return q.forEach(e=>{e.blob&&(s+=e.blob.size)}),s}function He(){return{version:Q,cacheNames:[qe,M,ye,$e],pendingImageRequests:G.size,pendingVideoRequests:Le.size,videoBlobCacheSize:q.size,videoBlobCacheTotalBytes:tr(),completedImageRequestsSize:le.size,failedDomainsCount:Se.size,failedDomains:Array.from(Se),corsFailedDomainsCount:Te.size,corsFailedDomains:Array.from(Te),debugLogsCount:J.length,consoleLogsCount:Ie.length,debugModeEnabled:$,workflowHandlerInitialized:ue,memoryStats:{pendingRequestsMapSize:G.size,completedRequestsMapSize:le.size,videoBlobCacheMapSize:q.size,failedDomainsSetSize:Se.size,corsFailedDomainsSetSize:Te.size,debugLogsArraySize:J.length,consoleLogsArraySize:Ie.length}}}function ps(s){for(const e of Go)if(s.hostname===e.hostname&&s.pathname.includes(e.pathPattern))return e;return null}function sr(s,e){return Ho.test(s.pathname)||e.destination==="image"||ps(s)!==null}function or(s,e){return zo.test(s.pathname)||e.destination==="video"||s.pathname.includes("/video/")||s.hash.startsWith("#merged-video-")||s.hash.includes("video")}function rr(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 nr(){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=>Se.add(c.domain)),e()},a.onerror=()=>t(a.error)}else e()},s.onupgradeneeded=o=>{const r=o.target.result;r.objectStoreNames.contains("failedDomains")||r.createObjectStore("failedDomains",{keyPath:"domain"})}})}catch(s){console.warn("Service Worker: 无法加载失败域名列表:",s)}}async function ar(s){try{const e=indexedDB.open("ServiceWorkerDB",1);return new Promise((t,o)=>{e.onerror=()=>o(e.error),e.onsuccess=()=>{const n=e.result.transaction(["failedDomains"],"readwrite");n.objectStore("failedDomains").put({domain:s,timestamp:Date.now()}),n.oncomplete=()=>{t()},n.onerror=()=>o(n.error)},e.onupgradeneeded=r=>{const n=r.target.result;n.objectStoreNames.contains("failedDomains")||n.createObjectStore("failedDomains",{keyPath:"domain"})}})}catch(e){console.warn("Service Worker: 无法保存失败域名:",e)}}async function ir(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 r=0,n=0;for(let a=0;a<o&&a<t.length;a++)try{await s.delete(t[a].request),r++,n+=t[a].imageSize}catch(i){console.warn("Service Worker: Error deleting cache entry:",i)}}catch(e){console.warn("Service Worker: Cache cleanup failed:",e)}}async function cr(){try{const s=await fetch("./precache-manifest.json",{cache:"reload"});if(!s.ok)return console.log("Service Worker: No precache-manifest.json found (dev mode), skipping precache"),null;const e=await s.json();return console.log(`Service Worker: Loaded precache manifest v${e.version} with ${e.files.length} files`),e.files}catch{return console.log("Service Worker: Cannot load precache-manifest.json, skipping precache"),null}}async function lr(s,e,t){try{const o=await s.match(e);if(o&&o.headers.get("x-sw-revision")===t)return{url:e,success:!0,skipped:!0};const r=e.endsWith(".html")||e==="/";let n=null,a="server";if(!r){const i=await vo(e.startsWith("/")?e.slice(1):e,Q,location.origin);i&&i.response.ok&&(n=i.response,a=i.source)}if(n||(n=await fetch(e,{cache:"reload"}),a="server"),n.ok){const i=new Headers(n.headers);i.set("x-sw-revision",t),i.set("x-sw-cached-at",new Date().toISOString()),i.set("x-sw-source",a);const c=new Response(await n.blob(),{status:n.status,statusText:n.statusText,headers:i}),l=new URL(e,self.location.origin).href;return await s.put(l,c),{url:e,success:!0,source:a}}return{url:e,success:!1,status:n.status}}catch(o){return{url:e,success:!1,error:String(o)}}}async function ur(s,e){const o=[];for(let c=0;c<e.length;c+=6){const l=e.slice(c,c+6),u=await Promise.allSettled(l.map(({url:g,revision:w})=>lr(s,g,w)));for(const g of u)g.status==="fulfilled"?o.push({success:g.value.success,source:g.value.source}):o.push({success:!1})}const r=o.filter(c=>c.success).length,n=o.length-r,a=o.filter(c=>c.success&&c.source&&c.source!=="server").length,i=o.filter(c=>c.success&&c.source==="server").length;console.log(`Service Worker: Precached ${r}/${e.length} files (${n} failed)`),a>0&&console.log(`Service Worker: Sources - CDN: ${a}, Server: ${i}`)}D.addEventListener("install",s=>{console.log(`Service Worker v${Q} installing...`);const e=[];e.push(nr()),e.push((async()=>{try{const t=await cr();if(t&&t.length>0){const o=await caches.open(ye);await ur(o,t)}}catch(t){console.warn("Service Worker: Precache failed:",t)}})()),s.waitUntil(Promise.all(e).then(async()=>{console.log(`Service Worker v${Q} installed, resources ready`);const t=await caches.keys();t.some(o=>o.startsWith("drawnix-static-v")&&o!==ye),t.some(o=>o.startsWith("drawnix-v")&&o!==qe&&o!==M&&!o.startsWith("drawnix-static-v")),D.skipWaiting()}))}),D.addEventListener("activate",s=>{s.waitUntil(caches.keys().then(async e=>{const t=e.filter(a=>a.startsWith("drawnix-images-v")&&a!==M);if(t.length>0){const a=await caches.open(M);for(const i of t)try{const c=await caches.open(i),l=await c.keys();for(const u of l){const g=await c.match(u);g&&await a.put(u,g)}await caches.delete(i)}catch(c){console.warn(`Failed to migrate cache ${i}:`,c)}}const o=e.filter(a=>a.startsWith("drawnix-static-v")&&a!==ye),r=e.filter(a=>a.startsWith("drawnix-v")&&a!==qe&&a!==M&&!a.startsWith("drawnix-static-v"));(o.length>0||r.length>0)&&setTimeout(async()=>{for(const a of[...o,...r])try{await caches.delete(a)}catch(i){console.warn("Failed to delete old cache:",a,i)}},3e4),Zo().catch(a=>{console.warn("Failed to cleanup expired console logs:",a)}),await D.clients.claim(),(await D.clients.matchAll()).forEach(a=>{a.postMessage({type:"SW_ACTIVATED",version:Q})})}))});const dr=["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 hr(s){if(!s||typeof s!="object")return!1;const e=s;return e.type?dr.includes(e.type):!1}let ue=!1,Ee=null,_e=null;const ze=[];function ms(s){$&&D.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_POSTMESSAGE_LOG",entry:s})})})}Js(ms),D.addEventListener("message",s=>{var r,n,a,i,c,l,u,g,w,p,d,y,S;const e=((r=s.data)==null?void 0:r.type)||"unknown",t=((n=s.source)==null?void 0:n.id)||"";let o="";if(Je()&&(o=zs(e,s.data,t),o&&$)){const f=Re().find(m=>m.id===o);f&&ms(f)}if(s.data&&hr(s.data)){const h=((a=s.source)==null?void 0:a.id)||"";if(ho(s.data,h),s.data.type==="TASK_QUEUE_INIT"){const{geminiConfig:f,videoConfig:m}=s.data;if(Ee=f,_e=m,!ue&&(ht(D,f,m),ue=!0,ze.length>0)){for(const T of ze)ft(T.message,T.clientId);ze.length=0}Ro()}if(s.data.type==="TASK_QUEUE_UPDATE_CONFIG"){const{geminiConfig:f,videoConfig:m}=s.data;f&&(Ee={...Ee,...f}),m&&(_e={..._e,...m}),Eo(f,m)}return}if(s.data&&_o(s.data)){const h=((i=s.source)==null?void 0:i.id)||"";if(!ue&&Ee&&_e&&(ht(D,Ee,_e),ue=!0),!ue){(async()=>{try{const{geminiConfig:f,videoConfig:m}=await E.loadConfig();if(f&&m)Ee=f,_e=m,ht(D,f,m),ue=!0,ft(s.data,h);else{const T=await D.clients.matchAll({type:"window"});for(const _ of T)_.postMessage({type:"SW_REQUEST_CONFIG",reason:"workflow_handler_not_initialized",pendingMessageType:s.data.type});ze.push({message:s.data,clientId:h})}}catch(f){console.error("[SW] Failed to load config from storage:",Ve(f))}})();return}ft(s.data,h);return}if(s.data&&s.data.type==="MAIN_THREAD_TOOL_RESPONSE"){Ao(s.data);return}if(s.data&&s.data.type==="SKIP_WAITING")D.skipWaiting(),D.clients.matchAll().then(h=>{h.forEach(f=>{f.postMessage({type:"SW_UPDATED"})})});else if(s.data&&s.data.type==="GET_UPGRADE_STATUS")(c=s.source)==null||c.postMessage({type:"UPGRADE_STATUS",version:Q});else if(s.data&&s.data.type==="FORCE_UPGRADE")D.skipWaiting(),D.clients.matchAll().then(h=>{h.forEach(f=>{f.postMessage({type:"SW_UPDATED"})})});else if(s.data&&s.data.type==="DELETE_CACHE"){const{url:h}=s.data;h&&Cr(h).then(()=>{D.clients.matchAll().then(f=>{f.forEach(m=>{m.postMessage({type:"CACHE_DELETED",url:h})})})}).catch(f=>{console.error("Service Worker: Failed to delete cache:",f)})}else if(s.data&&s.data.type==="DELETE_CACHE_BATCH"){const{urls:h}=s.data;h&&Array.isArray(h)&&Er(h).then(()=>{}).catch(f=>{console.error("Service Worker: Failed to batch delete caches:",f)})}else if(s.data&&s.data.type==="CLEAR_ALL_CACHE")_r().then(()=>{}).catch(h=>{console.error("Service Worker: Failed to clear all cache:",h)});else if(s.data&&s.data.type==="SW_DEBUG_ENABLE")$=!0,Ce=Date.now(),Promise.resolve().then(()=>N).then(({setDebugFetchEnabled:h})=>{h(!0)}),Ye(!0),ce.log("Service Worker: Debug mode enabled"),X&&clearTimeout(X),X=setTimeout(us,5e3),D.clients.matchAll().then(h=>{h.forEach(f=>{f.postMessage({type:"SW_DEBUG_ENABLED"})})}),(l=s.source)==null||l.postMessage({type:"SW_DEBUG_STATUS",status:He()});else if(s.data&&s.data.type==="SW_DEBUG_HEARTBEAT")$&&(Ce=Date.now());else if(s.data&&s.data.type==="SW_DEBUG_DISABLE")$=!1,Ce=0,X&&(clearTimeout(X),X=null),Promise.resolve().then(()=>N).then(({setDebugFetchEnabled:h})=>{h(!1)}),Ye(!1),Ie.length=0,J.length=0,fs().catch(()=>{}),ce.log("Service Worker: Debug mode disabled, logs cleared"),D.clients.matchAll().then(h=>{h.forEach(f=>{f.postMessage({type:"SW_DEBUG_DISABLED"})})}),(u=s.source)==null||u.postMessage({type:"SW_DEBUG_STATUS",status:He()});else if(s.data&&s.data.type==="SW_DEBUG_GET_STATUS")(async()=>{var m;const h=He(),f=await Tr();(m=s.source)==null||m.postMessage({type:"SW_DEBUG_STATUS",status:{...h,cacheStats:f}})})();else if(s.data&&s.data.type==="SW_DEBUG_GET_LOGS"){const{limit:h=100,offset:f=0,filter:m}=s.data,T=ts().map(b=>({...b,type:"fetch"})),_=new Map;for(const b of J)_.set(b.id,b);for(const b of T)_.set(b.id,b);let C=Array.from(_.values()).sort((b,W)=>W.timestamp-b.timestamp);m&&(m.type&&(C=C.filter(b=>b.type===m.type)),m.requestType&&(C=C.filter(b=>b.requestType===m.requestType)),m.url&&(C=C.filter(b=>{var W;return(W=b.url)==null?void 0:W.includes(m.url)})),m.status&&(C=C.filter(b=>b.status===m.status)));const A=C.slice(f,f+h);(g=s.source)==null||g.postMessage({type:"SW_DEBUG_LOGS",logs:A,total:C.length,offset:f,limit:h})}else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_LOGS")J.length=0,(w=s.source)==null||w.postMessage({type:"SW_DEBUG_LOGS_CLEARED"});else if(s.data&&s.data.type==="SW_CDN_GET_STATUS")(p=s.source)==null||p.postMessage({type:"SW_CDN_STATUS",status:Bo()});else if(s.data&&s.data.type==="SW_CDN_RESET_STATUS")Uo(),(d=s.source)==null||d.postMessage({type:"SW_CDN_STATUS_RESET"});else if(s.data&&s.data.type==="SW_CDN_HEALTH_CHECK")(async()=>{var f;const h=await No(Q);(f=s.source)==null||f.postMessage({type:"SW_CDN_HEALTH_CHECK_RESULT",results:Object.fromEntries(h)})})();else if(s.data&&s.data.type==="SW_DEBUG_GET_CACHE_ENTRIES"){const{cacheName:h,limit:f=50,offset:m=0}=s.data;(async()=>{var T,_;try{const C=await caches.open(h||M),A=await C.keys(),b=[];for(let W=m;W<Math.min(m+f,A.length);W++){const Z=A[W],ee=await C.match(Z);if(ee){const We=ee.headers.get("sw-cache-date"),ke=ee.headers.get("sw-image-size")||ee.headers.get("content-length");b.push({url:Z.url,cacheDate:We?parseInt(We):void 0,size:ke?parseInt(ke):void 0})}}(T=s.source)==null||T.postMessage({type:"SW_DEBUG_CACHE_ENTRIES",cacheName:h||M,entries:b,total:A.length,offset:m,limit:f})}catch(C){(_=s.source)==null||_.postMessage({type:"SW_DEBUG_CACHE_ENTRIES",error:String(C)})}})()}else if(s.data&&s.data.type==="SW_CONSOLE_LOG_REPORT"){const{logLevel:h,logMessage:f,logStack:m,logSource:T,url:_}=s.data;gs({logLevel:h,logMessage:f,logStack:m,logSource:T,url:_})}else if(s.data&&s.data.type==="SW_DEBUG_GET_CONSOLE_LOGS")(async()=>{var h,f;try{const{limit:m=500,offset:T=0,filter:_}=s.data;let C=await hs();if(_&&(_.logLevel&&(C=C.filter(b=>b.logLevel===_.logLevel)),_.search)){const b=_.search.toLowerCase();C=C.filter(W=>{var Z,ee;return((Z=W.logMessage)==null?void 0:Z.toLowerCase().includes(b))||((ee=W.logStack)==null?void 0:ee.toLowerCase().includes(b))})}const A=C.slice(T,T+m);(h=s.source)==null||h.postMessage({type:"SW_DEBUG_CONSOLE_LOGS",logs:A,total:C.length,offset:T,limit:m})}catch(m){(f=s.source)==null||f.postMessage({type:"SW_DEBUG_CONSOLE_LOGS",logs:[],total:0,error:String(m)})}})();else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_CONSOLE_LOGS")(async()=>{var h;Ie.length=0,await fs(),(h=s.source)==null||h.postMessage({type:"SW_DEBUG_CONSOLE_LOGS_CLEARED"})})();else if(s.data&&s.data.type==="SW_DEBUG_EXPORT_LOGS")(async()=>{var T;const h=await hs(),f=Re(),m={exportTime:new Date().toISOString(),swVersion:Q,userAgent:"",status:He(),fetchLogs:J,consoleLogs:h,postmessageLogs:f};(T=s.source)==null||T.postMessage({type:"SW_DEBUG_EXPORT_DATA",data:m})})();else if(s.data&&s.data.type==="SW_DEBUG_GET_POSTMESSAGE_LOGS"){const{limit:h=200,offset:f=0,filter:m}=s.data;let T=Re();if(m&&(m.direction&&(T=T.filter(C=>C.direction===m.direction)),m.messageType)){const C=m.messageType.toLowerCase();T=T.filter(A=>{var b;return(b=A.messageType)==null?void 0:b.toLowerCase().includes(C)})}const _=T.slice(f,f+h);(y=s.source)==null||y.postMessage({type:"SW_DEBUG_POSTMESSAGE_LOGS",logs:_,total:T.length,offset:f,limit:h,stats:Qs()})}else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_POSTMESSAGE_LOGS")Ks(),(S=s.source)==null||S.postMessage({type:"SW_DEBUG_POSTMESSAGE_LOGS_CLEARED"});else if(s.data&&s.data.type==="CRASH_SNAPSHOT"){const h=s.data.snapshot;h&&(gr(h),D.clients.matchAll().then(f=>{f.forEach(m=>{m.postMessage({type:"SW_DEBUG_NEW_CRASH_SNAPSHOT",snapshot:h})})}))}else s.data&&s.data.type==="SW_DEBUG_GET_CRASH_SNAPSHOTS"?(async()=>{var h,f;try{const m=await pr();(h=s.source)==null||h.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS",snapshots:m,total:m.length})}catch(m){(f=s.source)==null||f.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS",snapshots:[],total:0,error:String(m)})}})():s.data&&s.data.type==="SW_DEBUG_CLEAR_CRASH_SNAPSHOTS"?(async()=>{var h;await mr(),(h=s.source)==null||h.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS_CLEARED"})})():s.data&&s.data.type==="SW_DEBUG_GET_LLM_API_LOGS"?(async()=>{var h,f;try{const{getAllLLMApiLogs:m}=await Promise.resolve().then(()=>O),T=await m();(h=s.source)==null||h.postMessage({type:"SW_DEBUG_LLM_API_LOGS",logs:T,total:T.length})}catch(m){(f=s.source)==null||f.postMessage({type:"SW_DEBUG_LLM_API_LOGS",logs:[],total:0,error:String(m)})}})():s.data&&s.data.type==="SW_DEBUG_CLEAR_LLM_API_LOGS"&&(async()=>{var f;const{clearAllLLMApiLogs:h}=await Promise.resolve().then(()=>O);await h(),(f=s.source)==null||f.postMessage({type:"SW_DEBUG_LLM_API_LOGS_CLEARED"})})()});const fr="MemorySnapshotDB",re="snapshots",ws=50;async function Et(){return new Promise((s,e)=>{const t=indexedDB.open(fr,1);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const r=o.target.result;if(!r.objectStoreNames.contains(re)){const n=r.createObjectStore(re,{keyPath:"id"});n.createIndex("timestamp","timestamp",{unique:!1}),n.createIndex("type","type",{unique:!1})}}})}async function gr(s){try{const e=await Et(),t=e.transaction(re,"readwrite"),o=t.objectStore(re);o.put(s);const r=o.count();r.onsuccess=()=>{const n=r.result;if(n>ws){const i=o.index("timestamp").openCursor();let c=0;const l=n-ws;i.onsuccess=u=>{const g=u.target.result;g&&c<l&&(o.delete(g.value.id),c++,g.continue())}}},await new Promise((n,a)=>{t.oncomplete=()=>{e.close(),n()},t.onerror=()=>{e.close(),a(t.error)}})}catch(e){console.warn("[SW] Failed to save crash snapshot:",e)}}async function pr(){try{const s=await Et(),o=s.transaction(re,"readonly").objectStore(re).index("timestamp");return new Promise((r,n)=>{const a=o.getAll();a.onsuccess=()=>{s.close();const i=a.result.sort((c,l)=>l.timestamp-c.timestamp);r(i)},a.onerror=()=>{s.close(),n(a.error)}})}catch(s){return console.warn("[SW] Failed to get crash snapshots:",s),[]}}async function mr(){try{const s=await Et(),e=s.transaction(re,"readwrite");e.objectStore(re).clear(),await new Promise((o,r)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),r(e.error)}})}catch(s){console.warn("[SW] Failed to clear crash snapshots:",s)}}const wr=["ConsoleLogDB","ServiceWorkerDB","sw-task-queue","aitu-workspace","drawnix-unified-cache","drawnix-kv-storage","drawnix-prompts","drawnix-chat-db","MemorySnapshotDB"];function yr(s){try{const e=JSON.stringify(s);return new Blob([e]).size}catch{return 0}}async function Sr(s){return new Promise(e=>{try{const t=indexedDB.open(s);t.onerror=()=>e({count:0,totalSize:0}),t.onsuccess=()=>{const o=t.result,r=Array.from(o.objectStoreNames);if(r.length===0){o.close(),e({count:0,totalSize:0});return}let n=0,a=0,i=0,c=0;const l=10;try{const u=o.transaction(r,"readonly");for(const g of r){const w=u.objectStore(g),p=w.count();p.onsuccess=()=>{const d=p.result;if(n+=d,d>0){const y=w.openCursor();let S=0;y.onsuccess=h=>{const f=h.target.result;if(f&&S<l)a+=yr(f.value),i++,S++,f.continue();else if(c++,c===r.length){o.close();const m=i>0?a/i:0,T=Math.round(m*n);e({count:n,totalSize:T})}},y.onerror=()=>{if(c++,c===r.length){o.close();const h=i>0?a/i:0,f=Math.round(h*n);e({count:n,totalSize:f})}}}else c++,c===r.length&&(o.close(),e({count:n,totalSize:0}))},p.onerror=()=>{if(c++,c===r.length){o.close();const d=i>0?a/i:0,y=Math.round(d*n);e({count:n,totalSize:y})}}}}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 Tr(){const s={},e=[qe,M,ye,$e];for(const t of e)try{const o=await caches.open(t),r=await o.keys();let n=0;const a=Math.min(r.length,100);let i=0;for(let c=0;c<a;c++){const l=await o.match(r[c]);if(l){const u=l.headers.get("sw-image-size")||l.headers.get("content-length");u&&(i+=parseInt(u))}}a>0&&r.length>a?n=Math.round(i/a*r.length):n=i,s[t]={count:r.length,totalSize:n,type:"cache"}}catch{s[t]={count:0,totalSize:0,type:"cache"}}for(const t of wr)try{const o=await Sr(t);o.count>0&&(s[`[IDB] ${t}`]={...o,type:"indexeddb"})}catch{}return s}async function Cr(s){try{await(await caches.open(M)).delete(s)}catch(e){throw console.error("Service Worker: Failed to delete cache entry:",s,e),e}}async function Er(s){try{const e=await caches.open(M);let t=0;for(const o of s)try{await e.delete(o),t++}catch(r){console.warn("Service Worker: Failed to delete cache in batch:",o,r)}}catch(e){throw console.error("Service Worker: Failed to batch delete caches:",e),e}}async function _r(){try{const s=await caches.open(M),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 ys(s,e,t){try{(await D.clients.matchAll()).forEach(r=>{r.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 br(){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 D.clients.matchAll()).forEach(n=>{n.postMessage({type:"QUOTA_WARNING",usage:e,quota:t})}))}}catch(s){console.warn("Service Worker: Failed to check storage quota:",s)}}D.addEventListener("fetch",s=>{const e=new URL(s.request.url),t=Date.now();if(e.protocol!=="http:"&&e.protocol!=="https:"){H({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(qo)){const o=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"cache-url",details:"Intercepting cache URL request"});s.respondWith(Rr(s.request).then(r=>(v(o,{status:r.status,statusText:r.statusText,responseType:r.type,duration:Date.now()-t,cached:r.status===200}),r)).catch(r=>{throw v(o,{error:String(r),duration:Date.now()-t}),r}));return}if(e.pathname.startsWith($o)){const o=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"asset-library",details:"Intercepting asset library request"});s.respondWith(Dr(s.request).then(r=>(v(o,{status:r.status,statusText:r.statusText,responseType:r.type,duration:Date.now()-t,cached:r.status===200}),r)).catch(r=>{throw v(o,{error:String(r),duration:Date.now()-t}),r}));return}if(e.hostname==="cdn.i666.fun"){H({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")){H({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")){H({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(Vo(e.hostname)){H({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(or(e,s.request)){const o=Date.now(),r=s.request.headers.get("range"),n=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"video",headers:r?{range:r}:void 0,details:r?`Video Range request: ${r}`:"Video request"});s.respondWith(Lr(s.request).then(a=>(v(n,{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 v(n,{error:String(a),duration:Date.now()-o}),a}));return}if(rr(e,s.request)){const o=Date.now(),r=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"font",details:"Font request"});s.respondWith(Ar(s.request).then(n=>(v(r,{status:n.status,statusText:n.statusText,responseType:n.type,duration:Date.now()-o,cached:n.headers.has("sw-cache-date")}),n)).catch(n=>{throw v(r,{error:String(n),duration:Date.now()-o}),n}));return}if(e.origin!==location.origin&&sr(e,s.request)){const o=Date.now(),r=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"image",details:"External image request"});s.respondWith(kr(s.request).then(n=>(v(r,{status:n.status,statusText:n.statusText,responseType:n.type,duration:Date.now()-o,cached:n.headers.has("sw-cache-date"),size:parseInt(n.headers.get("content-length")||"0")}),n)).catch(n=>{throw v(r,{error:String(n),duration:Date.now()-o}),n}));return}if(s.request.method==="GET"){const o=s.request.mode==="navigate",r=s.request.destination!=="";if(o||r){const n=Date.now(),a=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"static",details:o?"Navigation request":`Static resource (${s.request.destination})`});s.respondWith(Ir(s.request).then(i=>(v(a,{status:i.status,statusText:i.statusText,responseType:i.type,duration:Date.now()-n}),i)).catch(i=>{throw v(a,{error:String(i),duration:Date.now()-n}),i}));return}}if($){const o=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"xhr",details:`XHR/API request (${s.request.method})`});s.respondWith((async()=>{try{const r=s.request.clone();let n,a={};if(s.request.headers.forEach((g,w)=>{a[w]=g}),["POST","PUT","PATCH"].includes(s.request.method))try{const g=s.request.headers.get("content-type")||"";g.includes("application/json")?(n=await r.text(),n.length>2e3&&(n=n.substring(0,2e3)+"... (truncated)")):g.includes("application/x-www-form-urlencoded")?(n=await r.text(),n.length>2e3&&(n=n.substring(0,2e3)+"... (truncated)")):n=`[${g||"binary data"}]`}catch{n="[unable to read body]"}v(o,{headers:a,details:n?`XHR/API request (${s.request.method})
6
6
 
7
7
  Request Body:
8
- ${n}`:`XHR/API request (${s.request.method})`});const i=await fetch(s.request),c=i.clone();let l;const u={};i.headers.forEach((p,w)=>{u[w]=p});try{const p=i.headers.get("content-type")||"";p.includes("application/json")||p.includes("text/")?(l=await c.text(),l.length>5e3&&(l=l.substring(0,5e3)+"... (truncated)")):l=`[${p||"binary data"}] (${i.headers.get("content-length")||"unknown"} bytes)`}catch{l="[unable to read response body]"}return x(o,{status:i.status,statusText:i.statusText,responseType:i.type,duration:Date.now()-t,responseHeaders:u,size:parseInt(i.headers.get("content-length")||"0"),details:n?`XHR/API request (${s.request.method})
8
+ ${n}`:`XHR/API request (${s.request.method})`});const i=await fetch(s.request),c=i.clone();let l;const u={};i.headers.forEach((g,w)=>{u[w]=g});try{const g=i.headers.get("content-type")||"";g.includes("application/json")||g.includes("text/")?(l=await c.text(),l.length>5e3&&(l=l.substring(0,5e3)+"... (truncated)")):l=`[${g||"binary data"}] (${i.headers.get("content-length")||"unknown"} bytes)`}catch{l="[unable to read response body]"}return v(o,{status:i.status,statusText:i.statusText,responseType:i.type,duration:Date.now()-t,responseHeaders:u,size:parseInt(i.headers.get("content-length")||"0"),details:n?`XHR/API request (${s.request.method})
9
9
 
10
10
  Request Body:
11
11
  ${n}
@@ -14,7 +14,7 @@ Response Body:
14
14
  ${l}`:`XHR/API request (${s.request.method})
15
15
 
16
16
  Response Body:
17
- ${l}`}),i}catch(r){throw x(o,{error:String(r),duration:Date.now()-t}),r}})());return}});async function _r(s){new URL(s.url);const e=Math.random().toString(36).substring(2,10);try{const t=await caches.open($e),o=await t.match(s);if(o)return o;const r=await fetch(s);if(r&&r.status===200){const n=r.clone(),a=new Headers(n.headers);a.set("sw-cache-date",Date.now().toString());const i=new Response(n.body,{status:n.status,statusText:n.statusText,headers:a});t.put(s,i).catch(c=>{console.warn(`Service Worker [Font-${e}]: 缓存字体失败:`,c)})}return r}catch(t){console.error(`Service Worker [Font-${e}]: 字体请求失败:`,t);const r=await(await caches.open($e)).match(s);return r||new Response("Font loading failed",{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/plain"}})}}async function _t(s,e={}){return fetch(s,e)}async function br(s){const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=s.headers.get("range"),r=t.pathname.includes("/video/")||/\.(mp4|webm|ogg|mov)$/i.test(t.pathname);try{const n=await caches.open(M);let a=await n.match(s.url);if(a||(a=await n.match(t.pathname)),a){const i=await a.blob();return r?be(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(n){return console.error("Service Worker: Error handling cache URL request:",n),new Response("Internal error",{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain"}})}}async function Ar(s){const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=s.headers.get("range"),r=t.pathname;try{const a=await(await caches.open(M)).match(r);if(a){const i=await a.blob();return t.pathname.match(/\.(mp4|webm|ogg|mov)$/i)&&o?be(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:`,r),new Response("Asset not found",{status:404,statusText:"Not Found",headers:{"Content-Type":"text/plain"}})}catch(n){return console.error(`Service Worker [Asset-${e}]: Error handling asset library request:`,n),new Response("Internal error",{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain"}})}}async function Rr(s){const e=new URL(s.url),t=Math.random().toString(36).substring(2,10);try{const o=s.headers.get("range"),r=new URL(e);["_t","cache_buster","v","timestamp","nocache","_cb","t","retry","rand"].forEach(u=>r.searchParams.delete(u));const a=r.toString(),i=Le.get(a);if(i){i.count=(i.count||1)+1;const u=await i.promise;if(!u){const p={method:"GET",headers:new Headers(s.headers),mode:"cors",credentials:"omit"};return await fetch(e,p)}return be(u,o,t)}if(q.has(a)){const u=q.get(a);if(u)return u.timestamp=Date.now(),be(u.blob,o,t)}try{const p=await(await caches.open(M)).match(a);if(p){const w=await p.blob();return w.size/(1024*1024)<50&&q.set(a,{blob:w,timestamp:Date.now()}),be(w,o,t)}}catch(u){console.warn(`Service Worker [Video-${t}]: 检查 Cache API 失败:`,u)}const c=(async()=>{const u={method:"GET",mode:"cors",credentials:"omit",cache:"default"},p=new URL(r),w=await fetch(p,u);if(!w.ok)throw console.error(`Service Worker [Video-${t}]: Video fetch failed:`,w.status),new Error(`Video fetch failed: ${w.status}`);if(w.status===206)return null;const m=await w.blob();if(m.size/(1024*1024)<50){q.set(a,{blob:m,timestamp:Date.now()});try{const y=await caches.open(M),S=new Response(m,{headers:{"Content-Type":m.type||"video/mp4","Content-Length":m.size.toString(),"sw-cache-date":Date.now().toString(),"sw-video-size":m.size.toString()}});await y.put(a,S)}catch(y){console.warn(`Service Worker [Video-${t}]: 持久化到 Cache API 失败:`,y)}}return m})();Le.set(a,{promise:c,timestamp:Date.now(),count:1,requestId:t}),c.finally(()=>{Le.get(a)&&Le.delete(a)});const l=await c;if(l===null){const u={method:"GET",headers:new Headers(s.headers),mode:"cors",credentials:"omit"};return await fetch(e,u)}return be(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 be(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 r=e.match(/bytes=(\d+)-(\d*)/);if(!r)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 n=parseInt(r[1],10),a=r[2]?parseInt(r[2],10):o-1,i=s.slice(n,a+1),c=a-n+1;return new Response(i,{status:206,statusText:"Partial Content",headers:{"Content-Type":"video/mp4","Content-Range":`bytes ${n}-${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 Dr(s){const e=new URL(s.url),t=s.mode==="navigate"||e.pathname.endsWith(".html"),o=await caches.open(ye);if(rs)try{const a=await _t(s);if(a&&a.status===200&&s.url.startsWith("http"))return o.put(s,a.clone()),a;if(!a.ok){let i=await o.match(s);return!i&&t&&(i=await o.match("/"),i||(i=await o.match("/index.html"))),i||a}return a}catch{let i=await o.match(s);return!i&&t&&(i=await o.match("/"),i||(i=await o.match("/index.html"))),i||(t?ws():new Response("Resource unavailable",{status:503}))}if(t)try{const a=await _t(s,{cache:"reload"});if(a&&a.status===200&&s.url.startsWith("http"))return o.put(s,a.clone()),a;if(!a.ok){let i=await o.match(s);if(i||(i=await o.match("/")),i||(i=await o.match("/index.html")),!i){const c=await caches.keys();for(const l of c)if(l.startsWith("drawnix-static-v"))try{const u=await caches.open(l);if(i=await u.match(s)||await u.match("/")||await u.match("/index.html"),i)break}catch{}}return i||a}return a}catch{let i=await o.match(s);if(i||(i=await o.match("/")),i||(i=await o.match("/index.html")),!i){const c=await caches.keys();for(const l of c)if(l.startsWith("drawnix-static-v"))try{const u=await caches.open(l);if(i=await u.match(s)||await u.match("/")||await u.match("/index.html"),i)break}catch{}}return i||ws()}const r=await o.match(s);if(r)return r;const n=e.pathname;!rs&&(n.match(/\.(js|css|png|jpg|jpeg|gif|webp|svg|woff|woff2|ttf|eot|json|ico)$/i)||s.destination==="script"||s.destination==="style"||s.destination==="image"||s.destination);try{const a=await _t(s),i=a.headers.get("Content-Type");if(a.status===200&&(i==null?void 0:i.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")){console.warn("Service Worker: HTML response for static resource (404 fallback), trying old caches:",s.url);const l=await caches.keys();for(const u of l)if(u.startsWith("drawnix-static-v"))try{const w=await(await caches.open(u)).match(s);if(w)return console.log(`Service Worker: Found resource in ${u} after invalid HTML response`),w}catch{}return new Response("Resource not found",{status:404,statusText:"Not Found"})}if(a&&a.status===200&&s.url.startsWith("http")&&o.put(s,a.clone()),a.status>=400){const l=await caches.keys();for(const u of l)if(u.startsWith("drawnix-static-v"))try{const w=await(await caches.open(u)).match(s);if(w)return w}catch{}}return a}catch{console.warn("[SW] Network failed, trying old caches:",s.url);const i=await caches.keys();for(const c of i)if(c.startsWith("drawnix-static-v"))try{const u=await(await caches.open(c)).match(s);if(u)return console.log(`[SW] Found resource in ${c} after network failure`),u}catch{}return new Response("Resource unavailable offline",{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/plain"}})}}function ws(){return new Response(`<!DOCTYPE html>
17
+ ${l}`}),i}catch(r){throw v(o,{error:String(r),duration:Date.now()-t}),r}})());return}});async function Ar(s){new URL(s.url);const e=Math.random().toString(36).substring(2,10);try{const t=await caches.open($e),o=await t.match(s);if(o)return o;const r=await fetch(s);if(r&&r.status===200){const n=r.clone(),a=new Headers(n.headers);a.set("sw-cache-date",Date.now().toString());const i=new Response(n.body,{status:n.status,statusText:n.statusText,headers:a});t.put(s,i).catch(c=>{console.warn(`Service Worker [Font-${e}]: 缓存字体失败:`,c)})}return r}catch(t){console.error(`Service Worker [Font-${e}]: 字体请求失败:`,t);const r=await(await caches.open($e)).match(s);return r||new Response("Font loading failed",{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/plain"}})}}async function _t(s,e={}){return fetch(s,e)}async function Rr(s){const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=s.headers.get("range"),r=t.pathname.includes("/video/")||/\.(mp4|webm|ogg|mov)$/i.test(t.pathname);try{const n=await caches.open(M);let a=await n.match(s.url);if(a||(a=await n.match(t.pathname)),a){const i=await a.blob();return r?be(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(n){return console.error("Service Worker: Error handling cache URL request:",n),new Response("Internal error",{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain"}})}}async function Dr(s){const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=s.headers.get("range"),r=t.pathname;try{const a=await(await caches.open(M)).match(r);if(a){const i=await a.blob();return t.pathname.match(/\.(mp4|webm|ogg|mov)$/i)&&o?be(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:`,r),new Response("Asset not found",{status:404,statusText:"Not Found",headers:{"Content-Type":"text/plain"}})}catch(n){return console.error(`Service Worker [Asset-${e}]: Error handling asset library request:`,n),new Response("Internal error",{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain"}})}}async function Lr(s){const e=new URL(s.url),t=Math.random().toString(36).substring(2,10);try{const o=s.headers.get("range"),r=new URL(e);["_t","cache_buster","v","timestamp","nocache","_cb","t","retry","rand"].forEach(u=>r.searchParams.delete(u));const a=r.toString(),i=Le.get(a);if(i){i.count=(i.count||1)+1;const u=await i.promise;if(!u){const g={method:"GET",headers:new Headers(s.headers),mode:"cors",credentials:"omit"};return await fetch(e,g)}return be(u,o,t)}if(q.has(a)){const u=q.get(a);if(u)return u.timestamp=Date.now(),be(u.blob,o,t)}try{const g=await(await caches.open(M)).match(a);if(g){const w=await g.blob();return w.size/(1024*1024)<50&&q.set(a,{blob:w,timestamp:Date.now()}),be(w,o,t)}}catch(u){console.warn(`Service Worker [Video-${t}]: 检查 Cache API 失败:`,u)}const c=(async()=>{const u={method:"GET",mode:"cors",credentials:"omit",cache:"default"},g=new URL(r),w=await fetch(g,u);if(!w.ok)throw console.error(`Service Worker [Video-${t}]: Video fetch failed:`,w.status),new Error(`Video fetch failed: ${w.status}`);if(w.status===206)return null;const p=await w.blob();if(p.size/(1024*1024)<50){q.set(a,{blob:p,timestamp:Date.now()});try{const y=await caches.open(M),S=new Response(p,{headers:{"Content-Type":p.type||"video/mp4","Content-Length":p.size.toString(),"sw-cache-date":Date.now().toString(),"sw-video-size":p.size.toString()}});await y.put(a,S)}catch(y){console.warn(`Service Worker [Video-${t}]: 持久化到 Cache API 失败:`,y)}}return p})();Le.set(a,{promise:c,timestamp:Date.now(),count:1,requestId:t}),c.finally(()=>{Le.get(a)&&Le.delete(a)});const l=await c;if(l===null){const u={method:"GET",headers:new Headers(s.headers),mode:"cors",credentials:"omit"};return await fetch(e,u)}return be(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 be(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 r=e.match(/bytes=(\d+)-(\d*)/);if(!r)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 n=parseInt(r[1],10),a=r[2]?parseInt(r[2],10):o-1,i=s.slice(n,a+1),c=a-n+1;return new Response(i,{status:206,statusText:"Partial Content",headers:{"Content-Type":"video/mp4","Content-Range":`bytes ${n}-${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 Ir(s){const e=new URL(s.url),t=s.mode==="navigate"||e.pathname.endsWith(".html"),o=await caches.open(ye);if(as)try{const a=await _t(s);if(a&&a.status===200&&s.url.startsWith("http"))return o.put(s,a.clone()),a;if(!a.ok){let i=await o.match(s);return!i&&t&&(i=await o.match("/"),i||(i=await o.match("/index.html"))),i||a}return a}catch{let i=await o.match(s);return!i&&t&&(i=await o.match("/"),i||(i=await o.match("/index.html"))),i||(t?Ss():new Response("Resource unavailable",{status:503}))}if(t)try{const a=await _t(s,{cache:"reload"});if(a&&a.status===200&&s.url.startsWith("http"))return o.put(s,a.clone()),a;if(!a.ok){let i=await o.match(s);if(i||(i=await o.match("/")),i||(i=await o.match("/index.html")),!i){const c=await caches.keys();for(const l of c)if(l.startsWith("drawnix-static-v"))try{const u=await caches.open(l);if(i=await u.match(s)||await u.match("/")||await u.match("/index.html"),i)break}catch{}}return i||a}return a}catch{let i=await o.match(s);if(i||(i=await o.match("/")),i||(i=await o.match("/index.html")),!i){const c=await caches.keys();for(const l of c)if(l.startsWith("drawnix-static-v"))try{const u=await caches.open(l);if(i=await u.match(s)||await u.match("/")||await u.match("/index.html"),i)break}catch{}}return i||Ss()}const r=await o.match(s);if(r)return r;const n=e.pathname;!as&&(n.match(/\.(js|css|png|jpg|jpeg|gif|webp|svg|woff|woff2|ttf|eot|json|ico)$/i)||s.destination==="script"||s.destination==="style"||s.destination==="image"||s.destination);try{const a=await _t(s),i=a.headers.get("Content-Type");if(a.status===200&&(i==null?void 0:i.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")){console.warn("Service Worker: HTML response for static resource (404 fallback), trying old caches:",s.url);const l=await caches.keys();for(const u of l)if(u.startsWith("drawnix-static-v"))try{const w=await(await caches.open(u)).match(s);if(w)return console.log(`Service Worker: Found resource in ${u} after invalid HTML response`),w}catch{}return new Response("Resource not found",{status:404,statusText:"Not Found"})}if(a&&a.status===200&&s.url.startsWith("http")&&o.put(s,a.clone()),a.status>=400){const l=await caches.keys();for(const u of l)if(u.startsWith("drawnix-static-v"))try{const w=await(await caches.open(u)).match(s);if(w)return w}catch{}}return a}catch{console.warn("[SW] Network failed, trying old caches:",s.url);const i=await caches.keys();for(const c of i)if(c.startsWith("drawnix-static-v"))try{const u=await(await caches.open(c)).match(s);if(u)return console.log(`[SW] Found resource in ${c} after network failure`),u}catch{}return new Response("Resource unavailable offline",{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/plain"}})}}function Ss(){return new Response(`<!DOCTYPE html>
18
18
  <html lang="zh-CN">
19
19
  <head>
20
20
  <meta charset="UTF-8">
@@ -55,4 +55,4 @@ ${l}`}),i}catch(r){throw x(o,{error:String(r),duration:Date.now()-t}),r}})());re
55
55
  <p>请检查您的网络连接,或稍后再试。</p>
56
56
  <button onclick="location.reload()">重试</button>
57
57
  </body>
58
- </html>`,{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}const bt=15e3,ys=3e4;function Ss(s,e,t){return Promise.race([s,new Promise((o,r)=>{setTimeout(()=>r(new Error(t)),e)})])}function Lr(){const s=Date.now(),e=[];if(q.forEach((t,o)=>{s-t.timestamp>Ho&&e.push(o)}),e.length>0&&e.forEach(t=>q.delete(t)),q.size>as){const t=Array.from(q.entries()).sort((n,a)=>n[1].timestamp-a[1].timestamp),o=q.size-as,r=t.slice(0,o);r.length>0&&r.forEach(([n])=>q.delete(n))}}function Ir(){const s=Date.now(),e=[];G.forEach((o,r)=>{s-o.timestamp>ys&&e.push(r)}),e.length>0&&(console.warn(`Service Worker: 清理 ${e.length} 个过期的 pending 请求`),e.forEach(o=>G.delete(o)));const t=[];le.forEach((o,r)=>{s-o.timestamp>ns&&t.push(r)}),t.length>0&&t.forEach(o=>le.delete(o)),Lr()}async function Or(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 n=new Request(t.toString(),{method:s.method,headers:s.headers,mode:s.mode,credentials:s.credentials}),a=t.toString(),i=le.get(a);if(i){if(Date.now()-i.timestamp<ns)return i.response.clone();le.delete(a)}if(G.has(a)){const l=G.get(a);if(l){const u=Date.now()-l.timestamp;if(u>ys)console.warn(`Service Worker [${e}]: 发现过期的 pending 请求 (${u}ms),清理并重新发起:`,a),G.delete(a);else{l.count=(l.count||1)+1,l.duplicateRequestIds=l.duplicateRequestIds||[],l.duplicateRequestIds.push(e);try{const p=await Ss(l.promise,bt,"Image request timeout");return p&&p.clone?p.clone():p}catch(p){if(p.message==="Image request timeout")return console.warn(`Service Worker [${e}]: 重复请求等待超时,清理并返回超时响应让前端直接加载`),G.delete(a),Ts(s.url,e);throw p}}}}Ir();const c=Wr(n,s.url,a,e,o);G.set(a,{promise:c,timestamp:Date.now(),count:1,originalRequestId:e,duplicateRequestIds:[]}),c.then(l=>{l&&l.ok&&le.set(a,{response:l.clone(),timestamp:Date.now()})}).catch(()=>{}).finally(()=>{G.get(a)&&G.delete(a)});try{return await Ss(c,bt,"Image request timeout")}catch(l){if(l.message==="Image request timeout")return console.warn(`Service Worker [${e}]: 图片请求超时(${bt}ms),清理并返回超时响应让前端直接加载:`,s.url),G.delete(a),Ts(s.url,e);throw l}}catch(e){throw console.error("Service Worker fetch error:",e),e}}function Ts(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 Wr(s,e,t,o,r=!1){try{const n=await caches.open(M);if(!r){const d=await n.match(s);if(d){const S=await d.clone().blob();if(S.size===0)console.warn(`Service Worker [${o}]: 检测到空缓存,删除并重新获取:`,e),await n.delete(s);else if(d.headers.get("sw-cache-date")){const f=Date.now(),g=new Response(S,{status:d.status,statusText:d.statusText,headers:{...Object.fromEntries(d.headers.entries()),"sw-cache-date":f.toString()}});return s.url.startsWith("http")&&await n.put(s,g.clone()),g}else{const f=new Response(S,{status:d.status,statusText:d.statusText,headers:{...Object.fromEntries(d.headers.entries()),"sw-cache-date":Date.now().toString()}});return s.url.startsWith("http")&&await n.put(s,f.clone()),f}}}const a=new URL(e),i=fs(a);let c=null,l=!1;i&&i.fallbackDomain&&(c=e.replace(i.hostname,i.fallbackDomain),Se.has(i.hostname)&&(l=!0));let u,p=[{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"}],w;l?w=[c]:(w=[e],c&&w.push(c));let m=null;for(let d=0;d<w.length;d++){const y=w[d],S=d>0;for(let h of p)try{let f,g=!1;for(let T=0;T<=2;T++)try{if(u=await fetch(y,h),u&&(u.status!==0||u.type==="opaque"))break}catch(_){f=_;const E=_.message||"";if(E.includes("CORS")||E.includes("cross-origin")||E.includes("Access-Control-Allow-Origin")||E.includes("Failed to fetch")||E.includes("NetworkError")||E.includes("TypeError")){g=!0;break}T<2&&await new Promise(D=>setTimeout(D,Math.pow(2,T)*1e3))}if(g){const T=new URL(y).hostname;is(T);try{const _=await fetch(e,{mode:"no-cors",credentials:"omit",referrerPolicy:"no-referrer"});if(_.type==="opaque")return _}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(u&&(u.status!==0||u.type==="opaque"))break;f&&(m=f)}catch(f){m=f;continue}if(u&&(u.status!==0||u.type==="opaque"))break;i&&i.fallbackDomain&&d===0&&!l&&(Se.add(i.hostname),rr(i.hostname).catch(h=>{console.warn("Service Worker: 保存失败域名到数据库时出错:",h)}))}if(!u||u.status===0&&u.type!=="opaque"){let d="All fetch attempts failed";return i&&i.fallbackDomain&&(l?d=`备用域名${i.fallbackDomain}也失败了`:d=`All fetch attempts failed for both ${i.hostname} and ${i.fallbackDomain} domains`),console.error(`Service Worker [${o}]: ${d}`,m),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(u.type==="opaque"){const d=new URL(e).hostname;return is(d),u}if(u.ok){const y=await u.clone().blob(),S=y.size/(1024*1024),h=new Response(y,{status:200,statusText:"OK",headers:{"Content-Type":u.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":y.size.toString()}});try{s.url.startsWith("http")&&(await n.put(s,h.clone()),await ms(e,y.size,y.type),await Er())}catch(f){console.warn(`Service Worker: Failed to cache normal response (${S.toFixed(2)}MB, 可能超出存储限制):`,f),await nr(n);try{s.url.startsWith("http")&&(await n.put(s,h.clone()),await ms(e,y.size,y.type))}catch(g){console.error("Service Worker: Still failed to cache after cleanup:",g)}}return h}throw new Error(`HTTP ${u.status}: ${u.statusText}`)}catch(n){console.error("Service Worker fetch error:",n);const a=new URL(e);return n.message.includes("SSL_PROTOCOL_ERROR")||n.message.includes("ERR_SSL_PROTOCOL_ERROR")||n.message.includes("net::ERR_CERT")||n.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: ${n.message}`,{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*"}})}}const Y=[],kr=50,Pr="llm-api-logs",Mr=2,z="logs",Cs=500;let se=null;function Oe(){return new Promise((s,e)=>{const t=indexedDB.open(Pr,Mr);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const r=o.target.result;if(!r.objectStoreNames.contains(z)){const n=r.createObjectStore(z,{keyPath:"id"});n.createIndex("timestamp","timestamp",{unique:!1}),n.createIndex("taskType","taskType",{unique:!1}),n.createIndex("status","status",{unique:!1}),n.createIndex("taskId","taskId",{unique:!1})}}})}async function Es(s){try{const e=await Oe(),t=e.transaction(z,"readwrite"),o=t.objectStore(z);o.put(s);const r=o.count();r.onsuccess=()=>{const n=r.result;if(n>Cs){const a=o.index("timestamp"),i=n-Cs;let c=0;a.openCursor().onsuccess=l=>{const u=l.target.result;u&&c<i&&(u.delete(),c++,u.continue())}}},await new Promise((n,a)=>{t.oncomplete=()=>{e.close(),n()},t.onerror=()=>{e.close(),a(t.error)}})}catch(e){console.warn("[LLMApiLogger] Failed to save log to DB:",e)}}async function At(s){await Es(s)}async function vr(){try{const s=await Oe(),o=s.transaction(z,"readonly").objectStore(z).index("timestamp");return new Promise((r,n)=>{const a=o.getAll();a.onsuccess=()=>{s.close();const i=a.result.reverse();r(i)},a.onerror=()=>{s.close(),n(a.error)}})}catch(s){return console.warn("[LLMApiLogger] Failed to get logs from DB:",s),Y}}async function xr(s){const e=Y.find(t=>t.taskId===s&&t.status==="success"&&t.resultUrl);if(e)return e;try{const t=await Oe(),n=t.transaction(z,"readonly").objectStore(z).index("taskId");return new Promise(a=>{const i=n.getAll(s);i.onsuccess=()=>{const c=i.result;t.close();const l=c.filter(u=>u.status==="success"&&u.resultUrl).sort((u,p)=>p.timestamp-u.timestamp)[0];a(l||null)},i.onerror=()=>{t.close(),a(null)}})}catch(t){return console.warn("[LLMApiLogger] Failed to find log by taskId:",t),null}}async function Nr(s){const e=Y.find(t=>t.taskId===s);if(e)return e;try{const t=await Oe(),n=t.transaction(z,"readonly").objectStore(z).index("taskId");return new Promise(a=>{const i=n.getAll(s);i.onsuccess=()=>{const c=i.result;t.close();const l=c.sort((u,p)=>p.timestamp-u.timestamp)[0];a(l||null)},i.onerror=()=>{t.close(),a(null)}})}catch(t){return console.warn("[LLMApiLogger] Failed to find latest log by taskId:",t),null}}async function Br(){Y.length=0;try{const s=await Oe(),e=s.transaction(z,"readwrite");e.objectStore(z).clear(),await new Promise((o,r)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),r(e.error)}})}catch(s){console.warn("[LLMApiLogger] Failed to clear logs from DB:",s)}}function Ur(s){se=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?Hr(s.prompt):void 0,requestBody:s.requestBody?Dt(s.requestBody):void 0,hasReferenceImages:s.hasReferenceImages,referenceImageCount:s.referenceImageCount,referenceImages:s.referenceImages,status:"pending",taskId:s.taskId,workflowId:s.workflowId};return Y.unshift(t),Y.length>kr&&Y.pop(),Es(t),se&&se({...t}),e}function qr(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?Ke(e.resultText,1e3):void 0,t.responseBody=e.responseBody?Ke(e.responseBody,2e3):void 0,At(t),se&&se({...t}))}function $r(s,e){const t=Y.find(o=>o.id===s);t&&(e.remoteId&&(t.remoteId=e.remoteId),e.responseBody&&(t.responseBody=Ke(e.responseBody,2e3)),e.httpStatus&&(t.httpStatus=e.httpStatus),At(t),se&&se({...t}))}function Gr(s,e){const t=Y.find(o=>o.id===s);t&&(t.status="error",t.httpStatus=e.httpStatus,t.duration=e.duration,t.errorMessage=zr(e.errorMessage),t.responseBody=e.responseBody?Ke(e.responseBody,2e3):void 0,At(t),se&&se({...t}))}function Hr(s){return s.length<=200?s:s.substring(0,200)+"..."}function Ke(s,e){return s.length<=e?s:s.substring(0,e)+"..."}function zr(s){return s.length<=500?s:s.substring(0,500)+"..."}const O=Object.freeze(Object.defineProperty({__proto__:null,clearAllLLMApiLogs:Br,completeLLMApiLog:qr,failLLMApiLog:Gr,findLatestLogByTaskId:Nr,findSuccessLogByTaskId:xr,getAllLLMApiLogs:vr,setLLMApiLogBroadcast:Ur,startLLMApiLog:Fr,updateLLMApiLogMetadata:$r},Symbol.toStringTag,{value:"Module"}));async function Kr(s,e,t,o,r,n,a){try{if(dt(e)){Rt(s,{success:!1,error:`Tool "${e}" requires main thread execution`,type:"error"},n,a);return}const i=await ut(e,t,{geminiConfig:o,videoConfig:r,onProgress:()=>{}});Rt(s,i,n,a)}catch(i){Rt(s,{success:!1,error:i.message||"Tool execution failed",type:"error"},n)}}function Rt(s,e,t,o){const r={type:"MCP_TOOL_RESULT",requestId:s,success:e.success,data:e.data,error:e.error,resultType:e.type};xe(t,r)}const jr=Object.freeze(Object.defineProperty({__proto__:null,executeMCPTool:Kr},Symbol.toStringTag,{value:"Module"}))})();
58
+ </html>`,{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}const bt=15e3,Ts=3e4;function Cs(s,e,t){return Promise.race([s,new Promise((o,r)=>{setTimeout(()=>r(new Error(t)),e)})])}function Or(){const s=Date.now(),e=[];if(q.forEach((t,o)=>{s-t.timestamp>Ko&&e.push(o)}),e.length>0&&e.forEach(t=>q.delete(t)),q.size>cs){const t=Array.from(q.entries()).sort((n,a)=>n[1].timestamp-a[1].timestamp),o=q.size-cs,r=t.slice(0,o);r.length>0&&r.forEach(([n])=>q.delete(n))}}function Wr(){const s=Date.now(),e=[];G.forEach((o,r)=>{s-o.timestamp>Ts&&e.push(r)}),e.length>0&&(console.warn(`Service Worker: 清理 ${e.length} 个过期的 pending 请求`),e.forEach(o=>G.delete(o)));const t=[];le.forEach((o,r)=>{s-o.timestamp>is&&t.push(r)}),t.length>0&&t.forEach(o=>le.delete(o)),Or()}async function kr(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 n=new Request(t.toString(),{method:s.method,headers:s.headers,mode:s.mode,credentials:s.credentials}),a=t.toString(),i=le.get(a);if(i){if(Date.now()-i.timestamp<is)return i.response.clone();le.delete(a)}if(G.has(a)){const l=G.get(a);if(l){const u=Date.now()-l.timestamp;if(u>Ts)console.warn(`Service Worker [${e}]: 发现过期的 pending 请求 (${u}ms),清理并重新发起:`,a),G.delete(a);else{l.count=(l.count||1)+1,l.duplicateRequestIds=l.duplicateRequestIds||[],l.duplicateRequestIds.push(e);try{const g=await Cs(l.promise,bt,"Image request timeout");return g&&g.clone?g.clone():g}catch(g){if(g.message==="Image request timeout")return console.warn(`Service Worker [${e}]: 重复请求等待超时,清理并返回超时响应让前端直接加载`),G.delete(a),Es(s.url,e);throw g}}}}Wr();const c=Pr(n,s.url,a,e,o);G.set(a,{promise:c,timestamp:Date.now(),count:1,originalRequestId:e,duplicateRequestIds:[]}),c.then(l=>{l&&l.ok&&le.set(a,{response:l.clone(),timestamp:Date.now()})}).catch(()=>{}).finally(()=>{G.get(a)&&G.delete(a)});try{return await Cs(c,bt,"Image request timeout")}catch(l){if(l.message==="Image request timeout")return console.warn(`Service Worker [${e}]: 图片请求超时(${bt}ms),清理并返回超时响应让前端直接加载:`,s.url),G.delete(a),Es(s.url,e);throw l}}catch(e){throw console.error("Service Worker fetch error:",e),e}}function Es(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 Pr(s,e,t,o,r=!1){try{const n=await caches.open(M);if(!r){const d=await n.match(s);if(d){const S=await d.clone().blob();if(S.size===0)console.warn(`Service Worker [${o}]: 检测到空缓存,删除并重新获取:`,e),await n.delete(s);else if(d.headers.get("sw-cache-date")){const f=Date.now(),m=new Response(S,{status:d.status,statusText:d.statusText,headers:{...Object.fromEntries(d.headers.entries()),"sw-cache-date":f.toString()}});return s.url.startsWith("http")&&await n.put(s,m.clone()),m}else{const f=new Response(S,{status:d.status,statusText:d.statusText,headers:{...Object.fromEntries(d.headers.entries()),"sw-cache-date":Date.now().toString()}});return s.url.startsWith("http")&&await n.put(s,f.clone()),f}}}const a=new URL(e),i=ps(a);let c=null,l=!1;i&&i.fallbackDomain&&(c=e.replace(i.hostname,i.fallbackDomain),Se.has(i.hostname)&&(l=!0));let u,g=[{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"}],w;l?w=[c]:(w=[e],c&&w.push(c));let p=null;for(let d=0;d<w.length;d++){const y=w[d],S=d>0;for(let h of g)try{let f,m=!1;for(let T=0;T<=2;T++)try{if(u=await fetch(y,h),u&&(u.status!==0||u.type==="opaque"))break}catch(_){f=_;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")){m=!0;break}T<2&&await new Promise(A=>setTimeout(A,Math.pow(2,T)*1e3))}if(m){const T=new URL(y).hostname;ls(T);try{const _=await fetch(e,{mode:"no-cors",credentials:"omit",referrerPolicy:"no-referrer"});if(_.type==="opaque")return _}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(u&&(u.status!==0||u.type==="opaque"))break;f&&(p=f)}catch(f){p=f;continue}if(u&&(u.status!==0||u.type==="opaque"))break;i&&i.fallbackDomain&&d===0&&!l&&(Se.add(i.hostname),ar(i.hostname).catch(h=>{console.warn("Service Worker: 保存失败域名到数据库时出错:",h)}))}if(!u||u.status===0&&u.type!=="opaque"){let d="All fetch attempts failed";return i&&i.fallbackDomain&&(l?d=`备用域名${i.fallbackDomain}也失败了`:d=`All fetch attempts failed for both ${i.hostname} and ${i.fallbackDomain} domains`),console.error(`Service Worker [${o}]: ${d}`,p),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(u.type==="opaque"){const d=new URL(e).hostname;return ls(d),u}if(u.ok){const y=await u.clone().blob(),S=y.size/(1024*1024),h=new Response(y,{status:200,statusText:"OK",headers:{"Content-Type":u.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":y.size.toString()}});try{s.url.startsWith("http")&&(await n.put(s,h.clone()),await ys(e,y.size,y.type),await br())}catch(f){console.warn(`Service Worker: Failed to cache normal response (${S.toFixed(2)}MB, 可能超出存储限制):`,f),await ir(n);try{s.url.startsWith("http")&&(await n.put(s,h.clone()),await ys(e,y.size,y.type))}catch(m){console.error("Service Worker: Still failed to cache after cleanup:",m)}}return h}throw new Error(`HTTP ${u.status}: ${u.statusText}`)}catch(n){console.error("Service Worker fetch error:",n);const a=new URL(e);return n.message.includes("SSL_PROTOCOL_ERROR")||n.message.includes("ERR_SSL_PROTOCOL_ERROR")||n.message.includes("net::ERR_CERT")||n.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: ${n.message}`,{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*"}})}}const Y=[],Mr=50,xr="llm-api-logs",vr=2,z="logs",_s=500;let se=null;function Oe(){return new Promise((s,e)=>{const t=indexedDB.open(xr,vr);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const r=o.target.result;if(!r.objectStoreNames.contains(z)){const n=r.createObjectStore(z,{keyPath:"id"});n.createIndex("timestamp","timestamp",{unique:!1}),n.createIndex("taskType","taskType",{unique:!1}),n.createIndex("status","status",{unique:!1}),n.createIndex("taskId","taskId",{unique:!1})}}})}async function bs(s){try{const e=await Oe(),t=e.transaction(z,"readwrite"),o=t.objectStore(z);o.put(s);const r=o.count();r.onsuccess=()=>{const n=r.result;if(n>_s){const a=o.index("timestamp"),i=n-_s;let c=0;a.openCursor().onsuccess=l=>{const u=l.target.result;u&&c<i&&(u.delete(),c++,u.continue())}}},await new Promise((n,a)=>{t.oncomplete=()=>{e.close(),n()},t.onerror=()=>{e.close(),a(t.error)}})}catch(e){console.warn("[LLMApiLogger] Failed to save log to DB:",e)}}async function At(s){await bs(s)}async function Nr(){try{const s=await Oe(),o=s.transaction(z,"readonly").objectStore(z).index("timestamp");return new Promise((r,n)=>{const a=o.getAll();a.onsuccess=()=>{s.close();const i=a.result.reverse();r(i)},a.onerror=()=>{s.close(),n(a.error)}})}catch(s){return console.warn("[LLMApiLogger] Failed to get logs from DB:",s),Y}}async function Br(s){const e=Y.find(t=>t.taskId===s&&t.status==="success"&&t.resultUrl);if(e)return e;try{const t=await Oe(),n=t.transaction(z,"readonly").objectStore(z).index("taskId");return new Promise(a=>{const i=n.getAll(s);i.onsuccess=()=>{const c=i.result;t.close();const l=c.filter(u=>u.status==="success"&&u.resultUrl).sort((u,g)=>g.timestamp-u.timestamp)[0];a(l||null)},i.onerror=()=>{t.close(),a(null)}})}catch(t){return console.warn("[LLMApiLogger] Failed to find log by taskId:",t),null}}async function Ur(s){const e=Y.find(t=>t.taskId===s);if(e)return e;try{const t=await Oe(),n=t.transaction(z,"readonly").objectStore(z).index("taskId");return new Promise(a=>{const i=n.getAll(s);i.onsuccess=()=>{const c=i.result;t.close();const l=c.sort((u,g)=>g.timestamp-u.timestamp)[0];a(l||null)},i.onerror=()=>{t.close(),a(null)}})}catch(t){return console.warn("[LLMApiLogger] Failed to find latest log by taskId:",t),null}}async function Fr(){Y.length=0;try{const s=await Oe(),e=s.transaction(z,"readwrite");e.objectStore(z).clear(),await new Promise((o,r)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),r(e.error)}})}catch(s){console.warn("[LLMApiLogger] Failed to clear logs from DB:",s)}}function qr(s){se=s}function $r(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?Kr(s.prompt):void 0,requestBody:s.requestBody?Dt(s.requestBody):void 0,hasReferenceImages:s.hasReferenceImages,referenceImageCount:s.referenceImageCount,referenceImages:s.referenceImages,status:"pending",taskId:s.taskId,workflowId:s.workflowId};return Y.unshift(t),Y.length>Mr&&Y.pop(),bs(t),se&&se({...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?Ke(e.resultText,1e3):void 0,t.responseBody=e.responseBody?Ke(e.responseBody,2e3):void 0,At(t),se&&se({...t}))}function Hr(s,e){const t=Y.find(o=>o.id===s);t&&(e.remoteId&&(t.remoteId=e.remoteId),e.responseBody&&(t.responseBody=Ke(e.responseBody,2e3)),e.httpStatus&&(t.httpStatus=e.httpStatus),At(t),se&&se({...t}))}function zr(s,e){const t=Y.find(o=>o.id===s);t&&(t.status="error",t.httpStatus=e.httpStatus,t.duration=e.duration,t.errorMessage=jr(e.errorMessage),t.responseBody=e.responseBody?Ke(e.responseBody,2e3):void 0,At(t),se&&se({...t}))}function Kr(s){return s.length<=200?s:s.substring(0,200)+"..."}function Ke(s,e){return s.length<=e?s:s.substring(0,e)+"..."}function jr(s){return s.length<=500?s:s.substring(0,500)+"..."}const O=Object.freeze(Object.defineProperty({__proto__:null,clearAllLLMApiLogs:Fr,completeLLMApiLog:Gr,failLLMApiLog:zr,findLatestLogByTaskId:Ur,findSuccessLogByTaskId:Br,getAllLLMApiLogs:Nr,setLLMApiLogBroadcast:qr,startLLMApiLog:$r,updateLLMApiLogMetadata:Hr},Symbol.toStringTag,{value:"Module"}));async function Vr(s,e,t,o,r,n,a){try{if(dt(e)){Rt(s,{success:!1,error:`Tool "${e}" requires main thread execution`,type:"error"},n,a);return}const i=await ut(e,t,{geminiConfig:o,videoConfig:r,onProgress:()=>{}});Rt(s,i,n,a)}catch(i){Rt(s,{success:!1,error:i.message||"Tool execution failed",type:"error"},n)}}function Rt(s,e,t,o){const r={type:"MCP_TOOL_RESULT",requestId:s,success:e.success,data:e.data,error:e.error,resultType:e.type};ve(t,r)}const Qr=Object.freeze(Object.defineProperty({__proto__:null,executeMCPTool:Vr},Symbol.toStringTag,{value:"Module"}))})();