aitu-app 0.5.37 → 0.5.39

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 (133) hide show
  1. package/README.md +3 -3
  2. package/assets/{ChatMessagesArea-4R5uSEvc.js → ChatMessagesArea-DBsSaQfM.js} +3 -3
  3. package/assets/{DialogTaskList-s41NUoZM.js → DialogTaskList-Fy2YnTcK.js} +1 -1
  4. package/assets/{Serializer-CrbKWfwv.js → Serializer-BBbyVbcD.js} +1 -1
  5. package/assets/{ToolboxDrawer-BkXaNTSp.css → ToolboxDrawer-BGGMfGy1.css} +1 -1
  6. package/assets/ToolboxDrawer-DrkR1kan.js +91 -0
  7. package/assets/{_baseUniq-D2Iraxur.js → _baseUniq-ItLLAPPG.js} +1 -1
  8. package/assets/{advancedFormat-DVUzgFdS.js → advancedFormat-Cyt8ycVj.js} +1 -1
  9. package/assets/{ai-analyze-DYDblQ8D.js → ai-analyze-hCO9RVDQ.js} +1 -1
  10. package/assets/{ai-image-generation-DG3sOclU.js → ai-image-generation-k6P0qCkq.js} +1 -1
  11. package/assets/{ai-video-generation-DPixqh5_.js → ai-video-generation-zbeqUVxV.js} +1 -1
  12. package/assets/{arc-Cr7q4CkH.js → arc-BqKX1pNT.js} +1 -1
  13. package/assets/{architectureDiagram-VXUJARFQ-B7cvfCql.js → architectureDiagram-VXUJARFQ-oG-5UYdQ.js} +1 -1
  14. package/assets/batch-image-generation-Dq5gE6pJ.js +6 -0
  15. package/assets/{blockDiagram-38ab4fdb-F7hdyvyW.js → blockDiagram-38ab4fdb-B9R_268e.js} +1 -1
  16. package/assets/{blockDiagram-VD42YOAC-CDvOdKgv.js → blockDiagram-VD42YOAC-Ffi9rZ54.js} +1 -1
  17. package/assets/{c4Diagram-3d4e48cf-BRMF3Est.js → c4Diagram-3d4e48cf-B420fEns.js} +1 -1
  18. package/assets/{c4Diagram-YG6GDRKO-DiFWTiBc.js → c4Diagram-YG6GDRKO-BYPf3pLk.js} +1 -1
  19. package/assets/channel-CDS_Qf4B.js +1 -0
  20. package/assets/{chunk-4BX2VUAB-Pth0j0Tj.js → chunk-4BX2VUAB-ClMWk9EW.js} +1 -1
  21. package/assets/{chunk-55IACEB6-BMUQal2Y.js → chunk-55IACEB6-DDJ68Z6q.js} +1 -1
  22. package/assets/{chunk-B4BG7PRW-BRCyw1dO.js → chunk-B4BG7PRW-ClXSfaDb.js} +1 -1
  23. package/assets/{chunk-DI55MBZ5-hFdwndrs.js → chunk-DI55MBZ5-BfZfImW7.js} +1 -1
  24. package/assets/{chunk-FMBD7UC4-Bf-NmkqH.js → chunk-FMBD7UC4-DA2q3AyT.js} +1 -1
  25. package/assets/{chunk-QN33PNHL-DpBaMDxk.js → chunk-QN33PNHL-CY28Hdcd.js} +1 -1
  26. package/assets/{chunk-QZHKN3VN-DtbXLXUL.js → chunk-QZHKN3VN-B9bTwnHc.js} +1 -1
  27. package/assets/{chunk-TZMSLE5B-D0ZfSst5.js → chunk-TZMSLE5B-BRq1BWUZ.js} +1 -1
  28. package/assets/classDiagram-2ON5EDUG-Dz5m-vOe.js +1 -0
  29. package/assets/{classDiagram-70f12bd4-CxlVdSmR.js → classDiagram-70f12bd4-DNzQyAPw.js} +1 -1
  30. package/assets/classDiagram-v2-WZHVMYZB-Dz5m-vOe.js +1 -0
  31. package/assets/{classDiagram-v2-f2320105-HZT-eVj7.js → classDiagram-v2-f2320105-XTvONY-O.js} +1 -1
  32. package/assets/clone-B85cFPZq.js +1 -0
  33. package/assets/{cose-bilkent-S5V4N54A-DRiLweDS.js → cose-bilkent-S5V4N54A-wTQBClc3.js} +1 -1
  34. package/assets/{createText-2e5e7dd3-BTdiXD_R.js → createText-2e5e7dd3-Cpz7ChtF.js} +1 -1
  35. package/assets/{cytoscape-cose-bilkent-CW1aHa8q.js → cytoscape-cose-bilkent-BtkKO3EV.js} +1 -1
  36. package/assets/{dagre-6UL2VRFP-BN8PFmpv.js → dagre-6UL2VRFP-CLAcQT8D.js} +1 -1
  37. package/assets/{diagram-PSM6KHXK-ByvtQHnD.js → diagram-PSM6KHXK-BGrxmpLC.js} +1 -1
  38. package/assets/{diagram-QEK2KX5R-CEpkMkqO.js → diagram-QEK2KX5R-C39Q2zPM.js} +1 -1
  39. package/assets/{diagram-S2PKOQOG-DtjWqn8w.js → diagram-S2PKOQOG-CQsKcR2w.js} +1 -1
  40. package/assets/{edges-e0da2a9e-Bs7hlmE3.js → edges-e0da2a9e-DyDxahje.js} +1 -1
  41. package/assets/{erDiagram-9861fffd-DS-W0hHi.js → erDiagram-9861fffd-C8pPIiys.js} +1 -1
  42. package/assets/{erDiagram-Q2GNP2WA-vHsYpiEl.js → erDiagram-Q2GNP2WA-WsIShkjS.js} +1 -1
  43. package/assets/{flowDb-956e92f1-NbAwjRKz.js → flowDb-956e92f1-D7f_AaMZ.js} +1 -1
  44. package/assets/{flowDiagram-66a62f08-D5VVHUei.js → flowDiagram-66a62f08-CEZu2OG2.js} +1 -1
  45. package/assets/{flowDiagram-NV44I4VS-DMsTQeJg.js → flowDiagram-NV44I4VS-DN9cNNDH.js} +1 -1
  46. package/assets/flowDiagram-v2-96b9c2cf-aHk-L0CX.js +1 -0
  47. package/assets/{flowchart-elk-definition-4a651766-DOdRAhnj.js → flowchart-elk-definition-4a651766-Byz0W5JX.js} +1 -1
  48. package/assets/{ganttDiagram-JELNMOA3-Kc9B0VEX.js → ganttDiagram-JELNMOA3-BEtoPRCT.js} +1 -1
  49. package/assets/{ganttDiagram-c361ad54-COmEUt2G.js → ganttDiagram-c361ad54-D8cDKIDW.js} +1 -1
  50. package/assets/{gitGraphDiagram-72cf32ee-Cy4EC3CJ.js → gitGraphDiagram-72cf32ee-CeR12uHG.js} +1 -1
  51. package/assets/{gitGraphDiagram-NY62KEGX-CqyL21WR.js → gitGraphDiagram-NY62KEGX-DEkOgNji.js} +1 -1
  52. package/assets/{graph-BKV5on9y.js → graph-BuEKTPWn.js} +1 -1
  53. package/assets/{graph-oG3LeP7H.js → graph-DF6C7Pb4.js} +1 -1
  54. package/assets/{grid-image-CdvDGYAI.js → grid-image-S8DxjybO.js} +1 -1
  55. package/assets/{has-BHsqYbx0.js → has-B9f4jyaz.js} +1 -1
  56. package/assets/{hasIn-Co4aQICy.js → hasIn-CzYnYdke.js} +1 -1
  57. package/assets/{index-C4tTkKSZ.js → index--_4Ju5mY.js} +1 -1
  58. package/assets/{index-3862675e-COzZpf9r.js → index-3862675e-B5v1keEn.js} +1 -1
  59. package/assets/{index-B8QKLkjB.js → index-B5HQGfrF.js} +1 -1
  60. package/assets/{index-vL7QTGOg.js → index-BALzTgAE.js} +1 -1
  61. package/assets/index-BXp-gQxZ.js +2081 -0
  62. package/assets/index-BfW_kMkx.js +6 -0
  63. package/assets/{index-CSHw3wuM.js → index-BjOQVure.js} +1 -1
  64. package/assets/{index-DorTmaqo.js → index-C43H8OQj.js} +1 -1
  65. package/assets/{index-PoRskjQd.js → index-CljpoCtv.js} +14 -14
  66. package/assets/index-CwbXCuSp.css +9 -0
  67. package/assets/index-DIqMR4S4.css +1 -0
  68. package/assets/{index-BOWLxz8H.js → index-DsTb49bw.js} +1 -1
  69. package/assets/{index-Bfs1HbrZ.js → index-e40yW5SA.js} +10 -10
  70. package/assets/{infoDiagram-WHAUD3N6-BQsNIg3B.js → infoDiagram-WHAUD3N6-CkRZTQlJ.js} +1 -1
  71. package/assets/{infoDiagram-f8f76790-C6N_enwT.js → infoDiagram-f8f76790-DnJUQA5f.js} +1 -1
  72. package/assets/{inspiration-board-CZhQ2eNe.js → inspiration-board-BBS7Ggir.js} +1 -1
  73. package/assets/{isEmpty-DNjFjE1X.js → isEmpty-Cb-sxNzj.js} +1 -1
  74. package/assets/{journeyDiagram-49397b02-CHHC72m6.js → journeyDiagram-49397b02-C15lY7d_.js} +1 -1
  75. package/assets/{journeyDiagram-XKPGCS4Q-BTBm9K6M.js → journeyDiagram-XKPGCS4Q-BrVPMh4M.js} +1 -1
  76. package/assets/{kanban-definition-3W4ZIXB7-CSRkDI3S.js → kanban-definition-3W4ZIXB7-CiDmOTP0.js} +1 -1
  77. package/assets/{layout-Dw3kRoNR.js → layout-DOUBEDJ0.js} +1 -1
  78. package/assets/{layout-CuFQpR54.js → layout-LlEK-Af9.js} +1 -1
  79. package/assets/{line-M1K0EZk9.js → line-5DqkKu5a.js} +1 -1
  80. package/assets/{linear-BCayEq5f.js → linear-nORGeaV4.js} +1 -1
  81. package/assets/{mermaid.core-BRR3s9np.js → mermaid.core-CeadxHhK.js} +4 -4
  82. package/assets/{min-CigzM_E9.js → min-BqFoyXNs.js} +1 -1
  83. package/assets/{mindmap-definition-VGOIOE7T-CMnA43f1.js → mindmap-definition-VGOIOE7T-CAqwaVIW.js} +1 -1
  84. package/assets/{mindmap-definition-fc14e90a-CfNedaN0.js → mindmap-definition-fc14e90a-D-DDHujP.js} +1 -1
  85. package/assets/{photo-wall-splitter-CbtwGiS9.js → photo-wall-splitter-fKX9Yhjh.js} +1 -1
  86. package/assets/{pick-BLCtT8Rq.js → pick-BGF0ULYb.js} +1 -1
  87. package/assets/{pie-BrHter5G.js → pie-C-K0-SKW.js} +1 -1
  88. package/assets/{pieDiagram-8a3498a8-Dw2RcEhd.js → pieDiagram-8a3498a8-COAeUCCn.js} +1 -1
  89. package/assets/{pieDiagram-ADFJNKIX-_mngjs9u.js → pieDiagram-ADFJNKIX-D5mQZmnj.js} +1 -1
  90. package/assets/{quadrantDiagram-120e2f19-CWKx-2y3.js → quadrantDiagram-120e2f19-BVZGZWy5.js} +1 -1
  91. package/assets/{quadrantDiagram-AYHSOK5B-DCeWXXYz.js → quadrantDiagram-AYHSOK5B-DTN7IUf6.js} +1 -1
  92. package/assets/{requirementDiagram-UZGBJVZJ-3CRoO-y4.js → requirementDiagram-UZGBJVZJ-B7uIb-QP.js} +1 -1
  93. package/assets/{requirementDiagram-deff3bca-B_T4Xshy.js → requirementDiagram-deff3bca-3s56zRS3.js} +1 -1
  94. package/assets/{sankeyDiagram-04a897e0-CyYgIDMn.js → sankeyDiagram-04a897e0-NCf_QTUH.js} +1 -1
  95. package/assets/{sankeyDiagram-TZEHDZUN-CX2706qE.js → sankeyDiagram-TZEHDZUN-DN8QnN_i.js} +1 -1
  96. package/assets/{sequenceDiagram-704730f1-B_YVOpNP.js → sequenceDiagram-704730f1-DGwqPawx.js} +1 -1
  97. package/assets/{sequenceDiagram-WL72ISMW-CEaFRaB_.js → sequenceDiagram-WL72ISMW-Chuzy8HN.js} +1 -1
  98. package/assets/{settings-dialog-DdSeK4jE.js → settings-dialog-FRnZQ5kM.js} +1 -1
  99. package/assets/{stateDiagram-587899a1-C2j7YGa-.js → stateDiagram-587899a1-DYbD44BX.js} +1 -1
  100. package/assets/{stateDiagram-FKZM4ZOC-9THCO5NX.js → stateDiagram-FKZM4ZOC-DYfvAmje.js} +1 -1
  101. package/assets/stateDiagram-v2-4FDKWEC3-BWDNmR_6.js +1 -0
  102. package/assets/{stateDiagram-v2-d93cdb3a-DbDM5mM2.js → stateDiagram-v2-d93cdb3a-BoJkxeLI.js} +1 -1
  103. package/assets/{styles-6aaf32cf-CjtwIcXX.js → styles-6aaf32cf-DKg2ECnu.js} +1 -1
  104. package/assets/{styles-9a916d00-U2SyZx3N.js → styles-9a916d00-D69GuT3h.js} +1 -1
  105. package/assets/{styles-c10674c1-CzwOLZtE.js → styles-c10674c1-C_CUHqzf.js} +1 -1
  106. package/assets/{svgDrawCommon-08f97a94-BYSIub7f.js → svgDrawCommon-08f97a94-BXpHAhFM.js} +1 -1
  107. package/assets/{timeline-definition-85554ec2-BqCOOkln.js → timeline-definition-85554ec2-D30-0j4U.js} +1 -1
  108. package/assets/{timeline-definition-IT6M3QCI-CY9ZUPfV.js → timeline-definition-IT6M3QCI-B4FEc43V.js} +1 -1
  109. package/assets/{treemap-KMMF4GRG-BTycpGPx.js → treemap-KMMF4GRG-pDyLkft9.js} +1 -1
  110. package/assets/{ttd-dialog-CIhnIZ3I.js → ttd-dialog-DeCpGM5R.js} +4 -4
  111. package/assets/{union-DJUPbTpR.js → union-Dp_E3U6e.js} +1 -1
  112. package/assets/{upload-DWEsVOUe.js → upload-T9XlfBAZ.js} +1 -1
  113. package/assets/{video-recovery-service-5uRKw655.js → video-recovery-service-CBUtwYI8.js} +1 -1
  114. package/assets/{xychartDiagram-PRI3JC2R-BbrUvkRB.js → xychartDiagram-PRI3JC2R-m_qKGk-m.js} +1 -1
  115. package/assets/{xychartDiagram-e933f94c-DpNCMQAe.js → xychartDiagram-e933f94c-Bup4w7yN.js} +1 -1
  116. package/assets/zipObject-nNXDWpiI.js +1 -0
  117. package/package.json +1 -1
  118. package/precache-manifest.json +240 -240
  119. package/sw.js +7 -7
  120. package/version.json +11 -3
  121. package/assets/ToolboxDrawer-UoRROBuP.js +0 -87
  122. package/assets/batch-image-generation-IdsT9Hgo.js +0 -6
  123. package/assets/channel-BnjxhLNk.js +0 -1
  124. package/assets/classDiagram-2ON5EDUG-CvvgXUsI.js +0 -1
  125. package/assets/classDiagram-v2-WZHVMYZB-CvvgXUsI.js +0 -1
  126. package/assets/clone-0GA3G7Gj.js +0 -1
  127. package/assets/flowDiagram-v2-96b9c2cf-CcZZ9TC9.js +0 -1
  128. package/assets/index-BJdbZLDA.js +0 -2128
  129. package/assets/index-C4AKKbpQ.css +0 -1
  130. package/assets/index-CNP-5X5K.css +0 -1
  131. package/assets/index-D1UJ7CQO.js +0 -42
  132. package/assets/stateDiagram-v2-4FDKWEC3-0fkBazf8.js +0 -1
  133. package/assets/zipObject-DvKKL1BC.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 Is={timeouts:{image:600*1e3,video:1200*1e3,character:600*1e3,inspiration_board:600*1e3,chat:600*1e3}},Ke="sw-task-queue",At=2,k="tasks",K="config",B="workflows",U="chat-workflows",q="pending-tool-requests",Os=[k,K,B,U,q];function Ws(){return new Promise(s=>{const e=indexedDB.open(Ke);e.onsuccess=()=>{const t=e.result,o=t.version;t.close(),s(Math.max(o,At))},e.onerror=()=>{s(At)}})}function ks(s){const e=[];for(const t of Os)s.objectStoreNames.contains(t)||e.push(t);return e}function Ps(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(Ke,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;Rt(a)}})}function Rt(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(K)||s.createObjectStore(K,{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(q)||s.createObjectStore(q,{keyPath:"requestId"}).createIndex("workflowId","workflowId",{unique:!1})}async function Ms(){const s=await Ws();return new Promise((e,t)=>{const o=indexedDB.open(Ke,s);o.onerror=()=>{console.error("[SWStorage] Failed to open DB:",o.error),t(o.error)},o.onsuccess=()=>{const r=o.result,n=ks(r);if(n.length>0){console.warn(`[SWStorage] Missing object stores: ${n.join(", ")}. Repairing...`),r.close(),Ps(r.version).then(e).catch(t);return}e(r)},o.onupgradeneeded=r=>{const n=r.target.result;Rt(n)}})}class xs{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=Ms()),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 b=T.target.result;if(!b){c({tasks:h,total:g,hasMore:g>t+h.length});return}const E=b.value,D=!r||E.status===r,_=!n||E.type===n;D&&_&&(g++,f<t?f++:h.length<o&&h.push(E)),b.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(K,"readwrite"),i=a.objectStore(K);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:",o)}}async loadConfig(){try{const e=await this.getDB();return new Promise((t,o)=>{const r=e.transaction(K,"readonly"),n=r.objectStore(K),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:",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(K,"readwrite");n.objectStore(K).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(K,"readonly").objectStore(K).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(q,"readwrite").objectStore(q).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(q,"readonly").objectStore(q).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(q,"readonly").objectStore(q).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(q,"readonly").objectStore(q).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(q,"readwrite").objectStore(q).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 xs;let Pe=!1;const vs=500,oe=[];let Me=0;function Ns(){return Pe}const Bs=["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 Dt(s){const e=Pe;Pe=s,!s&&e&&(oe.length=0,Ae.clear(),Me=0)}function Ve(){return Pe}function Lt(s){return Ns()?!Bs.includes(s):!1}function Us(s,e,t){if(!Lt(s))return"";const o=`pm-recv-${Date.now()}-${++Me}`,r={id:o,timestamp:Date.now(),direction:"receive",messageType:s,data:Qe(e),clientId:t};if(Ot(r),Fs(s)){const n=Wt(e);n&&Ae.set(n,{entry:r,startTime:Date.now()})}return o}function It(s,e,t){if(!Lt(s))return"";const o=`pm-send-${Date.now()}-${++Me}`,r={id:o,timestamp:Date.now(),direction:"send",messageType:s,data:Qe(e),clientId:t};if($s(s)){const n=Wt(e);if(n){const a=Ae.get(n);a&&(r.duration=Date.now()-a.startTime,a.entry.response=Qe(e),a.entry.duration=r.duration,Ae.delete(n))}}return Ot(r),o}function Ot(s){oe.unshift(s),oe.length>vs&&oe.pop()}function Re(){return[...oe]}function qs(){oe.length=0,Ae.clear(),Me=0}function Fs(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 $s(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 Wt(s){if(!s||typeof s!="object")return null;const e=s;return e.requestId||e.taskId||e.workflowId||e.chatId||null}function Qe(s){if(!s)return s;try{const e=JSON.parse(JSON.stringify(s));return kt(e),e}catch{return"[Non-serializable data]"}}function kt(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"&&kt(t[o])}function Gs(){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 Je(s){xe=s,Dt(s)}function Hs(s){he=s}function Pt(s,e){if(!s){console.warn("[MessageBus] No client provided");return}let t="";if(Ve()){const o=(e==null?void 0:e.type)||"unknown";t=It(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 Mt(s){const e=self,t=(s==null?void 0:s.type)||"unknown";e.clients.matchAll().then(o=>{o.forEach(r=>{let n="";if(Ve()&&(n=It(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?(Pt(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 zs(s,e){xe=!1,Dt(!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 Xe(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 xt(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 vt(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 Nt extends Error{constructor(e){super(e),this.name="VideoGenerationFailedError"}}async function Ye(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 Nt(f)}await new Promise(f=>setTimeout(f,a)),c++}catch(d){if(d instanceof Nt){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 Ze="drawnix-images",Ks=720*60*1e3,Vs="drawnix-unified-cache",et="media";async function Qs(s){return new Promise(e=>{try{const t=indexedDB.open(Vs);t.onerror=()=>{console.warn("[MediaUtils] Failed to open IndexedDB:",t.error),e(null)},t.onsuccess=()=>{try{const o=t.result;if(!o.objectStoreNames.contains(et)){o.close(),e(null);return}const a=o.transaction(et,"readonly").objectStore(et).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 tt(s,e){try{if(s.startsWith("data:"))return st(s);const t=await caches.open(Ze),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 st(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 Bt(s){return new Promise((e,t)=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.onerror=t,o.readAsDataURL(s)})}const ot=1024*1024,Ne=.1,Be=2048;async function Ut(s,e=ot){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,b=.95,E=null;for(let D=0;D<6;D++){const _=(T+b)/2,W=await h.convertToBlob({type:"image/jpeg",quality:_});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=ot){const t=await Ut(s,e);return Bt(t)}async function Js(s,e){let t=null,o="";if(typeof s=="string"?(o=s,t=await tt(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 qt(s,e){if(s.startsWith("data:")){if((s.split(",")[1]||"").length*3/4>ot){const r=st(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(Ze);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 Qs(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<Ks)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 Ft(s,e){return!s||s.length===0?[]:(await Promise.all(s.map(o=>qt(o,e)))).map(o=>o.value)}function rt(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=Xe(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 Xs(s){return s.startsWith("data:image/")&&s.includes(";base64,")}function Ys(s){const e=s.match(/^data:(image\/[^;]+);base64,(.+)$/);return e?{mimeType:e[1],base64:e[2]}:null}async function $t(s,e="image/png"){try{const t=atob(s),o=new Uint8Array(t.length);for(let 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(Ze),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 nt(s,e){var i;if(!s.data||s.data.length===0)throw new Error("No image data in response");async function t(c,l){return c.url?c.url:c.b64_json?await $t(c.b64_json,"image/png"):null}const o=s.data[0],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 Gt(s){if(!Xs(s))return{url:s,migrated:!1};const e=Ys(s);if(!e)return{url:s,migrated:!1};try{return{url:await $t(e.base64,e.mimeType),migrated:!0}}catch(t){return console.error("[Migration] Failed to migrate Base64 URL:",t),{url:s,migrated:!1}}}const at=Object.freeze(Object.defineProperty({__proto__:null,blobToBase64:Bt,blobToCompressedBase64:ne,buildImageGenerationRequestBody:rt,compressImageBlob:Ut,convertAspectRatioToSize:Xe,dataUrlToBlob:st,extractUrlsFromUploadedImages:xt,fetchImageWithCache:tt,getImageInfo:Js,mergeReferenceImages:vt,migrateBase64UrlIfNeeded:Gt,parseImageGenerationResponse:nt,pollVideoUntilComplete:Ye,processReferenceImage:qt,processReferenceImages:Ft},Symbol.toStringTag,{value:"Module"}));class Zs{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||xt(n.uploadedImages);let i;const{getImageInfo:c}=await Promise.resolve().then(()=>at),{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 Ft(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||Xe(n.aspectRatio),y=rt({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:b}=await nt(g,e.id);return u(h,{httpStatus:f.status,duration:Date.now()-S,resultType:"image",resultCount:1,resultUrl:b,responseBody:T}),t.onProgress(e.id,100),{url:b,format:"png",size:0,width:n.width,height:n.height}}}class eo{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=vt({referenceImages:n.referenceImages,uploadedImages:n.uploadedImages,inputReference:n.inputReference,inputReferences:n.inputReferences}),{getImageInfo:c}=await Promise.resolve().then(()=>at),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 b=await tt(T,o);b?a.append("input_reference",b,`reference-${g+1}.png`):(console.warn(`[VideoHandler] Failed to get reference image: ${T}`),a.append("input_reference",T))}catch(b){console.warn(`[VideoHandler] Error fetching reference image: ${T}`,b),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 Ye(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 to{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 so{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,Ts,Cs,Es,bs,_s,As;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(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(()=>at),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 j=await S(de.image_url.url,n);h.push({url:j.url,size:j.size,width:j.width,height:j.height})}catch(j){console.warn("[ChatHandler] Failed to get image info for log",j),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 x=await g.text();throw w(f,{httpStatus:g.status,duration:Date.now()-m,errorMessage:x}),new Error(`Chat request failed: ${g.status} - ${x}`)}const T=m,b=f;if(!g.body)throw new Error("No response body");const E=g.body.getReader(),D=new TextDecoder;let _="",W="";try{for(;;){const{done:x,value:de}=await E.read();if(x)break;W+=D.decode(de,{stream:!0});const j=W.split(`
2
- `);W=j.pop()||"";for(const Rs of j)if(Rs.startsWith("data: ")){const Ds=Rs.slice(6).trim();if(Ds==="[DONE]")continue;try{const Ls=(Es=(Cs=(Ts=JSON.parse(Ds).choices)==null?void 0:Ts[0])==null?void 0:Cs.delta)==null?void 0:Es.content;Ls&&(_+=Ls,a==null||a(_))}catch{}}}if(W.startsWith("data: ")){const x=W.slice(6).trim();if(x&&x!=="[DONE]")try{const j=(As=(_s=(bs=JSON.parse(x).choices)==null?void 0:bs[0])==null?void 0:_s.delta)==null?void 0:As.content;j&&(_+=j,a==null||a(_))}catch{}}}finally{E.releaseLock()}if(g.__debugLogId&&_){const{updateLogResponseBody:x}=await Promise.resolve().then(()=>N);x(g.__debugLogId,_)}const{completeLLMApiLog:Z}=await Promise.resolve().then(()=>O);return Z(b,{httpStatus:g.status,duration:Date.now()-T,resultType:"text",resultCount:1,resultText:_}),_}}class oo{constructor(e,t){this.tasks=new Map,this.runningTasks=new Set,this.geminiConfig=null,this.videoConfig=null,this.initialized=!1,this.chatResultCache=new Map,this.CHAT_CACHE_TTL=60*1e3,this.sw=e,this.config={...Is,...t},this.imageHandler=new Zs,this.videoHandler=new eo,this.characterHandler=new to,this.chatHandler=new so,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);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 Gt(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){await this.storageRestorePromise,this.geminiConfig=e,this.videoConfig=t,this.initialized=!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.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)Pt(o,e)}catch(t){console.error("[SWTaskQueue] Failed to broadcast:",t)}}}let Ue=null;function ro(s,e){return Ue||(Ue=new oo(s,e)),Ue}function it(){return Ue}function no(s,e){var o,r;const t=it();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(()=>Gr).then(({executeMCPTool:n})=>{const a=it(),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 ao={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=rt({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 nt(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"}}}},io={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 b=typeof T=="string"?T:T==null?void 0:T.url;b&&d.push(b)}):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 Ye(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"}}}},Ht=new Map([["generate_image",ao],["generate_video",io]]);function zt(s){return Ht.get(s)}async function ct(s,e,t){const o=Ht.get(s);return o?o.execute(e,t):{success:!1,error:`Unknown tool: ${s}`,type:"error"}}function lt(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 co{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(lt(t.mcp)||!zt(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 y=[];for(const S of m.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&&(await C.saveWorkflow(e),this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:e.id,steps:y}))}const d=m.result;if((t.mcp==="generate_image"||t.mcp==="generate_video")&&m.taskId){t.result={success:!0,type:t.mcp==="generate_image"?"image":"video",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 ct(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 jt(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(fo(e))}catch{return null}}}function Kt(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 lo(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 Vt(s){const e=Kt(s);if(!lo(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 uo(s){const e=Vt(s);if(e&&e.next.length>0)return e.next.map((a,i)=>({id:jt(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:jt(),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 ho(s){const e=Vt(s);if(e)return e.content;let t=Kt(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 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 xs(){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 vs(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 xs();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=vs(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 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 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 xe=!1,he=null;function Ye(s){xe=s,Ot(s)}function Vs(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 Qs(s,e){xe=!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(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}),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 x=await g.text();throw w(f,{httpStatus:g.status,duration:Date.now()-m,errorMessage:x}),new Error(`Chat request failed: ${g.status} - ${x}`)}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:x,value:de}=await E.read();if(x)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 x=W.slice(6).trim();if(x&&x!=="[DONE]")try{const K=(Ls=(Ds=(Rs=JSON.parse(x).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:x}=await Promise.resolve().then(()=>N);x(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.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);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){await this.storageRestorePromise,this.geminiConfig=e,this.videoConfig=t,this.initialized=!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.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)vt(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?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(()=>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 y=[];for(const S of m.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&&(await C.saveWorkflow(e),this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:e.id,steps:y}))}const d=m.result;if((t.mcp==="generate_image"||t.mcp==="generate_video")&&m.taskId){t.result={success:!0,type:t.mcp==="generate_image"?"image":"video",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,`
3
3
 
4
- `),t.trim()}function fo(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 go(s){return uo(s).map(t=>({...t,status:"pending"}))}class po{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=go(o),n=ho(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:b}=await u.read();if(T)break;m+=p.decode(b,{stream:!0});const E=m.split(`
5
- `);m=E.pop()||"";for(const D of E)if(D.startsWith("data: ")){const _=D.slice(6).trim();if(_==="[DONE]")continue;try{const Z=(S=(y=(d=JSON.parse(_).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(lt(r.name)||!zt(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 ct(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 ut(s,e,t){fe=e,ge=t,P=new co({geminiConfig:e,videoConfig:t,broadcast:r=>me(r)});const o=it();o&&o.setTaskStatusChangeCallback((r,n,a,i)=>{P==null||P.updateWorkflowStepForTask(r,n,a,i)}),V=new po({geminiConfig:e,videoConfig:t,broadcast:r=>me(r),sendToClient:(r,n)=>ht(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}),ht(r,{type:"MAIN_THREAD_TOOL_REQUEST",requestId:l,workflowId:n,stepId:a,toolName:i,args:c})})}})}const pe=new Map;function mo(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 wo(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 dt(s,e){if(s.type.startsWith("CHAT_WORKFLOW_")){yo(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 yo(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 So(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 To(){if(P&&(P.broadcastRecoveredWorkflows(),P.resendPendingToolRequests()),V&&V.broadcastRecoveredWorkflows(),pe.size!==0)for(const[,s]of pe){const{requestInfo:e}=s;ht(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){Mt(s)}async function ht(s,e){await ve(s,e)||Mt(e)}const De=[],Co=100;let ft=!1,te=null;function Eo(s){ft=s}function gt(){return ft}function Qt(s){te=s}function Jt(){return[...De]}function bo(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 _o(s){return new Promise((e,t)=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.onerror=t,o.readAsDataURL(s)})}async function Ao(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 _o(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 Ro(s,e,t){if(!ft)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 Ao(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}]`);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>Co&&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:Ro,getInternalFetchLogs:Jt,isDebugFetchEnabled:gt,setDebugFetchBroadcast:Qt,setDebugFetchEnabled:Eo,updateLogResponseBody:bo},Symbol.toStringTag,{value:"Module"})),Do=typeof location<"u"&&(location.hostname==="localhost"||location.hostname==="127.0.0.1"),pt={degradeTimeout:60*1e3,failThreshold:3,fetchTimeout:1500},mt=[{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 Xt(){mt.forEach(s=>{we.has(s.name)||we.set(s.name,{name:s.name,isHealthy:!0,lastCheckTime:0,failCount:0,lastSuccessTime:Date.now()})})}Xt();function Yt(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>=pt.failThreshold&&(e.isHealthy=!1,console.warn(`[CDN Fallback] ${s} marked as unhealthy after ${e.failCount} failures`)))}function Lo(s){const e=we.get(s);return e?e.isHealthy?!0:Date.now()-e.lastCheckTime>pt.degradeTimeout?(console.log(`[CDN Fallback] Trying to recover ${s}...`),!0):!1:!1}function Io(){return mt.filter(s=>s.enabled&&Lo(s.name)).sort((s,e)=>s.priority-e.priority)}function Zt(s){const e=/^\/?(aitu-app@[\d.]+\/)/;return s.replace(e,"/")}function es(s,e,t){const o=Zt(t);return s.urlTemplate.replace("{version}",e).replace("{path}",o.startsWith("/")?o.slice(1):o)}async function wt(s,e=pt.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 Oo(s,e,t){if(Do)return console.log("[CDN Fallback] 开发模式,跳过 CDN 回退"),null;const o=Io();for(const r of o){const n=es(r,e,s);try{console.log(`[CDN Fallback] Trying ${r.name}: ${n}`);const a=await wt(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 Yt(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=Zt(s),n=`${t}/${r.startsWith("/")?r.slice(1):r}`;console.log(`[CDN Fallback] Trying local server: ${n}`);const a=await wt(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 Wo(s){const e=new Map;for(const t of mt){if(!t.enabled)continue;const o=es(t,s,t.healthCheckPath);try{const n=(await wt(o,5e3)).ok;e.set(t.name,n),n?Yt(t.name):ie(t.name)}catch{e.set(t.name,!1),ie(t.name)}}return e}function ko(){return Array.from(we.entries()).map(([s,e])=>({name:s,status:e}))}function Po(){Xt(),console.log("[CDN Fallback] All CDN status reset")}const R=self;ro(R),zs();const ce={log:console.log.bind(console),info:console.info.bind(console),warn:console.warn.bind(console),error:console.error.bind(console)};function Mo(){console.log=(...s)=>{ce.log(...s),gt()&&qe("log",s)},console.info=(...s)=>{ce.info(...s),gt()&&qe("info",s)},console.warn=(...s)=>{ce.warn(...s),qe("warn",s)},console.error=(...s)=>{ce.error(...s),qe("error",s)}}function qe(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 yt=="function"&&yt({logLevel:s,logMessage:o,logSource:"service-worker"})}let yt=null;Mo(),Qt(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.37",Fe=`drawnix-v${Q}`,M="drawnix-images",ye=`drawnix-static-v${Q}`,$e="drawnix-fonts",xo="/__aitu_cache__/",vo="/asset-library/",ts=location.hostname==="localhost"||location.hostname==="127.0.0.1",No=[{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"}],Bo=/\.(jpg|jpeg|png|gif|webp|svg|bmp|ico)$/i,Uo=/\.(mp4|webm|ogg|mov|avi|mkv|flv|wmv|m4v)$/i,G=new Map,le=new Map,ss=30*1e3,Le=new Map,F=new Map,qo=300*1e3,os=10,Se=new Set,Te=new Set,Fo=3600*1e3,St=new Map;function rs(s){Te.add(s),St.set(s,Date.now()),console.warn(`Service Worker: 标记 ${s} 为 CORS 问题域名,后续请求将跳过 SW`)}function $o(s){if(!Te.has(s))return!1;const e=St.get(s);return e&&Date.now()-e>Fo?(Te.delete(s),St.delete(s),!1):!0}const Ie=[],Go=7,J=[],Ho=500;let $=!1,Ce=0;const zo=15e3;let X=null;function ns(){if(!$)return;const s=Date.now();Ce>0&&s-Ce>zo?(ce.log("Service Worker: Debug heartbeat timeout, auto-disabling debug mode"),$=!1,Ce=0,Je(!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(ns,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>Ho&&J.pop(),as(t),e}function v(s,e){if(!$||!s)return;const t=J.find(o=>o.id===s);t&&(Object.assign(t,e),as(t))}async function as(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 is(){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 Ko(){try{const s=await Ge(),o=s.transaction(["logs"],"readwrite").objectStore("logs").index("timestamp"),r=Date.now()-Go*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 cs(){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 ls(s){if(!$)return;const t={id:Math.random().toString(36).substring(2,10),timestamp:Date.now(),type:"console",...s};Ie.unshift(t),jo(t),Vo(t)}yt=ls;async function Vo(s){try{(await R.clients.matchAll()).forEach(t=>{t.postMessage({type:"SW_CONSOLE_LOG",entry:s})})}catch{}}function Qo(){let s=0;return F.forEach(e=>{e.blob&&(s+=e.blob.size)}),s}function He(){return{version:Q,cacheNames:[Fe,M,ye,$e],pendingImageRequests:G.size,pendingVideoRequests:Le.size,videoBlobCacheSize:F.size,videoBlobCacheTotalBytes:Qo(),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:F.size,failedDomainsSetSize:Se.size,corsFailedDomainsSetSize:Te.size,debugLogsArraySize:J.length,consoleLogsArraySize:Ie.length}}}function us(s){for(const e of No)if(s.hostname===e.hostname&&s.pathname.includes(e.pathPattern))return e;return null}function Jo(s,e){return Bo.test(s.pathname)||e.destination==="image"||us(s)!==null}function Xo(s,e){return Uo.test(s.pathname)||e.destination==="video"||s.pathname.includes("/video/")||s.hash.startsWith("#merged-video-")||s.hash.includes("video")}function Yo(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 Zo(){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 er(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 tr(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 sr(){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 or(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 Oo(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 rr(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})=>or(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(Zo()),e.push((async()=>{try{const t=await sr();if(t&&t.length>0){const o=await caches.open(ye);await rr(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!==Fe&&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!==Fe&&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),Ko().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 nr=["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 ar(s){if(!s||typeof s!="object")return!1;const e=s;return e.type?nr.includes(e.type):!1}let ue=!1,Ee=null,be=null;const ze=[];function ds(s){$&&R.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_POSTMESSAGE_LOG",entry:s})})})}Hs(ds),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(Ve()&&(o=Us(e,s.data,t),o&&$)){const f=Re().find(g=>g.id===o);f&&ds(f)}if(s.data&&ar(s.data)){const h=((a=s.source)==null?void 0:a.id)||"";if(no(s.data,h),s.data.type==="TASK_QUEUE_INIT"){const{geminiConfig:f,videoConfig:g}=s.data;if(Ee=f,be=g,!ue&&(ut(R,f,g),ue=!0,ze.length>0)){for(const T of ze)dt(T.message,T.clientId);ze.length=0}To()}if(s.data.type==="TASK_QUEUE_UPDATE_CONFIG"){const{geminiConfig:f,videoConfig:g}=s.data;f&&(Ee={...Ee,...f}),g&&(be={...be,...g}),mo(f,g)}return}if(s.data&&wo(s.data)){const h=((i=s.source)==null?void 0:i.id)||"";if(!ue&&Ee&&be&&(ut(R,Ee,be),ue=!0),!ue){(async()=>{try{const{geminiConfig:f,videoConfig:g}=await C.loadConfig();if(f&&g)Ee=f,be=g,ut(R,f,g),ue=!0,dt(s.data,h);else{const T=await R.clients.matchAll({type:"window"});for(const b of T)b.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:",f)}})();return}dt(s.data,h);return}if(s.data&&s.data.type==="MAIN_THREAD_TOOL_RESPONSE"){So(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&&pr(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)&&mr(h).then(()=>{}).catch(f=>{console.error("Service Worker: Failed to batch delete caches:",f)})}else if(s.data&&s.data.type==="CLEAR_ALL_CACHE")wr().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)}),Je(!0),ce.log("Service Worker: Debug mode enabled"),X&&clearTimeout(X),X=setTimeout(ns,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)}),Je(!1),Ie.length=0,J.length=0,cs().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 gr();(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=Jt().map(_=>({..._,type:"fetch"})),b=new Map;for(const _ of J)b.set(_.id,_);for(const _ of T)b.set(_.id,_);let E=Array.from(b.values()).sort((_,W)=>W.timestamp-_.timestamp);g&&(g.type&&(E=E.filter(_=>_.type===g.type)),g.requestType&&(E=E.filter(_=>_.requestType===g.requestType)),g.url&&(E=E.filter(_=>{var W;return(W=_.url)==null?void 0:W.includes(g.url)})),g.status&&(E=E.filter(_=>_.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:ko()});else if(s.data&&s.data.type==="SW_CDN_RESET_STATUS")Po(),(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 Wo(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,b;try{const E=await caches.open(h||M),D=await E.keys(),_=[];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");_.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:_,total:D.length,offset:g,limit:f})}catch(E){(b=s.source)==null||b.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:b}=s.data;ls({logLevel:h,logMessage:f,logStack:g,logSource:T,url:b})}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:b}=s.data;let E=await is();if(b&&(b.logLevel&&(E=E.filter(_=>_.logLevel===b.logLevel)),b.search)){const _=b.search.toLowerCase();E=E.filter(W=>{var Z,ee;return((Z=W.logMessage)==null?void 0:Z.toLowerCase().includes(_))||((ee=W.logStack)==null?void 0:ee.toLowerCase().includes(_))})}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 cs(),(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 is(),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 _;return(_=D.messageType)==null?void 0:_.toLowerCase().includes(E)})}const b=T.slice(f,f+h);(y=s.source)==null||y.postMessage({type:"SW_DEBUG_POSTMESSAGE_LOGS",logs:b,total:T.length,offset:f,limit:h,stats:Gs()})}else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_POSTMESSAGE_LOGS")qs(),(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&&(cr(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 lr();(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 ur(),(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 ir="MemorySnapshotDB",re="snapshots",hs=50;async function Tt(){return new Promise((s,e)=>{const t=indexedDB.open(ir,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 cr(s){try{const e=await Tt(),t=e.transaction(re,"readwrite"),o=t.objectStore(re);o.put(s);const r=o.count();r.onsuccess=()=>{const n=r.result;if(n>hs){const i=o.index("timestamp").openCursor();let c=0;const l=n-hs;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 lr(){try{const s=await Tt(),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 ur(){try{const s=await Tt(),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 dr=["ConsoleLogDB","ServiceWorkerDB","sw-task-queue","aitu-workspace","drawnix-unified-cache","drawnix-kv-storage","drawnix-prompts","drawnix-chat-db","MemorySnapshotDB"];function hr(s){try{const e=JSON.stringify(s);return new Blob([e]).size}catch{return 0}}async function fr(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+=hr(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 gr(){const s={},e=[Fe,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 dr)try{const o=await fr(t);o.count>0&&(s[`[IDB] ${t}`]={...o,type:"indexeddb"})}catch{}return s}async function pr(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 mr(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 wr(){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 fs(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 yr(){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(xo)){const o=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"cache-url",details:"Intercepting cache URL request"});s.respondWith(Tr(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(vo)){const o=H({type:"fetch",url:s.request.url,method:s.request.method,requestType:"asset-library",details:"Intercepting asset library request"});s.respondWith(Cr(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($o(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(Xo(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(Er(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(Yo(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(Sr(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&&Jo(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(Rr(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(br(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((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]"}v(o,{headers:a,details:n?`XHR/API request (${s.request.method})
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 ve(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 xo(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 vo(){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.39",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 v(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:vo()});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 xo(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=>(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(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=>(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(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=>(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(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=>(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&&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=>(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(Dr(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((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]"}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,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 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})
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 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 v(o,{error:String(r),duration:Date.now()-t}),r}})());return}});async function Sr(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 Ct(s,e={}){return fetch(s,e)}async function Tr(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?_e(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 Cr(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?_e(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 Er(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 _e(u,o,t)}if(F.has(a)){const u=F.get(a);if(u)return u.timestamp=Date.now(),_e(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&&F.set(a,{blob:w,timestamp:Date.now()}),_e(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){F.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 _e(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 _e(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 br(s){const e=new URL(s.url),t=s.mode==="navigate"||e.pathname.endsWith(".html"),o=await caches.open(ye);if(ts)try{const a=await Ct(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?gs():new Response("Resource unavailable",{status:503}))}if(t)try{const a=await Ct(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||gs()}const r=await o.match(s);if(r)return r;const n=e.pathname;!ts&&(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 Ct(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 gs(){return new Response(`<!DOCTYPE html>
17
+ ${l}`}),i}catch(r){throw v(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>
18
18
  <html lang="zh-CN">
19
19
  <head>
20
20
  <meta charset="UTF-8">
@@ -55,4 +55,4 @@ ${l}`}),i}catch(r){throw v(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 Et=15e3,ps=3e4;function ms(s,e,t){return Promise.race([s,new Promise((o,r)=>{setTimeout(()=>r(new Error(t)),e)})])}function _r(){const s=Date.now(),e=[];if(F.forEach((t,o)=>{s-t.timestamp>qo&&e.push(o)}),e.length>0&&e.forEach(t=>F.delete(t)),F.size>os){const t=Array.from(F.entries()).sort((n,a)=>n[1].timestamp-a[1].timestamp),o=F.size-os,r=t.slice(0,o);r.length>0&&r.forEach(([n])=>F.delete(n))}}function Ar(){const s=Date.now(),e=[];G.forEach((o,r)=>{s-o.timestamp>ps&&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>ss&&t.push(r)}),t.length>0&&t.forEach(o=>le.delete(o)),_r()}async function Rr(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<ss)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>ps)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 ms(l.promise,Et,"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),ws(s.url,e);throw p}}}}Ar();const c=Dr(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 ms(c,Et,"Image request timeout")}catch(l){if(l.message==="Image request timeout")return console.warn(`Service Worker [${e}]: 图片请求超时(${Et}ms),清理并返回超时响应让前端直接加载:`,s.url),G.delete(a),ws(s.url,e);throw l}}catch(e){throw console.error("Service Worker fetch error:",e),e}}function ws(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 Dr(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=us(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(b){f=b;const E=b.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;rs(T);try{const b=await fetch(e,{mode:"no-cors",credentials:"omit",referrerPolicy:"no-referrer"});if(b.type==="opaque")return b}catch(b){console.warn(`Service Worker [${o}]: no-cors 模式也失败:`,b)}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),er(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 rs(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 fs(e,y.size,y.type),await yr())}catch(f){console.warn(`Service Worker: Failed to cache normal response (${S.toFixed(2)}MB, 可能超出存储限制):`,f),await tr(n);try{s.url.startsWith("http")&&(await n.put(s,h.clone()),await fs(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=[],Lr=50,Ir="llm-api-logs",Or=2,z="logs",ys=500;let se=null;function Oe(){return new Promise((s,e)=>{const t=indexedDB.open(Ir,Or);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 Ss(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>ys){const a=o.index("timestamp"),i=n-ys;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 bt(s){await Ss(s)}async function Wr(){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 kr(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 Pr(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 Mr(){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 xr(s){se=s}function vr(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?qr(s.prompt):void 0,requestBody:s.requestBody,hasReferenceImages:s.hasReferenceImages,referenceImageCount:s.referenceImageCount,referenceImages:s.referenceImages,status:"pending",taskId:s.taskId,workflowId:s.workflowId};return Y.unshift(t),Y.length>Lr&&Y.pop(),Ss(t),se&&se({...t}),e}function Nr(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?je(e.resultText,1e3):void 0,t.responseBody=e.responseBody?je(e.responseBody,2e3):void 0,bt(t),se&&se({...t}))}function Br(s,e){const t=Y.find(o=>o.id===s);t&&(e.remoteId&&(t.remoteId=e.remoteId),e.responseBody&&(t.responseBody=je(e.responseBody,2e3)),e.httpStatus&&(t.httpStatus=e.httpStatus),bt(t),se&&se({...t}))}function Ur(s,e){const t=Y.find(o=>o.id===s);t&&(t.status="error",t.httpStatus=e.httpStatus,t.duration=e.duration,t.errorMessage=Fr(e.errorMessage),t.responseBody=e.responseBody?je(e.responseBody,2e3):void 0,bt(t),se&&se({...t}))}function qr(s){return s.length<=200?s:s.substring(0,200)+"..."}function je(s,e){return s.length<=e?s:s.substring(0,e)+"..."}function Fr(s){return s.length<=500?s:s.substring(0,500)+"..."}const O=Object.freeze(Object.defineProperty({__proto__:null,clearAllLLMApiLogs:Mr,completeLLMApiLog:Nr,failLLMApiLog:Ur,findLatestLogByTaskId:Pr,findSuccessLogByTaskId:kr,getAllLLMApiLogs:Wr,setLLMApiLogBroadcast:xr,startLLMApiLog:vr,updateLLMApiLogMetadata:Br},Symbol.toStringTag,{value:"Module"}));async function $r(s,e,t,o,r,n,a){try{if(lt(e)){_t(s,{success:!1,error:`Tool "${e}" requires main thread execution`,type:"error"},n,a);return}const i=await ct(e,t,{geminiConfig:o,videoConfig:r,onProgress:()=>{}});_t(s,i,n,a)}catch(i){_t(s,{success:!1,error:i.message||"Tool execution failed",type:"error"},n)}}function _t(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 Gr=Object.freeze(Object.defineProperty({__proto__:null,executeMCPTool:$r},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,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 xr(){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 vr(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:vr,getAllLLMApiLogs:xr,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};ve(t,r)}const jr=Object.freeze(Object.defineProperty({__proto__:null,executeMCPTool:Kr},Symbol.toStringTag,{value:"Module"}))})();