aitu-app 0.5.21 → 0.5.22

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 (117) hide show
  1. package/README.md +3 -3
  2. package/assets/{ChatMessagesArea-CAnmzKeA.js → ChatMessagesArea-DtzEt9y0.js} +3 -3
  3. package/assets/{Serializer-DPCLjt6U.js → Serializer-rTHzSF0Y.js} +1 -1
  4. package/assets/{ToolboxDrawer-D-ZDs49h.js → ToolboxDrawer-D0dL1xDI.js} +1 -1
  5. package/assets/{_baseUniq-CHS3E5If.js → _baseUniq-CJcN2wXt.js} +1 -1
  6. package/assets/{advancedFormat-Chr195ZY.js → advancedFormat-D3noAem-.js} +1 -1
  7. package/assets/{ai-analyze-D3V-tpIV.js → ai-analyze-DSNdzApa.js} +1 -1
  8. package/assets/{arc-lNLKXIKC.js → arc-DCMdqNJq.js} +1 -1
  9. package/assets/{architectureDiagram-VXUJARFQ-CCzBT9XK.js → architectureDiagram-VXUJARFQ-CNLyKX9W.js} +1 -1
  10. package/assets/{batch-image-generation-CgR-a8Ii.js → batch-image-generation-BEr8WnyA.js} +1 -1
  11. package/assets/{blockDiagram-38ab4fdb-CbcE_DRD.js → blockDiagram-38ab4fdb-BfuatLv6.js} +1 -1
  12. package/assets/{blockDiagram-VD42YOAC-CgcfCyW1.js → blockDiagram-VD42YOAC-Lc7hzFMW.js} +1 -1
  13. package/assets/{c4Diagram-3d4e48cf-DqzYo_xg.js → c4Diagram-3d4e48cf-CLYmRF8m.js} +1 -1
  14. package/assets/{c4Diagram-YG6GDRKO-BTZAWhX1.js → c4Diagram-YG6GDRKO-DFgYCXSR.js} +1 -1
  15. package/assets/channel-x6LKWmtX.js +1 -0
  16. package/assets/{chunk-4BX2VUAB-DH-I_3Sl.js → chunk-4BX2VUAB-ZP_vY4vZ.js} +1 -1
  17. package/assets/{chunk-55IACEB6-BJKBSn0v.js → chunk-55IACEB6-B5HoA7RC.js} +1 -1
  18. package/assets/{chunk-B4BG7PRW-BIhB4ChZ.js → chunk-B4BG7PRW-DYumBzJl.js} +1 -1
  19. package/assets/{chunk-DI55MBZ5-NlFLhYIc.js → chunk-DI55MBZ5-8cmxakR4.js} +1 -1
  20. package/assets/{chunk-FMBD7UC4-QVfOPBEJ.js → chunk-FMBD7UC4-CAoW1kf1.js} +1 -1
  21. package/assets/{chunk-QN33PNHL-C_DotWZ6.js → chunk-QN33PNHL-DT5Dd0sR.js} +1 -1
  22. package/assets/{chunk-QZHKN3VN-Ei6ogyMg.js → chunk-QZHKN3VN-CZH2zyPP.js} +1 -1
  23. package/assets/{chunk-TZMSLE5B-CKPTgIMs.js → chunk-TZMSLE5B-BX3lW2Ds.js} +1 -1
  24. package/assets/classDiagram-2ON5EDUG-xDDBDhvH.js +1 -0
  25. package/assets/{classDiagram-70f12bd4-DeAD0Lw4.js → classDiagram-70f12bd4-H_Ao4SWS.js} +1 -1
  26. package/assets/classDiagram-v2-WZHVMYZB-xDDBDhvH.js +1 -0
  27. package/assets/{classDiagram-v2-f2320105-DR43MMrr.js → classDiagram-v2-f2320105-wpOcN7Cp.js} +1 -1
  28. package/assets/clone-BliL8GTL.js +1 -0
  29. package/assets/{cose-bilkent-S5V4N54A-CE31mcuy.js → cose-bilkent-S5V4N54A-BpodmnGt.js} +1 -1
  30. package/assets/{createText-2e5e7dd3-DuyGuD-n.js → createText-2e5e7dd3-DevXK6aG.js} +1 -1
  31. package/assets/{cytoscape-cose-bilkent-DTqUuT3l.js → cytoscape-cose-bilkent-CfL2kyJn.js} +1 -1
  32. package/assets/{dagre-6UL2VRFP-CuJmVGl3.js → dagre-6UL2VRFP-DxcT4smm.js} +1 -1
  33. package/assets/{diagram-PSM6KHXK-D5Y5dlL9.js → diagram-PSM6KHXK-15LgvIqL.js} +1 -1
  34. package/assets/{diagram-QEK2KX5R-DOWAGxHq.js → diagram-QEK2KX5R-Cq44VPiw.js} +1 -1
  35. package/assets/{diagram-S2PKOQOG-ykMhl6fc.js → diagram-S2PKOQOG-DjR4N2-I.js} +1 -1
  36. package/assets/{edges-e0da2a9e-BpsZLv9t.js → edges-e0da2a9e-4-cJcCOg.js} +1 -1
  37. package/assets/{erDiagram-9861fffd-rZLPDBgy.js → erDiagram-9861fffd-CAhGmEfN.js} +1 -1
  38. package/assets/{erDiagram-Q2GNP2WA-zRo1erex.js → erDiagram-Q2GNP2WA-Bv6twqgU.js} +1 -1
  39. package/assets/{flowDb-956e92f1-f4MK2XS7.js → flowDb-956e92f1-7HzSxpZE.js} +1 -1
  40. package/assets/{flowDiagram-66a62f08-_6Eo5sZi.js → flowDiagram-66a62f08-Di0dNdDw.js} +1 -1
  41. package/assets/{flowDiagram-NV44I4VS-CFCClCRc.js → flowDiagram-NV44I4VS-jjJtsD7c.js} +1 -1
  42. package/assets/flowDiagram-v2-96b9c2cf-C7Z70T_R.js +1 -0
  43. package/assets/{flowchart-elk-definition-4a651766-t4QJuK_b.js → flowchart-elk-definition-4a651766-K2hM47DX.js} +1 -1
  44. package/assets/{ganttDiagram-JELNMOA3-DIX2ad-2.js → ganttDiagram-JELNMOA3-DcSqTXib.js} +1 -1
  45. package/assets/{ganttDiagram-c361ad54-dX5QjWrh.js → ganttDiagram-c361ad54-CH7Glt3P.js} +1 -1
  46. package/assets/{gitGraphDiagram-72cf32ee-BBZSqS6J.js → gitGraphDiagram-72cf32ee-BnEB0GU4.js} +1 -1
  47. package/assets/{gitGraphDiagram-NY62KEGX-C-FRyLSQ.js → gitGraphDiagram-NY62KEGX-O0TpP5xG.js} +1 -1
  48. package/assets/{graph-BpCqwwyJ.js → graph-BZ_Ixkdn.js} +1 -1
  49. package/assets/{graph-dwf5l9kJ.js → graph-DHfOf9vz.js} +1 -1
  50. package/assets/{grid-image-DRAUp_wj.js → grid-image-jIEBt3FV.js} +1 -1
  51. package/assets/{has-BBSmRLAB.js → has-C78hNt79.js} +1 -1
  52. package/assets/{hasIn-CGUnHN5L.js → hasIn-DNHU2Dgx.js} +1 -1
  53. package/assets/{index-3862675e-BmuXVGGA.js → index-3862675e-CQkaubhC.js} +1 -1
  54. package/assets/{index-DNIlXgAo.js → index-BNXtnhmh.js} +1 -1
  55. package/assets/{index-Ds1UcDjn.js → index-C6f1jS5T.js} +8 -8
  56. package/assets/{index-CISxTBJ3.js → index-CiiU0LMF.js} +1 -1
  57. package/assets/{index-DEjUAZUe.js → index-D1NStEds.js} +1 -1
  58. package/assets/{index-DvbaH1wH.js → index-DGb8pRqW.js} +1 -1
  59. package/assets/{index-DCs3C-gs.js → index-JhVJEcm-.js} +1 -1
  60. package/assets/{index-_FyCDKGq.js → index-QG8-KVAs.js} +4 -4
  61. package/assets/{index-eOV7y-oZ.js → index-sRDAAYLb.js} +1 -1
  62. package/assets/{infoDiagram-WHAUD3N6-Cw6LtQsv.js → infoDiagram-WHAUD3N6-CZKQnKde.js} +1 -1
  63. package/assets/{infoDiagram-f8f76790-suYKggbB.js → infoDiagram-f8f76790-Cq8UHTek.js} +1 -1
  64. package/assets/{inspiration-board-8CO8xK39.js → inspiration-board-CXBpTN2S.js} +1 -1
  65. package/assets/{isEmpty-BZ44SF3F.js → isEmpty-Bg6e-LN7.js} +1 -1
  66. package/assets/{journeyDiagram-49397b02-DLzRdow3.js → journeyDiagram-49397b02-u4P4ZPSo.js} +1 -1
  67. package/assets/{journeyDiagram-XKPGCS4Q-CcD6LNVi.js → journeyDiagram-XKPGCS4Q-DppWgwdD.js} +1 -1
  68. package/assets/{kanban-definition-3W4ZIXB7-DWA3YqY9.js → kanban-definition-3W4ZIXB7-Cu9Oq__U.js} +1 -1
  69. package/assets/{layout-D8KZ21ze.js → layout-Oya54E8b.js} +1 -1
  70. package/assets/{layout-jxFX0Ar3.js → layout-PukuJPWh.js} +1 -1
  71. package/assets/{line-B3fXWiyE.js → line-CCnY_Zjv.js} +1 -1
  72. package/assets/{linear-DsVcoO9v.js → linear-FgTbCOcj.js} +1 -1
  73. package/assets/{mermaid.core-ruaJ9d8x.js → mermaid.core-Bb0rcjVt.js} +4 -4
  74. package/assets/{min-B6fh4WRE.js → min-BYNXcs16.js} +1 -1
  75. package/assets/{mindmap-definition-VGOIOE7T-BzeNa7DW.js → mindmap-definition-VGOIOE7T-euTygwOP.js} +1 -1
  76. package/assets/{mindmap-definition-fc14e90a-C3sElkm0.js → mindmap-definition-fc14e90a-DMA7ROII.js} +1 -1
  77. package/assets/{photo-wall-splitter-C1GbxYBl.js → photo-wall-splitter-CAWxP47k.js} +1 -1
  78. package/assets/{pick-DUB8w7iE.js → pick-D_sga9lq.js} +1 -1
  79. package/assets/{pie-DAYMJpRO.js → pie-BWVaG8mI.js} +1 -1
  80. package/assets/{pieDiagram-8a3498a8-CZI3pF7g.js → pieDiagram-8a3498a8-JQ1MpLiZ.js} +1 -1
  81. package/assets/{pieDiagram-ADFJNKIX-BqonG77Q.js → pieDiagram-ADFJNKIX-BOGQkDt6.js} +1 -1
  82. package/assets/{quadrantDiagram-120e2f19-Q2bVMK-T.js → quadrantDiagram-120e2f19-kJzxW0Br.js} +1 -1
  83. package/assets/{quadrantDiagram-AYHSOK5B-yJZRIs-Q.js → quadrantDiagram-AYHSOK5B-UxkYiRF3.js} +1 -1
  84. package/assets/{requirementDiagram-UZGBJVZJ-3kaAkLjO.js → requirementDiagram-UZGBJVZJ-Bk95peTm.js} +1 -1
  85. package/assets/{requirementDiagram-deff3bca-DHOhXBYo.js → requirementDiagram-deff3bca-DwSHfS3q.js} +1 -1
  86. package/assets/{sankeyDiagram-04a897e0-3UqYNZg9.js → sankeyDiagram-04a897e0-Dee_8vG5.js} +1 -1
  87. package/assets/{sankeyDiagram-TZEHDZUN-Ce844Tbc.js → sankeyDiagram-TZEHDZUN-Dn-BrNQI.js} +1 -1
  88. package/assets/{sequenceDiagram-704730f1-CBXqjnXl.js → sequenceDiagram-704730f1-CK2_u2M2.js} +1 -1
  89. package/assets/{sequenceDiagram-WL72ISMW-DBN2cRGt.js → sequenceDiagram-WL72ISMW-PtdIXaXk.js} +1 -1
  90. package/assets/{settings-dialog-aU8BHcuS.js → settings-dialog-C4eZxway.js} +1 -1
  91. package/assets/{stateDiagram-587899a1-BGKPA37n.js → stateDiagram-587899a1-vSvTWjnf.js} +1 -1
  92. package/assets/{stateDiagram-FKZM4ZOC-Czg5Opf0.js → stateDiagram-FKZM4ZOC-DGbpdRXP.js} +1 -1
  93. package/assets/stateDiagram-v2-4FDKWEC3-C-2flGWR.js +1 -0
  94. package/assets/{stateDiagram-v2-d93cdb3a-DWU3UljE.js → stateDiagram-v2-d93cdb3a-BrPmXu5B.js} +1 -1
  95. package/assets/{styles-6aaf32cf-BVLDN8CD.js → styles-6aaf32cf-Cf3g-0g3.js} +1 -1
  96. package/assets/{styles-9a916d00-vSy8MhZp.js → styles-9a916d00--ZEFIk8R.js} +1 -1
  97. package/assets/{styles-c10674c1-dzTvI8BU.js → styles-c10674c1-DHwZqsJA.js} +1 -1
  98. package/assets/{svgDrawCommon-08f97a94-dptVwf62.js → svgDrawCommon-08f97a94-n9d3mPea.js} +1 -1
  99. package/assets/{timeline-definition-85554ec2-jKiT0ZaE.js → timeline-definition-85554ec2-H_sXtfLT.js} +1 -1
  100. package/assets/{timeline-definition-IT6M3QCI-B2NoE4jH.js → timeline-definition-IT6M3QCI-C-H3Ftyt.js} +1 -1
  101. package/assets/{treemap-KMMF4GRG-1nrNbz-r.js → treemap-KMMF4GRG-Cu1-wgRV.js} +1 -1
  102. package/assets/{ttd-dialog-WN-s4x87.js → ttd-dialog-TQYw_Nae.js} +5 -5
  103. package/assets/{union-B2D_ldts.js → union-DP4CDhaw.js} +1 -1
  104. package/assets/{upload-Crej215t.js → upload-DdSOuK5h.js} +1 -1
  105. package/assets/{video-recovery-service-Zb_336FQ.js → video-recovery-service-CZXUWRm1.js} +1 -1
  106. package/assets/{xychartDiagram-PRI3JC2R-UPkX0dfi.js → xychartDiagram-PRI3JC2R-CpjoxcIY.js} +1 -1
  107. package/assets/{xychartDiagram-e933f94c-BXYMaBZh.js → xychartDiagram-e933f94c-CTuQj9cZ.js} +1 -1
  108. package/assets/{zipObject-bwVIVuzi.js → zipObject-BF7eTaCR.js} +1 -1
  109. package/package.json +1 -1
  110. package/sw.js +7 -7
  111. package/version.json +2 -2
  112. package/assets/channel-Bew-Iahk.js +0 -1
  113. package/assets/classDiagram-2ON5EDUG-DIttp4Yk.js +0 -1
  114. package/assets/classDiagram-v2-WZHVMYZB-DIttp4Yk.js +0 -1
  115. package/assets/clone-Y0952eQY.js +0 -1
  116. package/assets/flowDiagram-v2-96b9c2cf-Dn2WmcvX.js +0 -1
  117. package/assets/stateDiagram-v2-4FDKWEC3-4Ev4KuVZ.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||{}),W=(s=>(s.SUBMITTING="submitting",s.POLLING="polling",s.DOWNLOADING="downloading",s))(W||{});const ms={timeouts:{image:600*1e3,video:1200*1e3,character:600*1e3,inspiration_board:600*1e3,chat:600*1e3}},He="sw-task-queue",wt=2,k="tasks",K="config",v="workflows",B="chat-workflows",U="pending-tool-requests",ws=[k,K,v,B,U];function Ss(){return new Promise(s=>{const e=indexedDB.open(He);e.onsuccess=()=>{const t=e.result,o=t.version;t.close(),s(Math.max(o,wt))},e.onerror=()=>{s(wt)}})}function ys(s){const e=[];for(const t of ws)s.objectStoreNames.contains(t)||e.push(t);return e}function Ts(s){return new Promise((e,t)=>{const o=s+1;console.log(`[SWStorage] Repairing database: upgrading from v${s} to v${o}`);const n=indexedDB.open(He,o);n.onerror=()=>{console.error("[SWStorage] Failed to repair DB:",n.error),t(n.error)},n.onsuccess=()=>{e(n.result)},n.onupgradeneeded=r=>{const a=r.target.result;St(a)}})}function St(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(v)){const e=s.createObjectStore(v,{keyPath:"id"});e.createIndex("status","status",{unique:!1}),e.createIndex("createdAt","createdAt",{unique:!1})}if(!s.objectStoreNames.contains(B)){const e=s.createObjectStore(B,{keyPath:"id"});e.createIndex("status","status",{unique:!1}),e.createIndex("createdAt","createdAt",{unique:!1})}s.objectStoreNames.contains(U)||s.createObjectStore(U,{keyPath:"requestId"}).createIndex("workflowId","workflowId",{unique:!1})}async function Es(){const s=await Ss();return new Promise((e,t)=>{const o=indexedDB.open(He,s);o.onerror=()=>{console.error("[SWStorage] Failed to open DB:",o.error),t(o.error)},o.onsuccess=()=>{const n=o.result,r=ys(n);if(r.length>0){console.warn(`[SWStorage] Missing object stores: ${r.join(", ")}. Repairing...`),n.close(),Ts(n.version).then(e).catch(t);return}e(n)},o.onupgradeneeded=n=>{const r=n.target.result;St(r)}})}class Cs{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=Es()),this.dbPromise}async flushPendingTaskSaves(){this.batchSaveTimer&&(clearTimeout(this.batchSaveTimer),this.batchSaveTimer=null);const e=Array.from(this.pendingTaskSaves.values()),t=new Map(this.batchSavePromises);if(this.pendingTaskSaves.clear(),this.batchSavePromises.clear(),e.length!==0)try{const o=await this.getDB();await new Promise((n,r)=>{const a=o.transaction(k,"readwrite"),i=a.objectStore(k);for(const c of e)i.put(c);a.oncomplete=()=>{t.forEach(({resolve:c})=>c()),n()},a.onerror=()=>{const c=a.error;t.forEach(({reject:l})=>l(c)),r(c)}})}catch(o){console.error("[SWStorage] Failed to batch save tasks:",o),t.forEach(({reject:n})=>n(o))}}async saveTask(e){return new Promise((t,o)=>{this.pendingTaskSaves.set(e.id,e),this.batchSavePromises.set(e.id,{resolve:t,reject:o}),this.batchSaveTimer||(this.batchSaveTimer=setTimeout(()=>{this.flushPendingTaskSaves()},this.BATCH_SAVE_DELAY))})}async saveTaskImmediate(e){this.pendingTaskSaves.delete(e.id);const t=this.batchSavePromises.get(e.id);t&&this.batchSavePromises.delete(e.id);try{const o=await this.getDB();await new Promise((n,r)=>{const c=o.transaction(k,"readwrite").objectStore(k).put(e);c.onerror=()=>r(c.error),c.onsuccess=()=>n()}),t&&t.resolve()}catch(o){throw console.error("[SWStorage] Failed to save task:",o),t&&t.reject(o),o}}async getTask(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(k,"readonly").objectStore(k).get(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o(i.result||null)})}catch(t){return console.error("[SWStorage] Failed to get task:",t),null}}async getAllTasks(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(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,n)=>{const c=t.transaction(k,"readonly").objectStore(k).index("status").getAll(e);c.onerror=()=>n(c.error),c.onsuccess=()=>o(c.result||[])})}catch(t){return console.error("[SWStorage] Failed to get tasks by status:",t),[]}}async getTasksPaginated(e){const{offset:t,limit:o,status:n,type:r,sortOrder:a="desc"}=e;try{const i=await this.getDB();return new Promise((c,l)=>{const m=i.transaction(k,"readonly").objectStore(k),y=m.index("createdAt"),w=m.count();let f=0;w.onsuccess=()=>{f=w.result};const p=a==="desc"?"prev":"next",S=y.openCursor(null,p),u=[];let h=0,g=0;S.onerror=()=>l(S.error),S.onsuccess=T=>{const _=T.target.result;if(!_){c({tasks:u,total:g,hasMore:g>t+u.length});return}const C=_.value,D=!n||C.status===n,b=!r||C.type===r;D&&b&&(g++,h<t?h++:u.length<o&&u.push(C)),_.continue()}})}catch(i){return console.error("[SWStorage] Failed to get paginated tasks:",i),{tasks:[],total:0,hasMore:!1}}}async deleteTask(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(k,"readwrite").objectStore(k).delete(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to delete task:",t)}}async saveConfig(e,t){try{const o=await this.getDB();return new Promise((n,r)=>{const a=o.transaction(K,"readwrite"),i=a.objectStore(K);e&&i.put({key:"gemini",...e}),t&&i.put({key:"video",...t}),a.oncomplete=()=>n(),a.onerror=()=>r(a.error)})}catch(o){console.error("[SWStorage] Failed to save config:",o)}}async loadConfig(){try{const e=await this.getDB();return new Promise((t,o)=>{const n=e.transaction(K,"readonly"),r=n.objectStore(K),a=r.get("gemini"),i=r.get("video");n.oncomplete=()=>{const c=a.result,l=i.result;t({geminiConfig:c?{apiKey:c.apiKey,baseUrl:c.baseUrl,modelName:c.modelName}:null,videoConfig:l?{baseUrl:l.baseUrl,apiKey:l.apiKey}:null})},n.onerror=()=>o(n.error)})}catch(e){return console.error("[SWStorage] Failed to load config:",e),{geminiConfig:null,videoConfig:null}}}async cleanupOldTasks(e=1440*60*1e3){console.warn("[SWStorage] cleanupOldTasks is deprecated and disabled")}async saveSystemPrompt(e){try{const t=await this.getDB();return new Promise((o,n)=>{const r=t.transaction(K,"readwrite");r.objectStore(K).put({key:"systemPrompt",value:e,updatedAt:Date.now()}),r.oncomplete=()=>o(),r.onerror=()=>n(r.error)})}catch(t){console.error("[SWStorage] Failed to save system prompt:",t)}}async getSystemPrompt(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(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,n)=>{const i=t.transaction(v,"readwrite").objectStore(v).put(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to save workflow:",t)}}async getWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(v,"readonly").objectStore(v).get(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o(i.result||null)})}catch(t){return console.error("[SWStorage] Failed to get workflow:",t),null}}async getAllWorkflows(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(v,"readonly").objectStore(v).getAll();a.onerror=()=>o(a.error),a.onsuccess=()=>t(a.result||[])})}catch(e){return console.error("[SWStorage] Failed to get all workflows:",e),[]}}async getWorkflowsByStatus(e){try{const t=await this.getDB();return new Promise((o,n)=>{const c=t.transaction(v,"readonly").objectStore(v).index("status").getAll(e);c.onerror=()=>n(c.error),c.onsuccess=()=>o(c.result||[])})}catch(t){return console.error("[SWStorage] Failed to get workflows by status:",t),[]}}async deleteWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(v,"readwrite").objectStore(v).delete(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to delete workflow:",t)}}async cleanupOldWorkflows(e=1440*60*1e3){console.warn("[SWStorage] cleanupOldWorkflows is deprecated and disabled")}async saveChatWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(B,"readwrite").objectStore(B).put(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to save chat workflow:",t)}}async getChatWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(B,"readonly").objectStore(B).get(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o(i.result||null)})}catch(t){return console.error("[SWStorage] Failed to get chat workflow:",t),null}}async getAllChatWorkflows(){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 chat workflows:",e),[]}}async getChatWorkflowsByStatus(e){try{const t=await this.getDB();return new Promise((o,n)=>{const c=t.transaction(B,"readonly").objectStore(B).index("status").getAll(e);c.onerror=()=>n(c.error),c.onsuccess=()=>o(c.result||[])})}catch(t){return console.error("[SWStorage] Failed to get chat workflows by status:",t),[]}}async deleteChatWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(B,"readwrite").objectStore(B).delete(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to delete chat workflow:",t)}}async cleanupOldChatWorkflows(e=1440*60*1e3){console.warn("[SWStorage] cleanupOldChatWorkflows is deprecated and disabled")}async savePendingToolRequest(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(U,"readwrite").objectStore(U).put(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to save pending tool request:",t)}}async getAllPendingToolRequests(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(U,"readonly").objectStore(U).getAll();a.onerror=()=>o(a.error),a.onsuccess=()=>t(a.result||[])})}catch(e){return console.error("[SWStorage] Failed to get all pending tool requests:",e),[]}}async getPendingToolRequestsByWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const c=t.transaction(U,"readonly").objectStore(U).index("workflowId").getAll(e);c.onerror=()=>n(c.error),c.onsuccess=()=>o(c.result||[])})}catch(t){return console.error("[SWStorage] Failed to get pending tool requests by workflow:",t),[]}}async getPendingToolRequest(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(U,"readonly").objectStore(U).get(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o(i.result||null)})}catch(t){return console.error("[SWStorage] Failed to get pending tool request:",t),null}}async deletePendingToolRequest(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(U,"readwrite").objectStore(U).delete(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to delete pending tool request:",t)}}async deletePendingToolRequestsByWorkflow(e){try{const t=await this.getPendingToolRequestsByWorkflow(e);for(const o of t)await this.deletePendingToolRequest(o.requestId)}catch(t){console.error("[SWStorage] Failed to delete pending tool requests by workflow:",t)}}}const E=new Cs;let Ie=!1;const _s=500,Y=[];let Oe=0;function bs(){return Ie}const As=["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"],Ee=new Map;function yt(s){const e=Ie;Ie=s,!s&&e&&(Y.length=0,Ee.clear(),Oe=0)}function Ke(){return Ie}function Tt(s){return bs()?!As.includes(s):!1}function Rs(s,e,t){if(!Tt(s))return"";const o=`pm-recv-${Date.now()}-${++Oe}`,n={id:o,timestamp:Date.now(),direction:"receive",messageType:s,data:ze(e),clientId:t};if(Ct(n),Ws(s)){const r=_t(e);r&&Ee.set(r,{entry:n,startTime:Date.now()})}return o}function Et(s,e,t){if(!Tt(s))return"";const o=`pm-send-${Date.now()}-${++Oe}`,n={id:o,timestamp:Date.now(),direction:"send",messageType:s,data:ze(e),clientId:t};if(Ls(s)){const r=_t(e);if(r){const a=Ee.get(r);a&&(n.duration=Date.now()-a.startTime,a.entry.response=ze(e),a.entry.duration=n.duration,Ee.delete(r))}}return Ct(n),o}function Ct(s){Y.unshift(s),Y.length>_s&&Y.pop()}function Ce(){return[...Y]}function Ds(){Y.length=0,Ee.clear(),Oe=0}function Ws(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 Ls(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 _t(s){if(!s||typeof s!="object")return null;const e=s;return e.requestId||e.taskId||e.workflowId||e.chatId||null}function ze(s){if(!s)return s;try{const e=JSON.parse(JSON.stringify(s));return bt(e),e}catch{return"[Non-serializable data]"}}function bt(s){if(!s||typeof s!="object")return;const e=["apiKey","password","token","secret","key"],t=s;for(const o in t)e.some(n=>o.toLowerCase().includes(n))?t[o]="[REDACTED]":typeof t[o]=="object"&&bt(t[o])}function Is(){const s={total:Y.length,sent:0,received:0,byType:{}};for(const e of Y)e.direction==="send"?s.sent++:s.received++,s.byType[e.messageType]||(s.byType[e.messageType]=0),s.byType[e.messageType]++;return s}let ke=!1,ce=null;function je(s){ke=s,yt(s)}function Os(s){ce=s}function At(s,e){if(!s){console.warn("[MessageBus] No client provided");return}let t="";if(Ke()){const o=(e==null?void 0:e.type)||"unknown";t=Et(o,e,s.id)}try{s.postMessage(e)}catch(o){console.warn("[MessageBus] Failed to postMessage to client:",s.id,o);return}if(t&&ke&&ce){const n=Ce().find(r=>r.id===t);n&&ce(n)}}function Rt(s){const e=self,t=(s==null?void 0:s.type)||"unknown";e.clients.matchAll().then(o=>{o.forEach(n=>{let r="";if(Ke()&&(r=Et(t,s,n.id)),n.postMessage(s),r&&ke&&ce){const i=Ce().find(c=>c.id===r);i&&ce(i)}})})}async function Me(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?(At(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 ks(s,e){ke=!1,yt(!1),ce=null}const Ms={"1x1":"1024x1024","16x9":"1792x1024","9x16":"1024x1792","4x3":"1536x1152","3x4":"1152x1536","3x2":"1536x1024","2x3":"1024x1536"};function xs(s){return Ms[s]||s}function Ps(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 Ns(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 Dt extends Error{constructor(e){super(e),this.name="VideoGenerationFailedError"}}async function Wt(s,e,t={}){var y,w;const{onProgress:o,signal:n,apiKey:r,interval:a=5e3,maxAttempts:i=1080}=t;let c=0,l=0;const d=10,{debugFetch:m}=await Promise.resolve().then(()=>N);for(;c<i;){if(n!=null&&n.aborted)throw new Error("Video generation cancelled");try{const f=await m(`${s}/videos/${e}`,{headers:r?{Authorization:`Bearer ${r}`}:{},signal:n},{label:`🔄 查询视频状态 #${c+1}`,logResponseBody:!0});if(!f.ok){if(l++,console.warn(`[VideoPolling] Status query failed (${f.status}), attempt ${l}/${d}, will retry with longer interval`),l>=d)throw new Error(`Failed to get video status after ${d} consecutive errors: ${f.status}`);const h=Math.min(a*Math.pow(1.5,l),6e4);await new Promise(g=>setTimeout(g,h)),c++;continue}l=0;const p=await f.json(),S=(y=p.status)==null?void 0:y.toLowerCase(),u=p.progress??Math.min(10+c*2,90);if(o==null||o(u,"polling"),S==="completed"||S==="succeeded")return o==null||o(100),p;if(S==="failed"||S==="error"){const h=typeof p.error=="string"?p.error:((w=p.error)==null?void 0:w.message)||p.message||"Video generation failed";throw new Dt(h)}await new Promise(h=>setTimeout(h,a)),c++}catch(f){if(f instanceof Dt)throw f;if(n!=null&&n.aborted)throw new Error("Video generation cancelled");if(l++,console.warn(`[VideoPolling] Network error during status query, attempt ${l}/${d}:`,f),l>=d)throw f;const p=Math.min(a*Math.pow(1.5,l),6e4);await new Promise(S=>setTimeout(S,p)),c++}}throw new Error("Video generation timed out")}const Ve="drawnix-images",vs=720*60*1e3,Bs="drawnix-unified-cache",Qe="media";async function Us(s){return new Promise(e=>{try{const t=indexedDB.open(Bs);t.onerror=()=>{console.warn("[MediaUtils] Failed to open IndexedDB:",t.error),e(null)},t.onsuccess=()=>{try{const o=t.result;if(!o.objectStoreNames.contains(Qe)){o.close(),e(null);return}const a=o.transaction(Qe,"readonly").objectStore(Qe).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 qs(s,e){try{if(s.startsWith("data:"))return Lt(s);const t=await caches.open(Ve),o=await t.match(s);if(o)return await o.blob();const n=await fetch(s,{signal:e});if(n.ok){const r=await n.blob();try{const a=new Response(r.slice(),{headers:{"Content-Type":r.type||"image/png","sw-cache-date":Date.now().toString()}});await t.put(s,a)}catch(a){console.warn(`[MediaUtils] Failed to cache image: ${s.substring(0,50)}...`,a)}return r}return console.warn(`[MediaUtils] Network fetch failed: ${s.substring(0,50)}...`,n.status),null}catch(t){return console.warn(`[MediaUtils] Error in fetchImageWithCache: ${s.substring(0,50)}...`,t),null}}function Lt(s){try{const[e,t]=s.split(",");if(!t)return null;const o=e.match(/data:([^;]+)/),n=o?o[1]:"image/png",r=atob(t),a=new Uint8Array(r.length);for(let i=0;i<r.length;i++)a[i]=r.charCodeAt(i);return new Blob([a],{type:n})}catch(e){return console.warn("[MediaUtils] Failed to convert data URL to Blob:",e),null}}async function Fs(s){return new Promise((e,t)=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.onerror=t,o.readAsDataURL(s)})}const Xe=1024*1024,xe=.1,Pe=2048;async function Gs(s,e=Xe){if(s.size<=e)return s;try{const t=await createImageBitmap(s);let{width:o,height:n}=t;const r={width:o,height:n};if(o>Pe||n>Pe){const p=Math.min(Pe/o,Pe/n);o=Math.round(o*p),n=Math.round(n*p)}const a=new OffscreenCanvas(o,n),i=a.getContext("2d");if(!i)return console.warn("[MediaUtils] Failed to get 2d context from OffscreenCanvas"),s;i.drawImage(t,0,0,o,n),t.close();let c=xe,l=.95,d=null,m=0;const y=8;for(let p=0;p<y;p++){const S=(c+l)/2,u=await a.convertToBlob({type:"image/jpeg",quality:S});if(u.size<=e?(d=u,m=S,c=S):l=S,l-c<.02)break}if(d)return d;let w=await a.convertToBlob({type:"image/jpeg",quality:xe}),f=.8;for(;f>=.3&&w.size>e;){const p=Math.round(o*f),S=Math.round(n*f),u=new OffscreenCanvas(p,S),h=u.getContext("2d");if(!h)break;const g=await createImageBitmap(s);h.drawImage(g,0,0,p,S),g.close();let T=xe,_=.95,C=null;for(let D=0;D<6;D++){const b=(T+_)/2,O=await u.convertToBlob({type:"image/jpeg",quality:b});if(O.size<=e?(C=O,T=b):_=b,_-T<.02)break}if(C)return C;w=await u.convertToBlob({type:"image/jpeg",quality:xe}),f-=.1}return w}catch(t){return console.warn("[MediaUtils] Image compression failed, returning original:",t),s}}async function _e(s,e=Xe){const t=await Gs(s,e);return Fs(t)}async function $s(s,e){if(s.startsWith("data:")){if((s.split(",")[1]||"").length*3/4>Xe){const n=Lt(s);if(n){const r=await _e(n);return{originalUrl:s,value:r,isBase64:!0}}}return{originalUrl:s,value:s,isBase64:!0}}try{const t=await caches.open(Ve);if(s.startsWith("/asset-library/")){const o=await t.match(s);if(o){const n=await o.blob(),r=await _e(n);return{originalUrl:s,value:r,isBase64:!0}}return console.warn(`[MediaUtils] Asset library image not found in cache: ${s}`),{originalUrl:s,value:s,isBase64:!1}}if(s.startsWith("/__aitu_cache__/")){const o=`${self.location.origin}${s}`,n=await t.match(o);if(n){const r=await n.blob(),a=await _e(r);return{originalUrl:s,value:a,isBase64:!0}}return console.warn(`[MediaUtils] Cache URL not found in cache: ${s}`),{originalUrl:s,value:s,isBase64:!1}}if(s.startsWith("http://")||s.startsWith("https://")){const o=await t.match(s,{ignoreVary:!0});if(o){const r=await Us(s),a=o.headers.get("sw-cache-date"),i=a?parseInt(a,10):0,c=r??i,l=Date.now(),d=c?l-c:1/0,m=d/(3600*1e3);if(c>0&&d<vs)return{originalUrl:s,value:s,isBase64:!1};const y=await o.blob(),w=await _e(y);return{originalUrl:s,value:w,isBase64:!0}}const n=await fetch(s,{signal:e});if(n.ok){const r=await n.blob();try{const i=new Response(r.slice(),{headers:{"Content-Type":r.type||"image/png","sw-cache-date":Date.now().toString()}});await t.put(s,i)}catch(i){console.warn(`[MediaUtils] Failed to cache image: ${s.substring(0,50)}...`,i)}const a=await _e(r);return{originalUrl:s,value:a,isBase64:!0}}return console.warn(`[MediaUtils] Failed to fetch remote image: ${s.substring(0,50)}...`),{originalUrl:s,value:s,isBase64:!1}}return{originalUrl:s,value:s,isBase64:!1}}catch(t){return console.warn(`[MediaUtils] Error processing reference image: ${s.substring(0,50)}...`,t),{originalUrl:s,value:s,isBase64:!1}}}async function Hs(s,e){return!s||s.length===0?[]:(await Promise.all(s.map(o=>$s(o,e)))).map(o=>o.value)}function It(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=xs(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 Ks(s){return s.startsWith("data:image/")&&s.includes(";base64,")}function zs(s){const e=s.match(/^data:(image\/[^;]+);base64,(.+)$/);return e?{mimeType:e[1],base64:e[2]}:null}async function Ot(s,e="image/png"){try{const t=atob(s),o=new Uint8Array(t.length);for(let d=0;d<t.length;d++)o[d]=t.charCodeAt(d);const n=new Blob([o],{type:e}),r=`img-${Date.now()}-${Math.random().toString(36).substring(2,10)}`,a=e.split("/")[1]||"png",i=`/__aitu_cache__/image/${r}.${a}`,c=await caches.open(Ve),l=new Response(n,{status:200,headers:{"Content-Type":e,"Content-Length":n.size.toString(),"Cache-Control":"max-age=31536000"}});return await c.put(i,l),i}catch(t){return console.error("[cacheBase64Image] Failed to cache image:",t),`data:${e};base64,${s}`}}async function kt(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 Ot(c.b64_json,"image/png"):null}const o=s.data[0],n=await t(o);if(!n)throw(i=o.revised_prompt)!=null&&i.includes("PROHIBITED_CONTENT")?new Error("内容被拒绝:包含违禁内容"):new Error("No image URL in response");const r=s.data.map((c,l)=>t(c)),a=(await Promise.all(r)).filter(Boolean);return{url:n,urls:a.length>1?a:void 0}}async function js(s){if(!Ks(s))return{url:s,migrated:!1};const e=zs(s);if(!e)return{url:s,migrated:!1};try{const t=await Ot(e.base64,e.mimeType);return console.log(`[Migration] Converted Base64 (${Math.round(s.length/1024)}KB) -> ${t}`),{url:t,migrated:!0}}catch(t){return console.error("[Migration] Failed to migrate Base64 URL:",t),{url:s,migrated:!1}}}class Vs{constructor(){this.abortControllers=new Map}async execute(e,t){const o=new AbortController;this.abortControllers.set(e.id,o);try{return t.onProgress(e.id,0,W.SUBMITTING),await this.generateImage(e,t,o.signal)}finally{this.abortControllers.delete(e.id)}}cancel(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e))}async generateImage(e,t,o){const{geminiConfig:n}=t,{params:r}=e,a=r.referenceImages||Ps(r.uploadedImages);let i;a&&a.length>0&&(i=await Hs(a,o));const c=It({prompt:r.prompt,model:r.model,size:r.size,referenceImages:i,isInspirationBoard:r.isInspirationBoard,inspirationBoardImageCount:r.inspirationBoardImageCount},n.modelName);t.onProgress(e.id,10,W.SUBMITTING);const{debugFetch:l}=await Promise.resolve().then(()=>N),{startLLMApiLog:d,completeLLMApiLog:m,failLLMApiLog:y}=await Promise.resolve().then(()=>I),w=Date.now(),f=d({endpoint:"/images/generations",model:n.modelName||"unknown",taskType:"image",prompt:r.prompt,hasReferenceImages:!!i&&i.length>0,referenceImageCount:i==null?void 0:i.length,taskId:e.id}),p=await l(`${n.baseUrl}/images/generations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`},body:JSON.stringify(c),signal:o},{label:`🎨 生成图片 (${n.modelName})`,logRequestBody:!0,logResponseBody:!0});if(!p.ok){const g=await p.text();throw y(f,{httpStatus:p.status,duration:Date.now()-w,errorMessage:g,responseBody:g}),new Error(`Image generation failed: ${p.status} - ${g}`)}t.onProgress(e.id,80,W.DOWNLOADING);const S=await p.json(),u=JSON.stringify(S),{url:h}=await kt(S,e.id);return m(f,{httpStatus:p.status,duration:Date.now()-w,resultType:"image",resultCount:1,resultUrl:h,responseBody:u}),t.onProgress(e.id,100),{url:h,format:"png",size:0,width:r.width,height:r.height}}}class Qs{constructor(){this.abortControllers=new Map,this.pollingIntervals=new Map}async execute(e,t){const o=new AbortController;this.abortControllers.set(e.id,o);try{t.onProgress(e.id,0,W.SUBMITTING);const{response:n,logId:r}=await this.submitVideoGeneration(e,t,o.signal);return t.onRemoteId(e.id,n.id),t.onProgress(e.id,5,W.POLLING),await this.pollUntilComplete(n.id,e.id,t,o.signal,r)}finally{this.cleanup(e.id)}}async resume(e,t){var a,i;if(!e.remoteId)throw new Error("No remote ID for resume");const o=new AbortController;this.abortControllers.set(e.id,o);const{startLLMApiLog:n}=await Promise.resolve().then(()=>I),r=n({endpoint:`/videos/${e.remoteId} (resumed)`,model:((a=e.params)==null?void 0:a.model)||"veo3",taskType:"video",prompt:((i=e.params)==null?void 0:i.prompt)||"",taskId:e.id});try{return t.onProgress(e.id,e.progress||0,W.POLLING),await this.pollUntilComplete(e.remoteId,e.id,t,o.signal,r)}finally{this.cleanup(e.id)}}cancel(e){this.cleanup(e)}async submitVideoGeneration(e,t,o){const{videoConfig:n}=t,{params:r}=e,a=new FormData;a.append("model",r.model||"veo3"),a.append("prompt",r.prompt),r.duration&&a.append("seconds",String(r.duration)),r.size&&a.append("size",r.size);const i=Ns({referenceImages:r.referenceImages,uploadedImages:r.uploadedImages,inputReference:r.inputReference,inputReferences:r.inputReferences});if(i.length>0)for(let u=0;u<i.length;u++){const h=i[u];try{const g=await qs(h,o);g?a.append("input_reference",g,`reference-${u+1}.png`):(console.warn(`[VideoHandler] Failed to get reference image: ${h}`),a.append("input_reference",h))}catch(g){console.warn(`[VideoHandler] Error fetching reference image: ${h}`,g),a.append("input_reference",h)}}const{debugFetch:c}=await Promise.resolve().then(()=>N),{startLLMApiLog:l,completeLLMApiLog:d,failLLMApiLog:m}=await Promise.resolve().then(()=>I),y=Date.now(),w=r.model||"veo3",f=l({endpoint:"/videos",model:w,taskType:"video",prompt:r.prompt,hasReferenceImages:i.length>0,referenceImageCount:i.length,taskId:e.id}),p=await c(`${n.baseUrl}/videos`,{method:"POST",headers:n.apiKey?{Authorization:`Bearer ${n.apiKey}`}:void 0,body:a,signal:o},{label:`🎬 提交视频生成 (${w})`,logResponseBody:!0});if(!p.ok){const u=await p.text();throw m(f,{httpStatus:p.status,duration:Date.now()-y,errorMessage:u,responseBody:u}),new Error(`Video submission failed: ${p.status} - ${u}`)}return{response:await p.json(),logId:f}}async pollUntilComplete(e,t,o,n,r){const{videoConfig:a}=o,i=Date.now();try{const c=await Wt(a.baseUrl,e,{onProgress:(d,m)=>{o.onProgress(t,d,m)},signal:n,apiKey:a.apiKey,interval:5e3,maxAttempts:1080}),l=c.video_url||c.url;if(!l)throw new Error("No video URL in completed response");if(r){const{completeLLMApiLog:d}=await Promise.resolve().then(()=>I);d(r,{httpStatus:200,duration:Date.now()-i,resultType:"video",resultCount:1,resultUrl:l,responseBody:JSON.stringify(c)})}return{url:l,format:"mp4",size:0,width:c.width,height:c.height,duration:parseInt(c.seconds||"0")||0}}catch(c){if(r){const{failLLMApiLog:l}=await Promise.resolve().then(()=>I);l(r,{duration:Date.now()-i,errorMessage:c instanceof Error?c.message:String(c)})}throw c}}cleanup(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e));const o=this.pollingIntervals.get(e);o&&(clearTimeout(o),this.pollingIntervals.delete(e))}}class Xs{constructor(){this.abortControllers=new Map,this.pollingIntervals=new Map}async execute(e,t){const o=new AbortController;this.abortControllers.set(e.id,o);try{t.onProgress(e.id,0,W.SUBMITTING);const{response:n,logId:r}=await this.createCharacter(e,t,o.signal);return t.onRemoteId(e.id,n.id),t.onProgress(e.id,10,W.POLLING),await this.pollUntilComplete(n.id,e.id,t,o.signal,r)}finally{this.cleanup(e.id)}}async resume(e,t){var a;if(!e.remoteId)throw new Error("No remote ID for resume");const o=new AbortController;this.abortControllers.set(e.id,o);const{startLLMApiLog:n}=await Promise.resolve().then(()=>I),r=n({endpoint:`/characters/${e.remoteId} (resumed)`,model:"character-extractor",taskType:"character",prompt:((a=e.params)==null?void 0:a.videoUrl)||"",taskId:e.id});try{return t.onProgress(e.id,e.progress||0,W.POLLING),await this.pollUntilComplete(e.remoteId,e.id,t,o.signal,r)}finally{this.cleanup(e.id)}}cancel(e){this.cleanup(e)}async createCharacter(e,t,o){const{videoConfig:n}=t,{params:r}=e,a=this.getCharacterModel(r.model),i=new FormData;i.append("character_from_task",r.sourceVideoTaskId||""),i.append("model",a),r.characterTimestamps&&i.append("character_timestamps",r.characterTimestamps);const{debugFetch:c}=await Promise.resolve().then(()=>N),{startLLMApiLog:l,completeLLMApiLog:d,failLLMApiLog:m}=await Promise.resolve().then(()=>I),y=Date.now(),w=l({endpoint:"/videos",model:a,taskType:"character",prompt:`角色提取: ${r.sourceVideoTaskId}`,taskId:e.id}),f=await c(`${n.baseUrl}/videos`,{method:"POST",headers:{...n.apiKey?{Authorization:`Bearer ${n.apiKey}`}:{}},body:i,signal:o},{label:`👤 创建角色视频 (${a})`,logResponseBody:!0});if(!f.ok){const S=await f.text();throw m(w,{httpStatus:f.status,duration:Date.now()-y,errorMessage:S,responseBody:S}),new Error(`Character creation failed: ${f.status} - ${S}`)}return{response:await f.json(),logId:w}}async pollUntilComplete(e,t,o,n,r){const{videoConfig:a}=o,i=3e3,c=60,l=Date.now();let d=0;return new Promise((m,y)=>{const w=async()=>{if(n.aborted){if(r){const{failLLMApiLog:f}=await Promise.resolve().then(()=>I);f(r,{duration:Date.now()-l,errorMessage:"Task cancelled"})}y(new Error("Task cancelled"));return}if(d++,d>c){if(r){const{failLLMApiLog:f}=await Promise.resolve().then(()=>I);f(r,{duration:Date.now()-l,errorMessage:"Character creation timeout"})}y(new Error("Character creation timeout"));return}try{const f=await this.queryCharacter(e,a,n),p=Math.min(10+d/c*90,99);if(o.onProgress(t,p,W.POLLING),f.username){if(o.onProgress(t,100),r){const{completeLLMApiLog:u}=await Promise.resolve().then(()=>I);u(r,{httpStatus:200,duration:Date.now()-l,resultType:"character",resultCount:1,resultUrl:f.profile_picture_url,responseBody:JSON.stringify(f)})}m({url:f.profile_picture_url,format:"png",size:0,characterUsername:f.username,characterProfileUrl:f.profile_picture_url,characterPermalink:f.permalink});return}const S=setTimeout(w,i);this.pollingIntervals.set(t,S)}catch(f){if(f instanceof Error&&f.message.includes("404")){const p=setTimeout(w,i);this.pollingIntervals.set(t,p)}else if(d<c){const p=setTimeout(w,i);this.pollingIntervals.set(t,p)}else{if(r){const{failLLMApiLog:p}=await Promise.resolve().then(()=>I);p(r,{duration:Date.now()-l,errorMessage:f instanceof Error?f.message:String(f)})}y(f)}}};w()})}async queryCharacter(e,t,o){const{debugFetch:n}=await Promise.resolve().then(()=>N),r=await n(`${t.baseUrl}/videos/${e}`,{method:"GET",headers:t.apiKey?{Authorization:`Bearer ${t.apiKey}`}:void 0,signal:o},{label:"👤 查询角色状态",logResponseBody:!0});if(!r.ok)throw new Error(`Character query failed: ${r.status}`);return r.json()}getCharacterModel(e){return e==="sora-2-pro"?"sora-2-pro-character":"sora-2-character"}cleanup(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e));const o=this.pollingIntervals.get(e);o&&(clearTimeout(o),this.pollingIntervals.delete(e))}}class Js{constructor(){this.abortControllers=new Map}async execute(e,t){const o=e.params,n=new AbortController;this.abortControllers.set(e.id,n);try{const r=this.convertToGeminiMessages(o),a=await this.streamChat(r,t.geminiConfig,o.temporaryModel,o.systemPrompt,n.signal,void 0);return{url:"",format:"text",size:a.length,chatResponse:a,toolCalls:[]}}finally{this.abortControllers.delete(e.id)}}cancel(e){this.stop(e)}async stream(e,t,o,n){const r=new AbortController;this.abortControllers.set(e,r);try{const a=this.convertToGeminiMessages(t);return await this.streamChat(a,o,t.temporaryModel,t.systemPrompt,r.signal,n)}finally{this.abortControllers.delete(e)}}stop(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e))}convertToGeminiMessages(e){var o;const t=[];e.systemPrompt&&t.push({role:"system",content:[{type:"text",text:e.systemPrompt}]});for(const n of e.messages){const r=[];if(n.content&&r.push({type:"text",text:n.content}),n.attachments)for(const a of n.attachments)a.type==="image"&&r.push({type:"image_url",image_url:{url:`data:${a.mimeType};base64,${a.data}`}});t.push({role:n.role,content:r})}if(e.newContent||(o=e.attachments)!=null&&o.length){const n=[];if(e.newContent&&n.push({type:"text",text:e.newContent}),e.attachments)for(const r of e.attachments)r.type==="image"&&n.push({type:"image_url",image_url:{url:`data:${r.mimeType};base64,${r.data}`}});t.push({role:"user",content:n})}return t}async streamChat(e,t,o,n,r,a){var O,z,X,De,We,ls,us,ds;const i=o||t.modelName||"gemini-2.5-flash",c={model:i,messages:e,stream:!0},{debugFetch:l}=await Promise.resolve().then(()=>N),{startLLMApiLog:d,completeLLMApiLog:m,failLLMApiLog:y}=await Promise.resolve().then(()=>I),w=Date.now(),f=e.filter(H=>H.role==="user").pop(),p=((z=(O=f==null?void 0:f.content)==null?void 0:O[0])==null?void 0:z.text)||"",S=d({endpoint:"/chat/completions",model:i,taskType:"chat",prompt:p,requestBody:JSON.stringify(c,null,2)}),u=await l(`${t.baseUrl}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`},body:JSON.stringify(c),signal:r},{label:`💬 对话请求 (${i})`,logRequestBody:!0,isStreaming:!0});if(!u.ok){const H=await u.text();throw y(S,{httpStatus:u.status,duration:Date.now()-w,errorMessage:H}),new Error(`Chat request failed: ${u.status} - ${H}`)}const h=w,g=S;if(!u.body)throw new Error("No response body");const T=u.body.getReader(),_=new TextDecoder;let C="",D="";try{for(;;){const{done:H,value:hs}=await T.read();if(H)break;D+=_.decode(hs,{stream:!0});const Le=D.split(`
2
- `);D=Le.pop()||"";for(const fs of Le)if(fs.startsWith("data: ")){const gs=fs.slice(6).trim();if(gs==="[DONE]")continue;try{const ps=(We=(De=(X=JSON.parse(gs).choices)==null?void 0:X[0])==null?void 0:De.delta)==null?void 0:We.content;ps&&(C+=ps,a==null||a(C))}catch{}}}if(D.startsWith("data: ")){const H=D.slice(6).trim();if(H&&H!=="[DONE]")try{const Le=(ds=(us=(ls=JSON.parse(H).choices)==null?void 0:ls[0])==null?void 0:us.delta)==null?void 0:ds.content;Le&&(C+=Le,a==null||a(C))}catch{}}}finally{T.releaseLock()}if(u.__debugLogId&&C){const{updateLogResponseBody:H}=await Promise.resolve().then(()=>N);H(u.__debugLogId,C)}const{completeLLMApiLog:b}=await Promise.resolve().then(()=>I);return b(g,{httpStatus:u.status,duration:Date.now()-h,resultType:"text",resultCount:1,resultText:C}),C}}class Ys{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={...ms,...t},this.imageHandler=new Vs,this.videoHandler=new Qs,this.characterHandler=new Xs,this.chatHandler=new Js,this.storageRestorePromise=this.restoreFromStorage()}setTaskStatusChangeCallback(e){this.onTaskStatusChange=e}getGeminiConfig(){return this.geminiConfig}getVideoConfig(){return this.videoConfig}getSW(){return this.sw}async restoreFromStorage(){var e;try{const{geminiConfig:t,videoConfig:o}=await E.loadConfig();t&&o&&(this.geminiConfig=t,this.videoConfig=o,this.initialized=!0);const n=await E.getAllTasks();let r=0;for(const a of n){if(a.status===A.COMPLETED&&((e=a.result)!=null&&e.url)&&a.result.url.startsWith("data:image/")){const{url:i,migrated:c}=await js(a.result.url);c&&(a.result.url=i,await E.updateTask(a),r++)}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)}r>0&&console.log(`[SWTaskQueue] Migrated ${r} Base64 URLs to cache`)}catch(t){console.error("[SWTaskQueue] Failed to restore from storage:",t)}}shouldResumeTask(e){return e.type===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,d;const t=((i=e.error)==null?void 0:i.message)||"",o=((l=(c=e.error)==null?void 0:c.details)==null?void 0:l.originalError)||"",n=((d=e.error)==null?void 0:d.code)||"",r=`${t} ${o}`.toLowerCase();return r.includes("generation_failed")||r.includes("invalid_argument")||r.includes("prohibited")||r.includes("content policy")||r.includes("视频生成失败")||n.includes("generation_failed")||n.includes("INVALID")?!1:r.includes("failed to fetch")||r.includes("network")||r.includes("fetch")||r.includes("timeout")||r.includes("aborted")||r.includes("connection")||r.includes("status query failed")}async resumeTaskExecution(e){if(this.initialized){if(e.remoteId&&(e.type===L.VIDEO||e.type===L.CHARACTER))e.status===A.FAILED&&(e.status=A.PROCESSING,e.error=void 0,e.executionPhase=W.POLLING,e.updatedAt=Date.now(),this.tasks.set(e.id,e),await E.saveTask(e)),this.runningTasks.add(e.id),this.broadcastToClients({type:"TASK_STATUS",taskId:e.id,status:A.PROCESSING,progress:e.progress,phase:W.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}=await Promise.resolve().then(()=>I),o=await t(e.id);if(o&&o.resultUrl){let n,r,a;if(o.responseBody)try{const i=JSON.parse(o.responseBody);n=i.width,r=i.height,a=parseInt(i.seconds||"0")||0}catch{}await this.handleTaskSuccess(e.id,{url:o.resultUrl,format:e.type===L.VIDEO?"mp4":"png",size:0,width:n,height:r,duration:a});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(()=>I),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 E.saveConfig(e,t),this.broadcastToClients({type:"TASK_QUEUE_INITIALIZED",success:!0}),this.syncTasksToClients();for(const o of this.tasks.values())this.shouldResumeTask(o)&&!this.runningTasks.has(o.id)&&this.resumeTaskExecution(o);this.processQueue()}async updateConfig(e,t){e&&this.geminiConfig&&(this.geminiConfig={...this.geminiConfig,...e}),t&&this.videoConfig&&(this.videoConfig={...this.videoConfig,...t}),await E.saveConfig(this.geminiConfig,this.videoConfig)}async submitTask(e,t,o,n){if(this.tasks.has(e)){console.warn(`[SWTaskQueue] Task ${e} already exists`);return}const r=Date.now(),a={id:e,type:t,status:A.PENDING,params:o,createdAt:r,updatedAt:r};this.tasks.set(e,a),await E.saveTask(a),this.broadcastToClients({type:"TASK_CREATED",task:a}),this.processQueue()}async cancelTask(e){var o;const t=this.tasks.get(e);t&&(this.runningTasks.has(e)&&((o=this.getHandler(t.type))==null||o.cancel(e),this.runningTasks.delete(e)),t.status=A.CANCELLED,t.updatedAt=Date.now(),this.tasks.set(e,t),await E.saveTask(t),this.broadcastToClients({type:"TASK_CANCELLED",taskId:e}))}async retryTask(e){const t=this.tasks.get(e);!t||t.status!==A.FAILED&&t.status!==A.CANCELLED||(t.status=A.PENDING,t.error=void 0,t.updatedAt=Date.now(),this.tasks.set(e,t),await E.saveTask(t),this.broadcastToClients({type:"TASK_STATUS",taskId:t.id,status:t.status,updatedAt:t.updatedAt}),this.processQueue())}async resumeTask(e,t,o,n){let r=this.tasks.get(e);if(!r){const a=Date.now();r={id:e,type:o,status:A.PROCESSING,params:{prompt:""},createdAt:a,updatedAt:a,remoteId:t,executionPhase:W.POLLING},this.tasks.set(e,r),await E.saveTask(r)}(o===L.VIDEO||o===L.CHARACTER)&&(this.runningTasks.add(e),this.executeResume(r,t))}getTask(e){return this.tasks.get(e)||null}getAllTasks(){return Array.from(this.tasks.values())}async deleteTask(e){var o;const t=this.tasks.get(e);t&&(this.runningTasks.has(e)&&((o=this.getHandler(t.type))==null||o.cancel(e),this.runningTasks.delete(e)),this.tasks.delete(e),await E.deleteTask(e),this.broadcastToClients({type:"TASK_DELETED",taskId:e}))}async markTaskInserted(e){const t=this.tasks.get(e);if(!t)return;const o={...t,insertedToCanvas:!0,updatedAt:Date.now()};this.tasks.set(e,o),await E.saveTask(o)}async restoreTasks(e){for(const t of e)t.status!==A.COMPLETED&&t.status!==A.CANCELLED&&(this.tasks.set(t.id,t),await E.saveTask(t));this.processQueue()}async startChat(e,t,o){if(!this.geminiConfig){this.broadcastToClients({type:"CHAT_ERROR",chatId:e,error:"Gemini config not initialized"});return}try{const n=await this.chatHandler.stream(e,t,this.geminiConfig,a=>{this.broadcastToClients({type:"CHAT_CHUNK",chatId:e,content:a})});this.chatResultCache.set(e,{chatId:e,fullContent:n,timestamp:Date.now(),delivered:!1}),this.broadcastToClients({type:"CHAT_DONE",chatId:e,fullContent:n});const r=this.chatResultCache.get(e);r&&(r.delivered=!0),this.cleanupChatCache()}catch(n){this.broadcastToClients({type:"CHAT_ERROR",chatId:e,error:n instanceof Error?n.message:String(n)})}}getCachedChatResult(e){return this.chatResultCache.get(e)}getAllCachedChatResults(){return Array.from(this.chatResultCache.values())}cleanupChatCache(){const e=Date.now();for(const[t,o]of this.chatResultCache.entries())e-o.timestamp>this.CHAT_CACHE_TTL&&this.chatResultCache.delete(t)}stopChat(e){this.chatHandler.stop(e)}syncTasksToClients(){const e=this.getAllTasks();this.broadcastToClients({type:"TASK_ALL_RESPONSE",tasks:e})}async getTasksPaginated(e){return E.getTasksPaginated(e)}async syncPaginatedTasksToClients(e){const t=await this.getTasksPaginated(e);this.broadcastToClients({type:"TASK_PAGINATED_RESPONSE",tasks:t.tasks,total:t.total,offset:e.offset,hasMore:t.hasMore})}processQueue(){if(!this.initialized){console.warn("[SWTaskQueue] Not initialized, skipping queue processing");return}const e=Array.from(this.tasks.values()).filter(t=>t.status===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}this.runningTasks.add(e.id),e.status=A.PROCESSING,e.startedAt=Date.now(),e.updatedAt=Date.now(),e.executionPhase=W.SUBMITTING,this.tasks.set(e.id,e),await E.saveTask(e),this.broadcastToClients({type:"TASK_STATUS",taskId:e.id,status:e.status,phase:e.executionPhase,updatedAt:e.updatedAt});const t={geminiConfig:this.geminiConfig,videoConfig:this.videoConfig,onProgress:async(o,n,r)=>{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=n,r&&(a.executionPhase=r),a.updatedAt=Date.now(),this.tasks.set(o,a),await E.saveTask(a);const c=this.tasks.get(o);c&&c.status===i&&this.broadcastToClients({type:"TASK_STATUS",taskId:o,status:i,progress:n,phase:r,updatedAt:a.updatedAt})}},onRemoteId:async(o,n)=>{const r=this.tasks.get(o);r&&(r.remoteId=n,r.executionPhase=W.POLLING,r.updatedAt=Date.now(),this.tasks.set(o,r),await E.saveTask(r),this.broadcastToClients({type:"TASK_SUBMITTED",taskId:o,remoteId:n}))}};try{const o=this.getHandler(e.type);if(!o)throw new Error(`No handler for task type: ${e.type}`);const n=this.config.timeouts[e.type]||600*1e3,r=await Promise.race([o.execute(e,t),new Promise((a,i)=>{setTimeout(()=>{var c;(c=o.cancel)==null||c.call(o,e.id),i(new Error(`Task timeout after ${Math.round(n/6e4)} minutes`))},n)})]);await this.handleTaskSuccess(e.id,r)}catch(o){await this.handleTaskError(e.id,o)}}async executeResume(e,t){if(!this.geminiConfig||!this.videoConfig)return;const o={geminiConfig:this.geminiConfig,videoConfig:this.videoConfig,onProgress:async(n,r,a)=>{const i=this.tasks.get(n);if(i&&i.status!==A.COMPLETED&&i.status!==A.FAILED&&i.status!==A.CANCELLED){const c=i.status;i.progress=r,a&&(i.executionPhase=a),i.updatedAt=Date.now(),this.tasks.set(n,i),await E.saveTask(i);const l=this.tasks.get(n);l&&l.status===c&&this.broadcastToClients({type:"TASK_STATUS",taskId:n,status:c,progress:r,phase:a,updatedAt:i.updatedAt})}},onRemoteId:()=>{}};try{const n=this.getHandler(e.type);if(!(n!=null&&n.resume))throw new Error(`Handler does not support resume: ${e.type}`);e.remoteId=t;const r=await n.resume(e,o);await this.handleTaskSuccess(e.id,r)}catch(n){console.error(`[SWTaskQueue] executeResume: 任务 ${e.id} 恢复失败`,n),await this.handleTaskError(e.id,n)}}async handleTaskSuccess(e,t){var n;const o=this.tasks.get(e);o&&(o.status=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 E.saveTask(o),this.broadcastToClients({type:"TASK_COMPLETED",taskId:e,result:t,completedAt:o.completedAt}),(n=this.onTaskStatusChange)==null||n.call(this,e,"completed",t),this.processQueue())}async handleTaskError(e,t){var r;const o=this.tasks.get(e);if(!o)return;this.runningTasks.delete(e);const n={code:"EXECUTION_ERROR",message:t instanceof Error?t.message:String(t),details:{originalError:t instanceof Error?t.stack:String(t),timestamp:Date.now()}};o.status=A.FAILED,o.error=n,o.updatedAt=Date.now(),this.tasks.set(e,o),await E.saveTask(o),this.broadcastToClients({type:"TASK_FAILED",taskId:e,error:n}),(r=this.onTaskStatusChange)==null||r.call(this,e,"failed",void 0,n.message),this.processQueue()}async markTaskFailed(e,t){const o=this.tasks.get(e);o&&(o.status=A.FAILED,o.error=t,o.updatedAt=Date.now(),this.tasks.set(e,o),await E.saveTask(o),this.broadcastToClients({type:"TASK_FAILED",taskId:e,error:t}))}getHandler(e){switch(e){case L.IMAGE:case L.INSPIRATION_BOARD:return this.imageHandler;case L.VIDEO:return this.videoHandler;case L.CHARACTER:return this.characterHandler;case L.CHAT:return this.chatHandler;default:return null}}async broadcastToClients(e){try{const t=await this.sw.clients.matchAll({type:"window"});for(const o of t)At(o,e)}catch(t){console.error("[SWTaskQueue] Failed to broadcast:",t)}}}let Ne=null;function Zs(s,e){return Ne||(Ne=new Ys(s,e)),Ne}function Je(){return Ne}function eo(s,e){var o,n;const t=Je();if(!t&&s.type!=="TASK_QUEUE_INIT"){console.warn("[SWTaskQueue] Queue not initialized");return}switch(s.type){case"TASK_QUEUE_INIT":t&&t.initialize(s.geminiConfig,s.videoConfig);break;case"TASK_QUEUE_UPDATE_CONFIG":t==null||t.updateConfig(s.geminiConfig,s.videoConfig);break;case"TASK_SUBMIT":t==null||t.submitTask(s.taskId,s.taskType,s.params,e);break;case"TASK_CANCEL":t==null||t.cancelTask(s.taskId);break;case"TASK_RETRY":t==null||t.retryTask(s.taskId);break;case"TASK_RESUME":t==null||t.resumeTask(s.taskId,s.remoteId,s.taskType,e);break;case"TASK_GET_STATUS":{t==null||t.syncTasksToClients();break}case"TASK_GET_ALL":{t==null||t.syncTasksToClients();break}case"TASK_GET_PAGINATED":{t==null||t.syncPaginatedTasksToClients({offset:s.offset,limit:s.limit,status:(o=s.filters)==null?void 0:o.status,type:(n=s.filters)==null?void 0:n.type,sortOrder:s.sortOrder});break}case"TASK_DELETE":t==null||t.deleteTask(s.taskId);break;case"TASK_MARK_INSERTED":t==null||t.markTaskInserted(s.taskId);break;case"CHAT_START":t==null||t.startChat(s.chatId,s.params,e);break;case"CHAT_STOP":t==null||t.stopChat(s.chatId);break;case"CHAT_GET_CACHED":{const r=t==null?void 0:t.getCachedChatResult(s.chatId);r?Me(e,{type:"CHAT_CACHED_RESULT",chatId:s.chatId,fullContent:r.fullContent,found:!0}).then(a=>{a||console.warn("[SWTaskQueue] Failed to send CHAT_CACHED_RESULT to client:",e)}):Me(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(()=>xr).then(({executeMCPTool:r})=>{const a=Je(),i=a==null?void 0:a.getGeminiConfig(),c=a==null?void 0:a.getVideoConfig(),l=a==null?void 0:a.getSW();a&&i&&c&&l?r(s.requestId,s.toolName,s.args,i,c,e,l):l==null||l.clients.get(e).then(d=>{d&&d.postMessage({type:"MCP_TOOL_RESULT",requestId:s.requestId,success:!1,error:"Task queue not initialized",resultType:"error"})})});break}}}const to={name:"generate_image",description:"Generate images using AI",async execute(s,e){const{geminiConfig:t,onProgress:o,signal:n}=e,{prompt:r,size:a,referenceImages:i,quality:c,model:l,count:d=1}=s;if(!r)return{success:!1,error:"缺少必填参数 prompt",type:"error"};try{o==null||o(0,W.SUBMITTING);const m=It({prompt:r,model:l,size:a,referenceImages:i,quality:c,n:Math.min(Math.max(1,d),10)},t.modelName);o==null||o(10,W.SUBMITTING);const{debugFetch:y}=await Promise.resolve().then(()=>N),w=await y(`${t.baseUrl}/images/generations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`},body:JSON.stringify(m),signal:n},{label:`🎨 生成图片 (${t.modelName})`,logRequestBody:!0,logResponseBody:!0});if(!w.ok){const u=await w.text();throw console.error("[SW:generateImage] ✗ API error:",w.status,u.substring(0,200)),new Error(`Image generation failed: ${w.status} - ${u}`)}o==null||o(80,W.DOWNLOADING);const f=await w.json(),{url:p,urls:S}=await kt(f);return o==null||o(100),{success:!0,type:"image",data:{url:p,urls:S,format:"png",prompt:r,size:a||"1x1"}}}catch(m){return console.error("[SW:generateImage] Error:",m),{success:!1,error:m.message||"图片生成失败",type:"error"}}}},so={name:"generate_video",description:"Generate videos using AI",async execute(s,e){const{videoConfig:t,onProgress:o,onRemoteId:n,signal:r}=e,{prompt:a,model:i="veo3",seconds:c="8",size:l="1280x720",inputReference:d,inputReferences:m,referenceImages:y}=s;if(!a)return{success:!1,error:"缺少必填参数 prompt",type:"error"};try{o==null||o(0,W.SUBMITTING);const w={model:i,prompt:a,seconds:c,size:l},f=[];m&&m.length>0?m.forEach(T=>{const _=typeof T=="string"?T:T==null?void 0:T.url;_&&f.push(_)}):y&&y.length>0?f.push(...y):d&&f.push(d),f.length>0&&(f.length===1?w.input_reference=f[0]:w.input_references=f);const{debugFetch:p}=await Promise.resolve().then(()=>N),S=await p(`${t.baseUrl}/videos/generations`,{method:"POST",headers:{"Content-Type":"application/json",...t.apiKey?{Authorization:`Bearer ${t.apiKey}`}:{}},body:JSON.stringify(w),signal:r},{label:`🎬 提交视频生成 (${t.model||"default"})`,logRequestBody:!0,logResponseBody:!0});if(!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 u=await S.json(),h=u.id||u.video_id;if(!h)throw console.error("[SW:generateVideo] ✗ No video ID in response:",u),new Error("No video ID in response");n==null||n(h),o==null||o(10,W.POLLING);const g=await Wt(t.baseUrl,h,{onProgress:o,signal:r,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(w){return console.error("[SW:generateVideo] ✗ Error:",w.message),{success:!1,error:w.message||"视频生成失败",type:"error"}}}},Mt=new Map([["generate_image",to],["generate_video",so]]);function xt(s){return Mt.get(s)}async function Ye(s,e,t){const o=Mt.get(s);return o?o.execute(e,t):{success:!1,error:`Unknown tool: ${s}`,type:"error"}}function Ze(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 oo{constructor(e){this.workflows=new Map,this.runningWorkflows=new Set,this.abortControllers=new Map,this.pendingToolRequests=new Map,this.config=e,this.restoreFromStorage()}async restoreFromStorage(){try{const e=await E.getAllWorkflows();for(const t of e){if(t.status==="completed"||t.status==="cancelled"||t.status==="failed"){this.workflows.set(t.id,t);continue}(t.status==="running"||t.status==="pending")&&await this.handleInterruptedWorkflow(t)}}catch(e){console.error("[WorkflowExecutor] Failed to restore from storage:",e)}}async handleInterruptedWorkflow(e){const t=e.steps.find(o=>o.status==="running");e.status="failed",e.error=t?`工作流在步骤 "${t.description||t.mcp}" 执行时中断,请重试`:"工作流执行时中断,请重试",e.updatedAt=Date.now(),t&&(t.status="failed",t.error="Service Worker 重启导致执行中断"),this.workflows.set(e.id,e),await E.saveWorkflow(e),await E.deletePendingToolRequestsByWorkflow(e.id)}updateConfig(e){this.config={...this.config,...e}}async handleMainThreadToolResponse(e){var o;console.log("[SW-WorkflowExecutor] ◀ Received tool response:",{requestId:e.requestId,success:e.success,hasPending:this.pendingToolRequests.has(e.requestId),hasAddSteps:!!((o=e.addSteps)!=null&&o.length),timestamp:new Date().toISOString()});const t=this.pendingToolRequests.get(e.requestId);if(t)console.log("[SW-WorkflowExecutor] ✓ Resolving pending tool request:",e.requestId),this.pendingToolRequests.delete(e.requestId),t.resolve(e);else{console.log("[SW-WorkflowExecutor] Tool response received after SW restart, attempting recovery:",e.requestId);const n=await E.getPendingToolRequest(e.requestId);if(!n){console.log("[SW-WorkflowExecutor] No stored request found for:",e.requestId);return}console.log("[SW-WorkflowExecutor] Found stored request:",{workflowId:n.workflowId,stepId:n.stepId,toolName:n.toolName});let r=this.workflows.get(n.workflowId);if(r||(r=await E.getWorkflow(n.workflowId),r&&this.workflows.set(r.id,r)),!r){console.log("[SW-WorkflowExecutor] Workflow not found:",n.workflowId),await E.deletePendingToolRequest(e.requestId);return}const a=r.steps.find(i=>i.id===n.stepId);if(!a){console.log("[SW-WorkflowExecutor] Step not found:",n.stepId),await E.deletePendingToolRequest(e.requestId);return}if(e.success){a.status="completed",a.result={success:!0,type:"text",data:e.result};const i=e.addSteps;if(i&&i.length>0){console.log("[SW-WorkflowExecutor] Adding",i.length,"new steps from recovered response");const c=[];for(const l of i)r.steps.find(d=>d.id===l.id)||(r.steps.push({id:l.id,mcp:l.mcp,args:l.args,description:l.description,status:l.status||"pending"}),c.push(l));c.length>0&&this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:r.id,steps:c})}await E.saveWorkflow(r),this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:r.id,stepId:a.id,status:"completed",result:a.result})}else{a.status="failed",a.error=e.error||"Unknown error",a.result={success:!1,type:"error",error:a.error},await E.saveWorkflow(r),this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:r.id,stepId:a.id,status:"failed",error:a.error}),this.config.broadcast({type:"WORKFLOW_FAILED",workflowId:r.id,error:a.error}),await E.deletePendingToolRequest(e.requestId);return}await E.deletePendingToolRequest(e.requestId),console.log("[SW-WorkflowExecutor] Continuing workflow execution after recovery:",r.id),await this.executeWorkflow(r)}}async updateWorkflowStepForTask(e,t,o,n){for(const r of this.workflows.values()){const a=r.steps.find(i=>{var l;const c=i.result;return(c==null?void 0:c.taskId)===e||((l=c==null?void 0:c.taskIds)==null?void 0:l.includes(e))});if(a){a.status=t,t==="completed"&&o?a.result={...a.result,success:!0,data:o}:t==="failed"&&(a.error=n,a.result={...a.result,success:!1,error:n}),a.updatedAt=Date.now(),r.updatedAt=Date.now(),await E.saveWorkflow(r),this.broadcastStepStatus(r.id,a),r.status==="running"&&this.executeWorkflow(r.id);return}}}broadcastRecoveredWorkflows(){for(const e of this.workflows.values())this.config.broadcast({type:"WORKFLOW_RECOVERED",workflowId:e.id,workflow:e})}resendPendingToolRequests(){if(this.pendingToolRequests.size===0)return;const e=[];console.log("[SW-WorkflowExecutor] resendPendingToolRequests:",{pendingCount:this.pendingToolRequests.size,pendingTools:Array.from(this.pendingToolRequests.values()).map(t=>({toolName:t.requestInfo.toolName,workflowId:t.requestInfo.workflowId})),timestamp:new Date().toISOString()});for(const[,t]of this.pendingToolRequests){const{requestInfo:o}=t;if(e.includes(o.toolName)){console.log("[SW-WorkflowExecutor] Skipping resend for tool (already in progress):",{toolName:o.toolName,workflowId:o.workflowId,requestId:o.requestId});continue}this.config.broadcast({type:"MAIN_THREAD_TOOL_REQUEST",requestId:o.requestId,workflowId:o.workflowId,stepId:o.stepId,toolName:o.toolName,args:o.args})}}cancelAllPendingToolRequests(){if(this.pendingToolRequests.size!==0){for(const[e,t]of this.pendingToolRequests)t.reject(new Error("页面刷新导致请求中断,请重试"));this.pendingToolRequests.clear()}}async submitWorkflow(e){var o,n;console.log("[SW-WorkflowExecutor] submitWorkflow:",{workflowId:e.id,existingWorkflowsCount:this.workflows.size,hasContext:!!e.context,referenceImagesCount:((n=(o=e.context)==null?void 0:o.referenceImages)==null?void 0:n.length)||0,timestamp:new Date().toISOString()});const t=this.workflows.get(e.id);if(t){if(t.status==="running"||t.status==="pending"){console.log(`[SW-WorkflowExecutor] Re-claiming active workflow ${e.id}, status: ${t.status}`),this.broadcastWorkflowStatus(t),t.steps.forEach(r=>this.broadcastStepStatus(t.id,r));return}console.warn(`[SW-WorkflowExecutor] Workflow ${e.id} already exists with terminal status ${t.status}, skipping`),this.broadcastWorkflowStatus(t);return}console.log("[SW-WorkflowExecutor] ✓ New workflow, starting execution:",e.id),e.status="pending",e.updatedAt=Date.now(),this.workflows.set(e.id,e),await E.saveWorkflow(e),this.executeWorkflow(e.id)}async cancelWorkflow(e){const t=this.workflows.get(e);if(!t)return;const o=this.abortControllers.get(e);o&&(o.abort(),this.abortControllers.delete(e)),t.status="cancelled",t.updatedAt=Date.now(),this.runningWorkflows.delete(e),await E.saveWorkflow(t),await E.deletePendingToolRequestsByWorkflow(e),this.broadcastWorkflowStatus(t)}getWorkflow(e){return this.workflows.get(e)}getAllWorkflows(){return Array.from(this.workflows.values())}async executeWorkflow(e){console.log("[SW-WorkflowExecutor] executeWorkflow called:",{workflowId:e,timestamp:new Date().toISOString()});const t=this.workflows.get(e);if(!t){console.error(`[WorkflowExecutor] ✗ Workflow ${e} not found`);return}if(this.runningWorkflows.has(e)){console.warn(`[SW-WorkflowExecutor] Workflow ${e} is already running, skipping duplicate execution`);return}this.runningWorkflows.add(e),console.log(`[SW-WorkflowExecutor] ▶ Starting workflow execution: ${e}`);const o=new AbortController;this.abortControllers.set(e,o),t.status="running",t.updatedAt=Date.now(),await E.saveWorkflow(t),this.broadcastWorkflowStatus(t);try{let n=0;for(;;){const a=t.steps.filter(c=>c.status==="completed"||c.status==="failed"||c.status==="skipped"||c.status==="running"?!1:c.dependsOn&&c.dependsOn.length>0?c.dependsOn.every(l=>{const d=t.steps.find(m=>m.id===l);return d&&(d.status==="completed"||d.status==="skipped")}):!0),i=t.steps.some(c=>c.status==="running");if(a.length===0){if(i||t.steps.every(l=>l.status==="completed"||l.status==="failed"||l.status==="skipped"))break;console.warn("[WorkflowExecutor] Workflow stuck: no executable steps and none running");break}for(const c of a){if(o.signal.aborted)throw new Error("Workflow cancelled");if(n++,await this.executeStep(t,c,o.signal),c.status==="failed")throw console.error(`[WorkflowExecutor] ✗ Step ${c.id} failed: ${c.error}`),new Error(`Step ${c.id} failed: ${c.error}`);c.status}}t.steps.every(a=>a.status==="completed"||a.status==="failed"||a.status==="skipped")?(t.status="completed",t.completedAt=Date.now(),t.updatedAt=Date.now(),await E.saveWorkflow(t),this.config.broadcast({type:"WORKFLOW_COMPLETED",workflowId:e,workflow:t})):await E.saveWorkflow(t)}catch(n){console.error(`[WorkflowExecutor] ✗ Workflow ${e} failed:`,n),t.status="failed",t.error=n.message,t.updatedAt=Date.now(),await E.saveWorkflow(t),this.config.broadcast({type:"WORKFLOW_FAILED",workflowId:e,error:n.message})}finally{this.runningWorkflows.delete(e),this.abortControllers.delete(e)}}replaceImagePlaceholders(e,t){if(!t||t.length===0)return e;const o=n=>{if(typeof n=="string"){let r=n.replace(/\[图片(\d+)\]/g,(a,i)=>{const c=parseInt(i,10)-1;return c>=0&&c<t.length?t[c]:a});return r=r.replace(/\[Image\s*(\d+)\]/gi,(a,i)=>{const c=parseInt(i,10)-1;return c>=0&&c<t.length?t[c]:a}),r}if(Array.isArray(n))return n.map(r=>o(r));if(n&&typeof n=="object"){const r={};for(const[a,i]of Object.entries(n))r[a]=o(i);return r}return n};return o(e)}async executeStep(e,t,o){var l,d,m,y,w,f;console.log("[SW-WorkflowExecutor] executeStep:",{workflowId:e.id,stepId:t.id,mcp:t.mcp,hasContext:!!e.context,referenceImagesCount:((d=(l=e.context)==null?void 0:l.referenceImages)==null?void 0:d.length)||0,timestamp:new Date().toISOString()});const n=Date.now(),r=((m=e.context)==null?void 0:m.referenceImages)||[];(t.mcp==="generate_image"||t.mcp==="generate_video")&&console.log("[SW-WorkflowExecutor] Image/Video step args before processing:",{stepId:t.id,referenceImagesInContext:r.length,referenceImagesValues:r.slice(0,2).map(p=>p.substring(0,50)+"..."),argsReferenceImages:t.args.referenceImages});const a=this.replaceImagePlaceholders(t.args,r),i=JSON.stringify(t.args),c=JSON.stringify(a);i!==c?(console.log("[SW-WorkflowExecutor] ✓ Replaced image placeholders:",{stepId:t.id,referenceImagesCount:r.length}),t.args=a):r.length>0&&(t.mcp==="generate_image"||t.mcp==="generate_video")&&console.log("[SW-WorkflowExecutor] No placeholders replaced (args unchanged):",{stepId:t.id,referenceImagesCount:r.length}),t.status="running",await E.saveWorkflow(e),this.broadcastStepStatus(e.id,t);try{if(Ze(t.mcp)||!xt(t.mcp)){const p=await this.requestMainThreadTool(e.id,t.id,t.mcp,t.args);if(!p.success)throw new Error(p.error||"Main thread tool execution failed");if(p.addSteps&&p.addSteps.length>0){const u=[];for(const h of p.addSteps)e.steps.find(g=>g.id===h.id)||(e.steps.push({id:h.id,mcp:h.mcp,args:h.args,description:h.description,status:h.status}),u.push(h));u.length>0&&(await E.saveWorkflow(e),this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:e.id,steps:u}))}const S=p.result;if((t.mcp==="generate_image"||t.mcp==="generate_video")&&p.taskId){t.result={success:!0,type:t.mcp==="generate_image"?"image":"video",data:S,taskId:p.taskId,taskIds:p.taskIds},t.status="running",t.duration=Date.now()-n,this.broadcastStepStatus(e.id,t);return}t.result={success:!0,type:(S==null?void 0:S.type)||"text",data:S}}else{const p={geminiConfig:this.config.geminiConfig,videoConfig:this.config.videoConfig,signal:o,onProgress:(u,h)=>{},onRemoteId:u=>{}},S=await Ye(t.mcp,t.args,p);if(S.success&&S.type==="canvas"&&((y=S.data)!=null&&y.delegateToMainThread)){const u=await this.requestCanvasOperation(S.data.operation,S.data.args);if(!u.success)throw new Error(u.error||"Canvas operation failed");t.result={success:!0,type:"canvas",data:{completed:!0}}}else if(S.success&&S.type==="image"&&((w=S.data)!=null&&w.url)){const u=S.data,h=await this.requestCanvasOperation("canvas_insert",{items:[{type:"image",url:u.url}]});h.success||console.warn("[WorkflowExecutor] Failed to insert image to canvas:",h.error),t.result={success:!0,type:"image",data:S.data}}else if(S.success&&S.type==="video"&&((f=S.data)!=null&&f.url)){const u=S.data,h=await this.requestCanvasOperation("canvas_insert",{items:[{type:"video",url:u.url}]});h.success||console.warn("[WorkflowExecutor] Failed to insert video to canvas:",h.error),t.result={success:!0,type:"video",data:S.data}}else if(t.result={success:S.success,type:S.type||"text",data:S.data,error:S.error},!S.success)throw new Error(S.error||"Step execution failed");if(S.addSteps&&S.addSteps.length>0){console.log(`[SW-WorkflowExecutor] Adding ${S.addSteps.length} new steps from ${t.mcp}`);const u=[];for(const h of S.addSteps)e.steps.find(g=>g.id===h.id)||(e.steps.push({id:h.id,mcp:h.mcp,args:h.args,description:h.description,status:h.status}),u.push(h));u.length>0&&this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:e.id,steps:u})}}t.status="completed",t.duration=Date.now()-n}catch(p){t.status="failed",t.error=p.message,t.duration=Date.now()-n,t.result={success:!1,type:"error",error:p.message}}await E.saveWorkflow(e),this.broadcastStepStatus(e.id,t)}async requestMainThreadTool(e,t,o,n){if(this.config.requestMainThreadTool)return this.config.requestMainThreadTool(e,t,o,n);const r=`tool_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return new Promise((a,i)=>{const c=setTimeout(()=>{this.pendingToolRequests.delete(r),i(new Error(`Main thread tool request timed out: ${o}`))},3e5);this.pendingToolRequests.set(r,{resolve:l=>{clearTimeout(c),E.deletePendingToolRequest(r),a(l)},reject:l=>{clearTimeout(c),E.deletePendingToolRequest(r),i(l)},requestInfo:{requestId:r,workflowId:e,stepId:t,toolName:o,args:n},timeout:c}),E.savePendingToolRequest({requestId:r,workflowId:e,stepId:t,toolName:o,args:n,createdAt:Date.now()}),this.config.broadcast({type:"MAIN_THREAD_TOOL_REQUEST",requestId:r,workflowId:e,stepId:t,toolName:o,args:n})})}async requestCanvasOperation(e,t){if(this.config.requestCanvasOperation)return this.config.requestCanvasOperation(e,t);const o=`canvas_${Date.now()}_${Math.random().toString(36).substr(2,9)}`;return this.config.broadcast({type:"CANVAS_OPERATION_REQUEST",requestId:o,operation:e,params:t}),{success:!0}}broadcastWorkflowStatus(e){this.config.broadcast({type:"WORKFLOW_STATUS",workflowId:e.id,status:e.status,updatedAt:e.updatedAt})}broadcastStepStatus(e,t){this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:e,stepId:t.id,status:t.status,result:t.result,error:t.error,duration:t.duration})}}function Pt(s=0){return`tc_${Date.now()}_${s}_${Math.random().toString(36).substr(2,9)}`}function oe(s){const e=s.trim();try{return JSON.parse(e)}catch{try{return JSON.parse(io(e))}catch{return null}}}function Nt(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 ro(s){const e=s.trim();if(!e.startsWith("{")||!e.endsWith("}")||!e.includes('"content"')||!e.includes('"next"'))return!1;let t=0,o=0,n=!1,r=!1;for(const a of e){if(r){r=!1;continue}if(a==="\\"){r=!0;continue}if(a==='"'){n=!n;continue}n||(a==="{"?t++:a==="}"?t--:a==="["?o++:a==="]"&&o--)}return t===0&&o===0}function vt(s){const e=Nt(s);if(!ro(e))return null;let t=oe(e);if(!t){const r=e.match(/\{\s*"content"\s*:\s*"[^"]*"\s*,\s*"next"\s*:\s*\[[\s\S]*?\]\s*\}/);r&&(t=oe(r[0]))}if(!t){const r=e.match(/\{[\s\S]*"content"[\s\S]*"next"[\s\S]*\}/);r&&(t=oe(r[0]))}if(!t||typeof t.content!="string")return null;const n=(Array.isArray(t.next)?t.next:[]).filter(r=>typeof r=="object"&&r!==null&&typeof r.mcp=="string"&&typeof r.args=="object").map(r=>({mcp:r.mcp,args:r.args}));return{content:t.content,next:n}}function no(s){const e=vt(s);if(e&&e.next.length>0)return e.next.map((a,i)=>({id:Pt(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:Pt(),name:a.name,arguments:typeof i=="object"&&i!==null?i:{}}},n=/```tool_call\s*\n?([\s\S]*?)\n?```/gi;let r;for(;(r=n.exec(s))!==null;){const a=oe(r[1]);if(a){const i=o(a);i&&t.push(i)}}if(t.length===0){const a=/```(?:json)?\s*\n?([\s\S]*?)\n?```/gi;for(;(r=a.exec(s))!==null;){const i=oe(r[1]);if(i){const c=o(i);c&&t.push(c)}}}if(t.length===0){const a=/<tool_call>([\s\S]*?)<\/tool_call>/gi;for(;(r=a.exec(s))!==null;){const i=oe(r[1]);if(i){const c=o(i);c&&t.push(c)}}}if(t.length===0){const a=/\{[\s\S]*?"name"\s*:\s*"(?:generate_image|generate_video|generate_grid_image|generate_photo_wall)"[\s\S]*?\}/g;for(;(r=a.exec(s))!==null;){const i=oe(r[0]);if(i){const c=o(i);if(c){t.push(c);break}}}}return t}function ao(s){const e=vt(s);if(e)return e.content;let t=Nt(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||{}),W=(s=>(s.SUBMITTING="submitting",s.POLLING="polling",s.DOWNLOADING="downloading",s))(W||{});const ws={timeouts:{image:600*1e3,video:1200*1e3,character:600*1e3,inspiration_board:600*1e3,chat:600*1e3}},He="sw-task-queue",wt=2,k="tasks",K="config",N="workflows",B="chat-workflows",U="pending-tool-requests",Ss=[k,K,N,B,U];function ys(){return new Promise(s=>{const e=indexedDB.open(He);e.onsuccess=()=>{const t=e.result,o=t.version;t.close(),s(Math.max(o,wt))},e.onerror=()=>{s(wt)}})}function Ts(s){const e=[];for(const t of Ss)s.objectStoreNames.contains(t)||e.push(t);return e}function Es(s){return new Promise((e,t)=>{const o=s+1;console.log(`[SWStorage] Repairing database: upgrading from v${s} to v${o}`);const n=indexedDB.open(He,o);n.onerror=()=>{console.error("[SWStorage] Failed to repair DB:",n.error),t(n.error)},n.onsuccess=()=>{e(n.result)},n.onupgradeneeded=r=>{const a=r.target.result;St(a)}})}function St(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(N)){const e=s.createObjectStore(N,{keyPath:"id"});e.createIndex("status","status",{unique:!1}),e.createIndex("createdAt","createdAt",{unique:!1})}if(!s.objectStoreNames.contains(B)){const e=s.createObjectStore(B,{keyPath:"id"});e.createIndex("status","status",{unique:!1}),e.createIndex("createdAt","createdAt",{unique:!1})}s.objectStoreNames.contains(U)||s.createObjectStore(U,{keyPath:"requestId"}).createIndex("workflowId","workflowId",{unique:!1})}async function Cs(){const s=await ys();return new Promise((e,t)=>{const o=indexedDB.open(He,s);o.onerror=()=>{console.error("[SWStorage] Failed to open DB:",o.error),t(o.error)},o.onsuccess=()=>{const n=o.result,r=Ts(n);if(r.length>0){console.warn(`[SWStorage] Missing object stores: ${r.join(", ")}. Repairing...`),n.close(),Es(n.version).then(e).catch(t);return}e(n)},o.onupgradeneeded=n=>{const r=n.target.result;St(r)}})}class _s{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=Cs()),this.dbPromise}async flushPendingTaskSaves(){this.batchSaveTimer&&(clearTimeout(this.batchSaveTimer),this.batchSaveTimer=null);const e=Array.from(this.pendingTaskSaves.values()),t=new Map(this.batchSavePromises);if(this.pendingTaskSaves.clear(),this.batchSavePromises.clear(),e.length!==0)try{const o=await this.getDB();await new Promise((n,r)=>{const a=o.transaction(k,"readwrite"),i=a.objectStore(k);for(const c of e)i.put(c);a.oncomplete=()=>{t.forEach(({resolve:c})=>c()),n()},a.onerror=()=>{const c=a.error;t.forEach(({reject:l})=>l(c)),r(c)}})}catch(o){console.error("[SWStorage] Failed to batch save tasks:",o),t.forEach(({reject:n})=>n(o))}}async saveTask(e){return new Promise((t,o)=>{this.pendingTaskSaves.set(e.id,e),this.batchSavePromises.set(e.id,{resolve:t,reject:o}),this.batchSaveTimer||(this.batchSaveTimer=setTimeout(()=>{this.flushPendingTaskSaves()},this.BATCH_SAVE_DELAY))})}async saveTaskImmediate(e){this.pendingTaskSaves.delete(e.id);const t=this.batchSavePromises.get(e.id);t&&this.batchSavePromises.delete(e.id);try{const o=await this.getDB();await new Promise((n,r)=>{const c=o.transaction(k,"readwrite").objectStore(k).put(e);c.onerror=()=>r(c.error),c.onsuccess=()=>n()}),t&&t.resolve()}catch(o){throw console.error("[SWStorage] Failed to save task:",o),t&&t.reject(o),o}}async getTask(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(k,"readonly").objectStore(k).get(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o(i.result||null)})}catch(t){return console.error("[SWStorage] Failed to get task:",t),null}}async getAllTasks(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(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,n)=>{const c=t.transaction(k,"readonly").objectStore(k).index("status").getAll(e);c.onerror=()=>n(c.error),c.onsuccess=()=>o(c.result||[])})}catch(t){return console.error("[SWStorage] Failed to get tasks by status:",t),[]}}async getTasksPaginated(e){const{offset:t,limit:o,status:n,type:r,sortOrder:a="desc"}=e;try{const i=await this.getDB();return new Promise((c,l)=>{const m=i.transaction(k,"readonly").objectStore(k),y=m.index("createdAt"),w=m.count();let f=0;w.onsuccess=()=>{f=w.result};const p=a==="desc"?"prev":"next",S=y.openCursor(null,p),u=[];let h=0,g=0;S.onerror=()=>l(S.error),S.onsuccess=T=>{const _=T.target.result;if(!_){c({tasks:u,total:g,hasMore:g>t+u.length});return}const C=_.value,D=!n||C.status===n,b=!r||C.type===r;D&&b&&(g++,h<t?h++:u.length<o&&u.push(C)),_.continue()}})}catch(i){return console.error("[SWStorage] Failed to get paginated tasks:",i),{tasks:[],total:0,hasMore:!1}}}async deleteTask(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(k,"readwrite").objectStore(k).delete(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to delete task:",t)}}async saveConfig(e,t){try{const o=await this.getDB();return new Promise((n,r)=>{const a=o.transaction(K,"readwrite"),i=a.objectStore(K);e&&i.put({key:"gemini",...e}),t&&i.put({key:"video",...t}),a.oncomplete=()=>n(),a.onerror=()=>r(a.error)})}catch(o){console.error("[SWStorage] Failed to save config:",o)}}async loadConfig(){try{const e=await this.getDB();return new Promise((t,o)=>{const n=e.transaction(K,"readonly"),r=n.objectStore(K),a=r.get("gemini"),i=r.get("video");n.oncomplete=()=>{const c=a.result,l=i.result;t({geminiConfig:c?{apiKey:c.apiKey,baseUrl:c.baseUrl,modelName:c.modelName}:null,videoConfig:l?{baseUrl:l.baseUrl,apiKey:l.apiKey}:null})},n.onerror=()=>o(n.error)})}catch(e){return console.error("[SWStorage] Failed to load config:",e),{geminiConfig:null,videoConfig:null}}}async cleanupOldTasks(e=1440*60*1e3){console.warn("[SWStorage] cleanupOldTasks is deprecated and disabled")}async saveSystemPrompt(e){try{const t=await this.getDB();return new Promise((o,n)=>{const r=t.transaction(K,"readwrite");r.objectStore(K).put({key:"systemPrompt",value:e,updatedAt:Date.now()}),r.oncomplete=()=>o(),r.onerror=()=>n(r.error)})}catch(t){console.error("[SWStorage] Failed to save system prompt:",t)}}async getSystemPrompt(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(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,n)=>{const i=t.transaction(N,"readwrite").objectStore(N).put(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to save workflow:",t)}}async getWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(N,"readonly").objectStore(N).get(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o(i.result||null)})}catch(t){return console.error("[SWStorage] Failed to get workflow:",t),null}}async getAllWorkflows(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(N,"readonly").objectStore(N).getAll();a.onerror=()=>o(a.error),a.onsuccess=()=>t(a.result||[])})}catch(e){return console.error("[SWStorage] Failed to get all workflows:",e),[]}}async getWorkflowsByStatus(e){try{const t=await this.getDB();return new Promise((o,n)=>{const c=t.transaction(N,"readonly").objectStore(N).index("status").getAll(e);c.onerror=()=>n(c.error),c.onsuccess=()=>o(c.result||[])})}catch(t){return console.error("[SWStorage] Failed to get workflows by status:",t),[]}}async deleteWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(N,"readwrite").objectStore(N).delete(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to delete workflow:",t)}}async cleanupOldWorkflows(e=1440*60*1e3){console.warn("[SWStorage] cleanupOldWorkflows is deprecated and disabled")}async saveChatWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(B,"readwrite").objectStore(B).put(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to save chat workflow:",t)}}async getChatWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(B,"readonly").objectStore(B).get(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o(i.result||null)})}catch(t){return console.error("[SWStorage] Failed to get chat workflow:",t),null}}async getAllChatWorkflows(){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 chat workflows:",e),[]}}async getChatWorkflowsByStatus(e){try{const t=await this.getDB();return new Promise((o,n)=>{const c=t.transaction(B,"readonly").objectStore(B).index("status").getAll(e);c.onerror=()=>n(c.error),c.onsuccess=()=>o(c.result||[])})}catch(t){return console.error("[SWStorage] Failed to get chat workflows by status:",t),[]}}async deleteChatWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(B,"readwrite").objectStore(B).delete(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to delete chat workflow:",t)}}async cleanupOldChatWorkflows(e=1440*60*1e3){console.warn("[SWStorage] cleanupOldChatWorkflows is deprecated and disabled")}async savePendingToolRequest(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(U,"readwrite").objectStore(U).put(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to save pending tool request:",t)}}async getAllPendingToolRequests(){try{const e=await this.getDB();return new Promise((t,o)=>{const a=e.transaction(U,"readonly").objectStore(U).getAll();a.onerror=()=>o(a.error),a.onsuccess=()=>t(a.result||[])})}catch(e){return console.error("[SWStorage] Failed to get all pending tool requests:",e),[]}}async getPendingToolRequestsByWorkflow(e){try{const t=await this.getDB();return new Promise((o,n)=>{const c=t.transaction(U,"readonly").objectStore(U).index("workflowId").getAll(e);c.onerror=()=>n(c.error),c.onsuccess=()=>o(c.result||[])})}catch(t){return console.error("[SWStorage] Failed to get pending tool requests by workflow:",t),[]}}async getPendingToolRequest(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(U,"readonly").objectStore(U).get(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o(i.result||null)})}catch(t){return console.error("[SWStorage] Failed to get pending tool request:",t),null}}async deletePendingToolRequest(e){try{const t=await this.getDB();return new Promise((o,n)=>{const i=t.transaction(U,"readwrite").objectStore(U).delete(e);i.onerror=()=>n(i.error),i.onsuccess=()=>o()})}catch(t){console.error("[SWStorage] Failed to delete pending tool request:",t)}}async deletePendingToolRequestsByWorkflow(e){try{const t=await this.getPendingToolRequestsByWorkflow(e);for(const o of t)await this.deletePendingToolRequest(o.requestId)}catch(t){console.error("[SWStorage] Failed to delete pending tool requests by workflow:",t)}}}const E=new _s;let Ie=!1;const bs=500,Y=[];let Oe=0;function As(){return Ie}const Rs=["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"],Ee=new Map;function yt(s){const e=Ie;Ie=s,!s&&e&&(Y.length=0,Ee.clear(),Oe=0)}function Ke(){return Ie}function Tt(s){return As()?!Rs.includes(s):!1}function Ds(s,e,t){if(!Tt(s))return"";const o=`pm-recv-${Date.now()}-${++Oe}`,n={id:o,timestamp:Date.now(),direction:"receive",messageType:s,data:ze(e),clientId:t};if(Ct(n),Ls(s)){const r=_t(e);r&&Ee.set(r,{entry:n,startTime:Date.now()})}return o}function Et(s,e,t){if(!Tt(s))return"";const o=`pm-send-${Date.now()}-${++Oe}`,n={id:o,timestamp:Date.now(),direction:"send",messageType:s,data:ze(e),clientId:t};if(Is(s)){const r=_t(e);if(r){const a=Ee.get(r);a&&(n.duration=Date.now()-a.startTime,a.entry.response=ze(e),a.entry.duration=n.duration,Ee.delete(r))}}return Ct(n),o}function Ct(s){Y.unshift(s),Y.length>bs&&Y.pop()}function Ce(){return[...Y]}function Ws(){Y.length=0,Ee.clear(),Oe=0}function Ls(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 Is(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 _t(s){if(!s||typeof s!="object")return null;const e=s;return e.requestId||e.taskId||e.workflowId||e.chatId||null}function ze(s){if(!s)return s;try{const e=JSON.parse(JSON.stringify(s));return bt(e),e}catch{return"[Non-serializable data]"}}function bt(s){if(!s||typeof s!="object")return;const e=["apiKey","password","token","secret","key"],t=s;for(const o in t)e.some(n=>o.toLowerCase().includes(n))?t[o]="[REDACTED]":typeof t[o]=="object"&&bt(t[o])}function Os(){const s={total:Y.length,sent:0,received:0,byType:{}};for(const e of Y)e.direction==="send"?s.sent++:s.received++,s.byType[e.messageType]||(s.byType[e.messageType]=0),s.byType[e.messageType]++;return s}let ke=!1,ce=null;function je(s){ke=s,yt(s)}function ks(s){ce=s}function At(s,e){if(!s){console.warn("[MessageBus] No client provided");return}let t="";if(Ke()){const o=(e==null?void 0:e.type)||"unknown";t=Et(o,e,s.id)}try{s.postMessage(e)}catch(o){console.warn("[MessageBus] Failed to postMessage to client:",s.id,o);return}if(t&&ke&&ce){const n=Ce().find(r=>r.id===t);n&&ce(n)}}function Rt(s){const e=self,t=(s==null?void 0:s.type)||"unknown";e.clients.matchAll().then(o=>{o.forEach(n=>{let r="";if(Ke()&&(r=Et(t,s,n.id)),n.postMessage(s),r&&ke&&ce){const i=Ce().find(c=>c.id===r);i&&ce(i)}})})}async function Pe(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?(At(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 Ps(s,e){ke=!1,yt(!1),ce=null}const Ms={"1x1":"1024x1024","16x9":"1792x1024","9x16":"1024x1792","4x3":"1536x1152","3x4":"1152x1536","3x2":"1536x1024","2x3":"1024x1536"};function xs(s){return Ms[s]||s}function vs(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 Ns(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 Dt extends Error{constructor(e){super(e),this.name="VideoGenerationFailedError"}}async function Wt(s,e,t={}){var y,w;const{onProgress:o,signal:n,apiKey:r,interval:a=5e3,maxAttempts:i=1080}=t;let c=0,l=0;const d=10,{debugFetch:m}=await Promise.resolve().then(()=>v);for(;c<i;){if(n!=null&&n.aborted)throw new Error("Video generation cancelled");try{const f=await m(`${s}/videos/${e}`,{headers:r?{Authorization:`Bearer ${r}`}:{},signal:n},{label:`🔄 查询视频状态 #${c+1}`,logResponseBody:!0});if(!f.ok){if(l++,console.warn(`[VideoPolling] Status query failed (${f.status}), attempt ${l}/${d}, will retry with longer interval`),l>=d)throw new Error(`Failed to get video status after ${d} consecutive errors: ${f.status}`);const h=Math.min(a*Math.pow(1.5,l),6e4);await new Promise(g=>setTimeout(g,h)),c++;continue}l=0;const p=await f.json(),S=(y=p.status)==null?void 0:y.toLowerCase(),u=p.progress??Math.min(10+c*2,90);if(o==null||o(u,"polling"),S==="completed"||S==="succeeded")return o==null||o(100),p;if(S==="failed"||S==="error"){const h=typeof p.error=="string"?p.error:((w=p.error)==null?void 0:w.message)||p.message||"Video generation failed";throw new Dt(h)}await new Promise(h=>setTimeout(h,a)),c++}catch(f){if(f instanceof Dt)throw f;if(n!=null&&n.aborted)throw new Error("Video generation cancelled");if(l++,console.warn(`[VideoPolling] Network error during status query, attempt ${l}/${d}:`,f),l>=d)throw f;const p=Math.min(a*Math.pow(1.5,l),6e4);await new Promise(S=>setTimeout(S,p)),c++}}throw new Error("Video generation timed out")}const Ve="drawnix-images",Bs=720*60*1e3,Us="drawnix-unified-cache",Qe="media";async function qs(s){return new Promise(e=>{try{const t=indexedDB.open(Us);t.onerror=()=>{console.warn("[MediaUtils] Failed to open IndexedDB:",t.error),e(null)},t.onsuccess=()=>{try{const o=t.result;if(!o.objectStoreNames.contains(Qe)){o.close(),e(null);return}const a=o.transaction(Qe,"readonly").objectStore(Qe).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 Fs(s,e){try{if(s.startsWith("data:"))return Lt(s);const t=await caches.open(Ve),o=await t.match(s);if(o)return await o.blob();const n=await fetch(s,{signal:e});if(n.ok){const r=await n.blob();try{const a=new Response(r.slice(),{headers:{"Content-Type":r.type||"image/png","sw-cache-date":Date.now().toString()}});await t.put(s,a)}catch(a){console.warn(`[MediaUtils] Failed to cache image: ${s.substring(0,50)}...`,a)}return r}return console.warn(`[MediaUtils] Network fetch failed: ${s.substring(0,50)}...`,n.status),null}catch(t){return console.warn(`[MediaUtils] Error in fetchImageWithCache: ${s.substring(0,50)}...`,t),null}}function Lt(s){try{const[e,t]=s.split(",");if(!t)return null;const o=e.match(/data:([^;]+)/),n=o?o[1]:"image/png",r=atob(t),a=new Uint8Array(r.length);for(let i=0;i<r.length;i++)a[i]=r.charCodeAt(i);return new Blob([a],{type:n})}catch(e){return console.warn("[MediaUtils] Failed to convert data URL to Blob:",e),null}}async function Gs(s){return new Promise((e,t)=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.onerror=t,o.readAsDataURL(s)})}const Xe=1024*1024,Me=.1,xe=2048;async function $s(s,e=Xe){if(s.size<=e)return s;try{const t=await createImageBitmap(s);let{width:o,height:n}=t;const r={width:o,height:n};if(o>xe||n>xe){const p=Math.min(xe/o,xe/n);o=Math.round(o*p),n=Math.round(n*p)}const a=new OffscreenCanvas(o,n),i=a.getContext("2d");if(!i)return console.warn("[MediaUtils] Failed to get 2d context from OffscreenCanvas"),s;i.drawImage(t,0,0,o,n),t.close();let c=Me,l=.95,d=null,m=0;const y=8;for(let p=0;p<y;p++){const S=(c+l)/2,u=await a.convertToBlob({type:"image/jpeg",quality:S});if(u.size<=e?(d=u,m=S,c=S):l=S,l-c<.02)break}if(d)return d;let w=await a.convertToBlob({type:"image/jpeg",quality:Me}),f=.8;for(;f>=.3&&w.size>e;){const p=Math.round(o*f),S=Math.round(n*f),u=new OffscreenCanvas(p,S),h=u.getContext("2d");if(!h)break;const g=await createImageBitmap(s);h.drawImage(g,0,0,p,S),g.close();let T=Me,_=.95,C=null;for(let D=0;D<6;D++){const b=(T+_)/2,O=await u.convertToBlob({type:"image/jpeg",quality:b});if(O.size<=e?(C=O,T=b):_=b,_-T<.02)break}if(C)return C;w=await u.convertToBlob({type:"image/jpeg",quality:Me}),f-=.1}return w}catch(t){return console.warn("[MediaUtils] Image compression failed, returning original:",t),s}}async function _e(s,e=Xe){const t=await $s(s,e);return Gs(t)}async function Hs(s,e){if(s.startsWith("data:")){if((s.split(",")[1]||"").length*3/4>Xe){const n=Lt(s);if(n){const r=await _e(n);return{originalUrl:s,value:r,isBase64:!0}}}return{originalUrl:s,value:s,isBase64:!0}}try{const t=await caches.open(Ve);if(s.startsWith("/asset-library/")){const o=await t.match(s);if(o){const n=await o.blob(),r=await _e(n);return{originalUrl:s,value:r,isBase64:!0}}return console.warn(`[MediaUtils] Asset library image not found in cache: ${s}`),{originalUrl:s,value:s,isBase64:!1}}if(s.startsWith("/__aitu_cache__/")){const o=`${self.location.origin}${s}`,n=await t.match(o);if(n){const r=await n.blob(),a=await _e(r);return{originalUrl:s,value:a,isBase64:!0}}return console.warn(`[MediaUtils] Cache URL not found in cache: ${s}`),{originalUrl:s,value:s,isBase64:!1}}if(s.startsWith("http://")||s.startsWith("https://")){const o=await t.match(s,{ignoreVary:!0});if(o){const r=await qs(s),a=o.headers.get("sw-cache-date"),i=a?parseInt(a,10):0,c=r??i,l=Date.now(),d=c?l-c:1/0,m=d/(3600*1e3);if(c>0&&d<Bs)return{originalUrl:s,value:s,isBase64:!1};const y=await o.blob(),w=await _e(y);return{originalUrl:s,value:w,isBase64:!0}}const n=await fetch(s,{signal:e});if(n.ok){const r=await n.blob();try{const i=new Response(r.slice(),{headers:{"Content-Type":r.type||"image/png","sw-cache-date":Date.now().toString()}});await t.put(s,i)}catch(i){console.warn(`[MediaUtils] Failed to cache image: ${s.substring(0,50)}...`,i)}const a=await _e(r);return{originalUrl:s,value:a,isBase64:!0}}return console.warn(`[MediaUtils] Failed to fetch remote image: ${s.substring(0,50)}...`),{originalUrl:s,value:s,isBase64:!1}}return{originalUrl:s,value:s,isBase64:!1}}catch(t){return console.warn(`[MediaUtils] Error processing reference image: ${s.substring(0,50)}...`,t),{originalUrl:s,value:s,isBase64:!1}}}async function Ks(s,e){return!s||s.length===0?[]:(await Promise.all(s.map(o=>Hs(o,e)))).map(o=>o.value)}function It(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=xs(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 zs(s){return s.startsWith("data:image/")&&s.includes(";base64,")}function js(s){const e=s.match(/^data:(image\/[^;]+);base64,(.+)$/);return e?{mimeType:e[1],base64:e[2]}:null}async function Ot(s,e="image/png"){try{const t=atob(s),o=new Uint8Array(t.length);for(let d=0;d<t.length;d++)o[d]=t.charCodeAt(d);const n=new Blob([o],{type:e}),r=`img-${Date.now()}-${Math.random().toString(36).substring(2,10)}`,a=e.split("/")[1]||"png",i=`/__aitu_cache__/image/${r}.${a}`,c=await caches.open(Ve),l=new Response(n,{status:200,headers:{"Content-Type":e,"Content-Length":n.size.toString(),"Cache-Control":"max-age=31536000"}});return await c.put(i,l),i}catch(t){return console.error("[cacheBase64Image] Failed to cache image:",t),`data:${e};base64,${s}`}}async function kt(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 Ot(c.b64_json,"image/png"):null}const o=s.data[0],n=await t(o);if(!n)throw(i=o.revised_prompt)!=null&&i.includes("PROHIBITED_CONTENT")?new Error("内容被拒绝:包含违禁内容"):new Error("No image URL in response");const r=s.data.map((c,l)=>t(c)),a=(await Promise.all(r)).filter(Boolean);return{url:n,urls:a.length>1?a:void 0}}async function Vs(s){if(!zs(s))return{url:s,migrated:!1};const e=js(s);if(!e)return{url:s,migrated:!1};try{const t=await Ot(e.base64,e.mimeType);return console.log(`[Migration] Converted Base64 (${Math.round(s.length/1024)}KB) -> ${t}`),{url:t,migrated:!0}}catch(t){return console.error("[Migration] Failed to migrate Base64 URL:",t),{url:s,migrated:!1}}}class Qs{constructor(){this.abortControllers=new Map}async execute(e,t){const o=new AbortController;this.abortControllers.set(e.id,o);try{return t.onProgress(e.id,0,W.SUBMITTING),await this.generateImage(e,t,o.signal)}finally{this.abortControllers.delete(e.id)}}cancel(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e))}async generateImage(e,t,o){const{geminiConfig:n}=t,{params:r}=e,a=r.referenceImages||vs(r.uploadedImages);let i;a&&a.length>0&&(i=await Ks(a,o));const c=It({prompt:r.prompt,model:r.model,size:r.size,referenceImages:i,isInspirationBoard:r.isInspirationBoard,inspirationBoardImageCount:r.inspirationBoardImageCount},n.modelName);t.onProgress(e.id,10,W.SUBMITTING);const{debugFetch:l}=await Promise.resolve().then(()=>v),{startLLMApiLog:d,completeLLMApiLog:m,failLLMApiLog:y}=await Promise.resolve().then(()=>I),w=Date.now(),f=d({endpoint:"/images/generations",model:n.modelName||"unknown",taskType:"image",prompt:r.prompt,hasReferenceImages:!!i&&i.length>0,referenceImageCount:i==null?void 0:i.length,taskId:e.id}),p=await l(`${n.baseUrl}/images/generations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`},body:JSON.stringify(c),signal:o},{label:`🎨 生成图片 (${n.modelName})`,logRequestBody:!0,logResponseBody:!0});if(!p.ok){const g=await p.text();throw y(f,{httpStatus:p.status,duration:Date.now()-w,errorMessage:g,responseBody:g}),new Error(`Image generation failed: ${p.status} - ${g}`)}t.onProgress(e.id,80,W.DOWNLOADING);const S=await p.json(),u=JSON.stringify(S),{url:h}=await kt(S,e.id);return m(f,{httpStatus:p.status,duration:Date.now()-w,resultType:"image",resultCount:1,resultUrl:h,responseBody:u}),t.onProgress(e.id,100),{url:h,format:"png",size:0,width:r.width,height:r.height}}}class Xs{constructor(){this.abortControllers=new Map,this.pollingIntervals=new Map}async execute(e,t){const o=new AbortController;this.abortControllers.set(e.id,o);try{t.onProgress(e.id,0,W.SUBMITTING);const{response:n,logId:r}=await this.submitVideoGeneration(e,t,o.signal);return t.onRemoteId(e.id,n.id),t.onProgress(e.id,5,W.POLLING),await this.pollUntilComplete(n.id,e.id,t,o.signal,r)}finally{this.cleanup(e.id)}}async resume(e,t){var a,i;if(!e.remoteId)throw new Error("No remote ID for resume");const o=new AbortController;this.abortControllers.set(e.id,o);const{startLLMApiLog:n}=await Promise.resolve().then(()=>I),r=n({endpoint:`/videos/${e.remoteId} (resumed)`,model:((a=e.params)==null?void 0:a.model)||"veo3",taskType:"video",prompt:((i=e.params)==null?void 0:i.prompt)||"",taskId:e.id});try{return t.onProgress(e.id,e.progress||0,W.POLLING),await this.pollUntilComplete(e.remoteId,e.id,t,o.signal,r)}finally{this.cleanup(e.id)}}cancel(e){this.cleanup(e)}async submitVideoGeneration(e,t,o){const{videoConfig:n}=t,{params:r}=e,a=new FormData;a.append("model",r.model||"veo3"),a.append("prompt",r.prompt),r.duration&&a.append("seconds",String(r.duration)),r.size&&a.append("size",r.size);const i=Ns({referenceImages:r.referenceImages,uploadedImages:r.uploadedImages,inputReference:r.inputReference,inputReferences:r.inputReferences});if(i.length>0)for(let u=0;u<i.length;u++){const h=i[u];try{const g=await Fs(h,o);g?a.append("input_reference",g,`reference-${u+1}.png`):(console.warn(`[VideoHandler] Failed to get reference image: ${h}`),a.append("input_reference",h))}catch(g){console.warn(`[VideoHandler] Error fetching reference image: ${h}`,g),a.append("input_reference",h)}}const{debugFetch:c}=await Promise.resolve().then(()=>v),{startLLMApiLog:l,completeLLMApiLog:d,failLLMApiLog:m}=await Promise.resolve().then(()=>I),y=Date.now(),w=r.model||"veo3",f=l({endpoint:"/videos",model:w,taskType:"video",prompt:r.prompt,hasReferenceImages:i.length>0,referenceImageCount:i.length,taskId:e.id}),p=await c(`${n.baseUrl}/videos`,{method:"POST",headers:n.apiKey?{Authorization:`Bearer ${n.apiKey}`}:void 0,body:a,signal:o},{label:`🎬 提交视频生成 (${w})`,logResponseBody:!0});if(!p.ok){const u=await p.text();throw m(f,{httpStatus:p.status,duration:Date.now()-y,errorMessage:u,responseBody:u}),new Error(`Video submission failed: ${p.status} - ${u}`)}return{response:await p.json(),logId:f}}async pollUntilComplete(e,t,o,n,r){const{videoConfig:a}=o,i=Date.now();try{const c=await Wt(a.baseUrl,e,{onProgress:(d,m)=>{o.onProgress(t,d,m)},signal:n,apiKey:a.apiKey,interval:5e3,maxAttempts:1080}),l=c.video_url||c.url;if(!l)throw new Error("No video URL in completed response");if(r){const{completeLLMApiLog:d}=await Promise.resolve().then(()=>I);d(r,{httpStatus:200,duration:Date.now()-i,resultType:"video",resultCount:1,resultUrl:l,responseBody:JSON.stringify(c)})}return{url:l,format:"mp4",size:0,width:c.width,height:c.height,duration:parseInt(c.seconds||"0")||0}}catch(c){if(r){const{failLLMApiLog:l}=await Promise.resolve().then(()=>I);l(r,{duration:Date.now()-i,errorMessage:c instanceof Error?c.message:String(c)})}throw c}}cleanup(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e));const o=this.pollingIntervals.get(e);o&&(clearTimeout(o),this.pollingIntervals.delete(e))}}class Js{constructor(){this.abortControllers=new Map,this.pollingIntervals=new Map}async execute(e,t){const o=new AbortController;this.abortControllers.set(e.id,o);try{t.onProgress(e.id,0,W.SUBMITTING);const{response:n,logId:r}=await this.createCharacter(e,t,o.signal);return t.onRemoteId(e.id,n.id),t.onProgress(e.id,10,W.POLLING),await this.pollUntilComplete(n.id,e.id,t,o.signal,r)}finally{this.cleanup(e.id)}}async resume(e,t){var a;if(!e.remoteId)throw new Error("No remote ID for resume");const o=new AbortController;this.abortControllers.set(e.id,o);const{startLLMApiLog:n}=await Promise.resolve().then(()=>I),r=n({endpoint:`/characters/${e.remoteId} (resumed)`,model:"character-extractor",taskType:"character",prompt:((a=e.params)==null?void 0:a.videoUrl)||"",taskId:e.id});try{return t.onProgress(e.id,e.progress||0,W.POLLING),await this.pollUntilComplete(e.remoteId,e.id,t,o.signal,r)}finally{this.cleanup(e.id)}}cancel(e){this.cleanup(e)}async createCharacter(e,t,o){const{videoConfig:n}=t,{params:r}=e,a=this.getCharacterModel(r.model),i=new FormData;i.append("character_from_task",r.sourceVideoTaskId||""),i.append("model",a),r.characterTimestamps&&i.append("character_timestamps",r.characterTimestamps);const{debugFetch:c}=await Promise.resolve().then(()=>v),{startLLMApiLog:l,completeLLMApiLog:d,failLLMApiLog:m}=await Promise.resolve().then(()=>I),y=Date.now(),w=l({endpoint:"/videos",model:a,taskType:"character",prompt:`角色提取: ${r.sourceVideoTaskId}`,taskId:e.id}),f=await c(`${n.baseUrl}/videos`,{method:"POST",headers:{...n.apiKey?{Authorization:`Bearer ${n.apiKey}`}:{}},body:i,signal:o},{label:`👤 创建角色视频 (${a})`,logResponseBody:!0});if(!f.ok){const S=await f.text();throw m(w,{httpStatus:f.status,duration:Date.now()-y,errorMessage:S,responseBody:S}),new Error(`Character creation failed: ${f.status} - ${S}`)}return{response:await f.json(),logId:w}}async pollUntilComplete(e,t,o,n,r){const{videoConfig:a}=o,i=3e3,c=60,l=Date.now();let d=0;return new Promise((m,y)=>{const w=async()=>{if(n.aborted){if(r){const{failLLMApiLog:f}=await Promise.resolve().then(()=>I);f(r,{duration:Date.now()-l,errorMessage:"Task cancelled"})}y(new Error("Task cancelled"));return}if(d++,d>c){if(r){const{failLLMApiLog:f}=await Promise.resolve().then(()=>I);f(r,{duration:Date.now()-l,errorMessage:"Character creation timeout"})}y(new Error("Character creation timeout"));return}try{const f=await this.queryCharacter(e,a,n),p=Math.min(10+d/c*90,99);if(o.onProgress(t,p,W.POLLING),f.username){if(o.onProgress(t,100),r){const{completeLLMApiLog:u}=await Promise.resolve().then(()=>I);u(r,{httpStatus:200,duration:Date.now()-l,resultType:"character",resultCount:1,resultUrl:f.profile_picture_url,responseBody:JSON.stringify(f)})}m({url:f.profile_picture_url,format:"png",size:0,characterUsername:f.username,characterProfileUrl:f.profile_picture_url,characterPermalink:f.permalink});return}const S=setTimeout(w,i);this.pollingIntervals.set(t,S)}catch(f){if(f instanceof Error&&f.message.includes("404")){const p=setTimeout(w,i);this.pollingIntervals.set(t,p)}else if(d<c){const p=setTimeout(w,i);this.pollingIntervals.set(t,p)}else{if(r){const{failLLMApiLog:p}=await Promise.resolve().then(()=>I);p(r,{duration:Date.now()-l,errorMessage:f instanceof Error?f.message:String(f)})}y(f)}}};w()})}async queryCharacter(e,t,o){const{debugFetch:n}=await Promise.resolve().then(()=>v),r=await n(`${t.baseUrl}/videos/${e}`,{method:"GET",headers:t.apiKey?{Authorization:`Bearer ${t.apiKey}`}:void 0,signal:o},{label:"👤 查询角色状态",logResponseBody:!0});if(!r.ok)throw new Error(`Character query failed: ${r.status}`);return r.json()}getCharacterModel(e){return e==="sora-2-pro"?"sora-2-pro-character":"sora-2-character"}cleanup(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e));const o=this.pollingIntervals.get(e);o&&(clearTimeout(o),this.pollingIntervals.delete(e))}}class Ys{constructor(){this.abortControllers=new Map}async execute(e,t){const o=e.params,n=new AbortController;this.abortControllers.set(e.id,n);try{const r=this.convertToGeminiMessages(o),a=await this.streamChat(r,t.geminiConfig,o.temporaryModel,o.systemPrompt,n.signal,void 0);return{url:"",format:"text",size:a.length,chatResponse:a,toolCalls:[]}}finally{this.abortControllers.delete(e.id)}}cancel(e){this.stop(e)}async stream(e,t,o,n){const r=new AbortController;this.abortControllers.set(e,r);try{const a=this.convertToGeminiMessages(t);return await this.streamChat(a,o,t.temporaryModel,t.systemPrompt,r.signal,n)}finally{this.abortControllers.delete(e)}}stop(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e))}convertToGeminiMessages(e){var o;const t=[];e.systemPrompt&&t.push({role:"system",content:[{type:"text",text:e.systemPrompt}]});for(const n of e.messages){const r=[];if(n.content&&r.push({type:"text",text:n.content}),n.attachments)for(const a of n.attachments)a.type==="image"&&r.push({type:"image_url",image_url:{url:`data:${a.mimeType};base64,${a.data}`}});t.push({role:n.role,content:r})}if(e.newContent||(o=e.attachments)!=null&&o.length){const n=[];if(e.newContent&&n.push({type:"text",text:e.newContent}),e.attachments)for(const r of e.attachments)r.type==="image"&&n.push({type:"image_url",image_url:{url:`data:${r.mimeType};base64,${r.data}`}});t.push({role:"user",content:n})}return t}async streamChat(e,t,o,n,r,a){var O,z,X,De,We,us,ds,hs;const i=o||t.modelName||"gemini-2.5-flash",c={model:i,messages:e,stream:!0},{debugFetch:l}=await Promise.resolve().then(()=>v),{startLLMApiLog:d,completeLLMApiLog:m,failLLMApiLog:y}=await Promise.resolve().then(()=>I),w=Date.now(),f=e.filter(H=>H.role==="user").pop(),p=((z=(O=f==null?void 0:f.content)==null?void 0:O[0])==null?void 0:z.text)||"",S=d({endpoint:"/chat/completions",model:i,taskType:"chat",prompt:p,requestBody:JSON.stringify(c,null,2)}),u=await l(`${t.baseUrl}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`},body:JSON.stringify(c),signal:r},{label:`💬 对话请求 (${i})`,logRequestBody:!0,isStreaming:!0});if(!u.ok){const H=await u.text();throw y(S,{httpStatus:u.status,duration:Date.now()-w,errorMessage:H}),new Error(`Chat request failed: ${u.status} - ${H}`)}const h=w,g=S;if(!u.body)throw new Error("No response body");const T=u.body.getReader(),_=new TextDecoder;let C="",D="";try{for(;;){const{done:H,value:fs}=await T.read();if(H)break;D+=_.decode(fs,{stream:!0});const Le=D.split(`
2
+ `);D=Le.pop()||"";for(const gs of Le)if(gs.startsWith("data: ")){const ps=gs.slice(6).trim();if(ps==="[DONE]")continue;try{const ms=(We=(De=(X=JSON.parse(ps).choices)==null?void 0:X[0])==null?void 0:De.delta)==null?void 0:We.content;ms&&(C+=ms,a==null||a(C))}catch{}}}if(D.startsWith("data: ")){const H=D.slice(6).trim();if(H&&H!=="[DONE]")try{const Le=(hs=(ds=(us=JSON.parse(H).choices)==null?void 0:us[0])==null?void 0:ds.delta)==null?void 0:hs.content;Le&&(C+=Le,a==null||a(C))}catch{}}}finally{T.releaseLock()}if(u.__debugLogId&&C){const{updateLogResponseBody:H}=await Promise.resolve().then(()=>v);H(u.__debugLogId,C)}const{completeLLMApiLog:b}=await Promise.resolve().then(()=>I);return b(g,{httpStatus:u.status,duration:Date.now()-h,resultType:"text",resultCount:1,resultText:C}),C}}class Zs{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={...ws,...t},this.imageHandler=new Qs,this.videoHandler=new Xs,this.characterHandler=new Js,this.chatHandler=new Ys,this.storageRestorePromise=this.restoreFromStorage()}setTaskStatusChangeCallback(e){this.onTaskStatusChange=e}getGeminiConfig(){return this.geminiConfig}getVideoConfig(){return this.videoConfig}getSW(){return this.sw}async restoreFromStorage(){var e;try{const{geminiConfig:t,videoConfig:o}=await E.loadConfig();t&&o&&(this.geminiConfig=t,this.videoConfig=o,this.initialized=!0);const n=await E.getAllTasks();let r=0;for(const a of n){if(a.status===A.COMPLETED&&((e=a.result)!=null&&e.url)&&a.result.url.startsWith("data:image/")){const{url:i,migrated:c}=await Vs(a.result.url);c&&(a.result.url=i,await E.updateTask(a),r++)}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)}r>0&&console.log(`[SWTaskQueue] Migrated ${r} Base64 URLs to cache`)}catch(t){console.error("[SWTaskQueue] Failed to restore from storage:",t)}}shouldResumeTask(e){return e.type===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,d;const t=((i=e.error)==null?void 0:i.message)||"",o=((l=(c=e.error)==null?void 0:c.details)==null?void 0:l.originalError)||"",n=((d=e.error)==null?void 0:d.code)||"",r=`${t} ${o}`.toLowerCase();return r.includes("generation_failed")||r.includes("invalid_argument")||r.includes("prohibited")||r.includes("content policy")||r.includes("视频生成失败")||n.includes("generation_failed")||n.includes("INVALID")?!1:r.includes("failed to fetch")||r.includes("network")||r.includes("fetch")||r.includes("timeout")||r.includes("aborted")||r.includes("connection")||r.includes("status query failed")}async resumeTaskExecution(e){if(this.initialized){if(e.remoteId&&(e.type===L.VIDEO||e.type===L.CHARACTER))e.status===A.FAILED&&(e.status=A.PROCESSING,e.error=void 0,e.executionPhase=W.POLLING,e.updatedAt=Date.now(),this.tasks.set(e.id,e),await E.saveTask(e)),this.runningTasks.add(e.id),this.broadcastToClients({type:"TASK_STATUS",taskId:e.id,status:A.PROCESSING,progress:e.progress,phase:W.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}=await Promise.resolve().then(()=>I),o=await t(e.id);if(o&&o.resultUrl){let n,r,a;if(o.responseBody)try{const i=JSON.parse(o.responseBody);n=i.width,r=i.height,a=parseInt(i.seconds||"0")||0}catch{}await this.handleTaskSuccess(e.id,{url:o.resultUrl,format:e.type===L.VIDEO?"mp4":"png",size:0,width:n,height:r,duration:a});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(()=>I),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 E.saveConfig(e,t),this.broadcastToClients({type:"TASK_QUEUE_INITIALIZED",success:!0}),this.syncTasksToClients();for(const o of this.tasks.values())this.shouldResumeTask(o)&&!this.runningTasks.has(o.id)&&this.resumeTaskExecution(o);this.processQueue()}async updateConfig(e,t){e&&this.geminiConfig&&(this.geminiConfig={...this.geminiConfig,...e}),t&&this.videoConfig&&(this.videoConfig={...this.videoConfig,...t}),await E.saveConfig(this.geminiConfig,this.videoConfig)}async submitTask(e,t,o,n){if(this.tasks.has(e)){console.warn(`[SWTaskQueue] Task ${e} already exists`);return}const r=Date.now(),a={id:e,type:t,status:A.PENDING,params:o,createdAt:r,updatedAt:r};this.tasks.set(e,a),await E.saveTask(a),this.broadcastToClients({type:"TASK_CREATED",task:a}),this.processQueue()}async cancelTask(e){var o;const t=this.tasks.get(e);t&&(this.runningTasks.has(e)&&((o=this.getHandler(t.type))==null||o.cancel(e),this.runningTasks.delete(e)),t.status=A.CANCELLED,t.updatedAt=Date.now(),this.tasks.set(e,t),await E.saveTask(t),this.broadcastToClients({type:"TASK_CANCELLED",taskId:e}))}async retryTask(e){const t=this.tasks.get(e);!t||t.status!==A.FAILED&&t.status!==A.CANCELLED||(t.status=A.PENDING,t.error=void 0,t.updatedAt=Date.now(),this.tasks.set(e,t),await E.saveTask(t),this.broadcastToClients({type:"TASK_STATUS",taskId:t.id,status:t.status,updatedAt:t.updatedAt}),this.processQueue())}async resumeTask(e,t,o,n){let r=this.tasks.get(e);if(!r){const a=Date.now();r={id:e,type:o,status:A.PROCESSING,params:{prompt:""},createdAt:a,updatedAt:a,remoteId:t,executionPhase:W.POLLING},this.tasks.set(e,r),await E.saveTask(r)}(o===L.VIDEO||o===L.CHARACTER)&&(this.runningTasks.add(e),this.executeResume(r,t))}getTask(e){return this.tasks.get(e)||null}getAllTasks(){return Array.from(this.tasks.values())}async deleteTask(e){var o;const t=this.tasks.get(e);t&&(this.runningTasks.has(e)&&((o=this.getHandler(t.type))==null||o.cancel(e),this.runningTasks.delete(e)),this.tasks.delete(e),await E.deleteTask(e),this.broadcastToClients({type:"TASK_DELETED",taskId:e}))}async markTaskInserted(e){const t=this.tasks.get(e);if(!t)return;const o={...t,insertedToCanvas:!0,updatedAt:Date.now()};this.tasks.set(e,o),await E.saveTask(o)}async restoreTasks(e){for(const t of e)t.status!==A.COMPLETED&&t.status!==A.CANCELLED&&(this.tasks.set(t.id,t),await E.saveTask(t));this.processQueue()}async startChat(e,t,o){if(!this.geminiConfig){this.broadcastToClients({type:"CHAT_ERROR",chatId:e,error:"Gemini config not initialized"});return}try{const n=await this.chatHandler.stream(e,t,this.geminiConfig,a=>{this.broadcastToClients({type:"CHAT_CHUNK",chatId:e,content:a})});this.chatResultCache.set(e,{chatId:e,fullContent:n,timestamp:Date.now(),delivered:!1}),this.broadcastToClients({type:"CHAT_DONE",chatId:e,fullContent:n});const r=this.chatResultCache.get(e);r&&(r.delivered=!0),this.cleanupChatCache()}catch(n){this.broadcastToClients({type:"CHAT_ERROR",chatId:e,error:n instanceof Error?n.message:String(n)})}}getCachedChatResult(e){return this.chatResultCache.get(e)}getAllCachedChatResults(){return Array.from(this.chatResultCache.values())}cleanupChatCache(){const e=Date.now();for(const[t,o]of this.chatResultCache.entries())e-o.timestamp>this.CHAT_CACHE_TTL&&this.chatResultCache.delete(t)}stopChat(e){this.chatHandler.stop(e)}syncTasksToClients(){const e=this.getAllTasks();this.broadcastToClients({type:"TASK_ALL_RESPONSE",tasks:e})}async getTasksPaginated(e){return E.getTasksPaginated(e)}async syncPaginatedTasksToClients(e){const t=await this.getTasksPaginated(e);this.broadcastToClients({type:"TASK_PAGINATED_RESPONSE",tasks:t.tasks,total:t.total,offset:e.offset,hasMore:t.hasMore})}processQueue(){if(!this.initialized){console.warn("[SWTaskQueue] Not initialized, skipping queue processing");return}const e=Array.from(this.tasks.values()).filter(t=>t.status===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}this.runningTasks.add(e.id),e.status=A.PROCESSING,e.startedAt=Date.now(),e.updatedAt=Date.now(),e.executionPhase=W.SUBMITTING,this.tasks.set(e.id,e),await E.saveTask(e),this.broadcastToClients({type:"TASK_STATUS",taskId:e.id,status:e.status,phase:e.executionPhase,updatedAt:e.updatedAt});const t={geminiConfig:this.geminiConfig,videoConfig:this.videoConfig,onProgress:async(o,n,r)=>{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=n,r&&(a.executionPhase=r),a.updatedAt=Date.now(),this.tasks.set(o,a),await E.saveTask(a);const c=this.tasks.get(o);c&&c.status===i&&this.broadcastToClients({type:"TASK_STATUS",taskId:o,status:i,progress:n,phase:r,updatedAt:a.updatedAt})}},onRemoteId:async(o,n)=>{const r=this.tasks.get(o);r&&(r.remoteId=n,r.executionPhase=W.POLLING,r.updatedAt=Date.now(),this.tasks.set(o,r),await E.saveTask(r),this.broadcastToClients({type:"TASK_SUBMITTED",taskId:o,remoteId:n}))}};try{const o=this.getHandler(e.type);if(!o)throw new Error(`No handler for task type: ${e.type}`);const n=this.config.timeouts[e.type]||600*1e3,r=await Promise.race([o.execute(e,t),new Promise((a,i)=>{setTimeout(()=>{var c;(c=o.cancel)==null||c.call(o,e.id),i(new Error(`Task timeout after ${Math.round(n/6e4)} minutes`))},n)})]);await this.handleTaskSuccess(e.id,r)}catch(o){await this.handleTaskError(e.id,o)}}async executeResume(e,t){if(!this.geminiConfig||!this.videoConfig)return;const o={geminiConfig:this.geminiConfig,videoConfig:this.videoConfig,onProgress:async(n,r,a)=>{const i=this.tasks.get(n);if(i&&i.status!==A.COMPLETED&&i.status!==A.FAILED&&i.status!==A.CANCELLED){const c=i.status;i.progress=r,a&&(i.executionPhase=a),i.updatedAt=Date.now(),this.tasks.set(n,i),await E.saveTask(i);const l=this.tasks.get(n);l&&l.status===c&&this.broadcastToClients({type:"TASK_STATUS",taskId:n,status:c,progress:r,phase:a,updatedAt:i.updatedAt})}},onRemoteId:()=>{}};try{const n=this.getHandler(e.type);if(!(n!=null&&n.resume))throw new Error(`Handler does not support resume: ${e.type}`);e.remoteId=t;const r=await n.resume(e,o);await this.handleTaskSuccess(e.id,r)}catch(n){console.error(`[SWTaskQueue] executeResume: 任务 ${e.id} 恢复失败`,n),await this.handleTaskError(e.id,n)}}async handleTaskSuccess(e,t){var n;const o=this.tasks.get(e);o&&(o.status=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 E.saveTask(o),this.broadcastToClients({type:"TASK_COMPLETED",taskId:e,result:t,completedAt:o.completedAt}),(n=this.onTaskStatusChange)==null||n.call(this,e,"completed",t),this.processQueue())}async handleTaskError(e,t){var r;const o=this.tasks.get(e);if(!o)return;this.runningTasks.delete(e);const n={code:"EXECUTION_ERROR",message:t instanceof Error?t.message:String(t),details:{originalError:t instanceof Error?t.stack:String(t),timestamp:Date.now()}};o.status=A.FAILED,o.error=n,o.updatedAt=Date.now(),this.tasks.set(e,o),await E.saveTask(o),this.broadcastToClients({type:"TASK_FAILED",taskId:e,error:n}),(r=this.onTaskStatusChange)==null||r.call(this,e,"failed",void 0,n.message),this.processQueue()}async markTaskFailed(e,t){const o=this.tasks.get(e);o&&(o.status=A.FAILED,o.error=t,o.updatedAt=Date.now(),this.tasks.set(e,o),await E.saveTask(o),this.broadcastToClients({type:"TASK_FAILED",taskId:e,error:t}))}getHandler(e){switch(e){case L.IMAGE:case L.INSPIRATION_BOARD:return this.imageHandler;case L.VIDEO:return this.videoHandler;case L.CHARACTER:return this.characterHandler;case L.CHAT:return this.chatHandler;default:return null}}async broadcastToClients(e){try{const t=await this.sw.clients.matchAll({type:"window"});for(const o of t)At(o,e)}catch(t){console.error("[SWTaskQueue] Failed to broadcast:",t)}}}let ve=null;function eo(s,e){return ve||(ve=new Zs(s,e)),ve}function Je(){return ve}function to(s,e){var o,n;const t=Je();if(!t&&s.type!=="TASK_QUEUE_INIT"){console.warn("[SWTaskQueue] Queue not initialized");return}switch(s.type){case"TASK_QUEUE_INIT":t&&t.initialize(s.geminiConfig,s.videoConfig);break;case"TASK_QUEUE_UPDATE_CONFIG":t==null||t.updateConfig(s.geminiConfig,s.videoConfig);break;case"TASK_SUBMIT":t==null||t.submitTask(s.taskId,s.taskType,s.params,e);break;case"TASK_CANCEL":t==null||t.cancelTask(s.taskId);break;case"TASK_RETRY":t==null||t.retryTask(s.taskId);break;case"TASK_RESUME":t==null||t.resumeTask(s.taskId,s.remoteId,s.taskType,e);break;case"TASK_GET_STATUS":{t==null||t.syncTasksToClients();break}case"TASK_GET_ALL":{t==null||t.syncTasksToClients();break}case"TASK_GET_PAGINATED":{t==null||t.syncPaginatedTasksToClients({offset:s.offset,limit:s.limit,status:(o=s.filters)==null?void 0:o.status,type:(n=s.filters)==null?void 0:n.type,sortOrder:s.sortOrder});break}case"TASK_DELETE":t==null||t.deleteTask(s.taskId);break;case"TASK_MARK_INSERTED":t==null||t.markTaskInserted(s.taskId);break;case"CHAT_START":t==null||t.startChat(s.chatId,s.params,e);break;case"CHAT_STOP":t==null||t.stopChat(s.chatId);break;case"CHAT_GET_CACHED":{const r=t==null?void 0:t.getCachedChatResult(s.chatId);r?Pe(e,{type:"CHAT_CACHED_RESULT",chatId:s.chatId,fullContent:r.fullContent,found:!0}).then(a=>{a||console.warn("[SWTaskQueue] Failed to send CHAT_CACHED_RESULT to client:",e)}):Pe(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(()=>xr).then(({executeMCPTool:r})=>{const a=Je(),i=a==null?void 0:a.getGeminiConfig(),c=a==null?void 0:a.getVideoConfig(),l=a==null?void 0:a.getSW();a&&i&&c&&l?r(s.requestId,s.toolName,s.args,i,c,e,l):l==null||l.clients.get(e).then(d=>{d&&d.postMessage({type:"MCP_TOOL_RESULT",requestId:s.requestId,success:!1,error:"Task queue not initialized",resultType:"error"})})});break}}}const so={name:"generate_image",description:"Generate images using AI",async execute(s,e){const{geminiConfig:t,onProgress:o,signal:n}=e,{prompt:r,size:a,referenceImages:i,quality:c,model:l,count:d=1}=s;if(!r)return{success:!1,error:"缺少必填参数 prompt",type:"error"};try{o==null||o(0,W.SUBMITTING);const m=It({prompt:r,model:l,size:a,referenceImages:i,quality:c,n:Math.min(Math.max(1,d),10)},t.modelName);o==null||o(10,W.SUBMITTING);const{debugFetch:y}=await Promise.resolve().then(()=>v),w=await y(`${t.baseUrl}/images/generations`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`},body:JSON.stringify(m),signal:n},{label:`🎨 生成图片 (${t.modelName})`,logRequestBody:!0,logResponseBody:!0});if(!w.ok){const u=await w.text();throw console.error("[SW:generateImage] ✗ API error:",w.status,u.substring(0,200)),new Error(`Image generation failed: ${w.status} - ${u}`)}o==null||o(80,W.DOWNLOADING);const f=await w.json(),{url:p,urls:S}=await kt(f);return o==null||o(100),{success:!0,type:"image",data:{url:p,urls:S,format:"png",prompt:r,size:a||"1x1"}}}catch(m){return console.error("[SW:generateImage] Error:",m),{success:!1,error:m.message||"图片生成失败",type:"error"}}}},oo={name:"generate_video",description:"Generate videos using AI",async execute(s,e){const{videoConfig:t,onProgress:o,onRemoteId:n,signal:r}=e,{prompt:a,model:i="veo3",seconds:c="8",size:l="1280x720",inputReference:d,inputReferences:m,referenceImages:y}=s;if(!a)return{success:!1,error:"缺少必填参数 prompt",type:"error"};try{o==null||o(0,W.SUBMITTING);const w={model:i,prompt:a,seconds:c,size:l},f=[];m&&m.length>0?m.forEach(T=>{const _=typeof T=="string"?T:T==null?void 0:T.url;_&&f.push(_)}):y&&y.length>0?f.push(...y):d&&f.push(d),f.length>0&&(f.length===1?w.input_reference=f[0]:w.input_references=f);const{debugFetch:p}=await Promise.resolve().then(()=>v),S=await p(`${t.baseUrl}/videos/generations`,{method:"POST",headers:{"Content-Type":"application/json",...t.apiKey?{Authorization:`Bearer ${t.apiKey}`}:{}},body:JSON.stringify(w),signal:r},{label:`🎬 提交视频生成 (${t.model||"default"})`,logRequestBody:!0,logResponseBody:!0});if(!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 u=await S.json(),h=u.id||u.video_id;if(!h)throw console.error("[SW:generateVideo] ✗ No video ID in response:",u),new Error("No video ID in response");n==null||n(h),o==null||o(10,W.POLLING);const g=await Wt(t.baseUrl,h,{onProgress:o,signal:r,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(w){return console.error("[SW:generateVideo] ✗ Error:",w.message),{success:!1,error:w.message||"视频生成失败",type:"error"}}}},Pt=new Map([["generate_image",so],["generate_video",oo]]);function Mt(s){return Pt.get(s)}async function Ye(s,e,t){const o=Pt.get(s);return o?o.execute(e,t):{success:!1,error:`Unknown tool: ${s}`,type:"error"}}function Ze(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 ro{constructor(e){this.workflows=new Map,this.runningWorkflows=new Set,this.abortControllers=new Map,this.pendingToolRequests=new Map,this.config=e,this.restoreFromStorage()}async restoreFromStorage(){try{const e=await E.getAllWorkflows();for(const t of e){if(t.status==="completed"||t.status==="cancelled"||t.status==="failed"){this.workflows.set(t.id,t);continue}(t.status==="running"||t.status==="pending")&&await this.handleInterruptedWorkflow(t)}}catch(e){console.error("[WorkflowExecutor] Failed to restore from storage:",e)}}async handleInterruptedWorkflow(e){const t=e.steps.find(o=>o.status==="running");e.status="failed",e.error=t?`工作流在步骤 "${t.description||t.mcp}" 执行时中断,请重试`:"工作流执行时中断,请重试",e.updatedAt=Date.now(),t&&(t.status="failed",t.error="Service Worker 重启导致执行中断"),this.workflows.set(e.id,e),await E.saveWorkflow(e),await E.deletePendingToolRequestsByWorkflow(e.id)}updateConfig(e){this.config={...this.config,...e}}async handleMainThreadToolResponse(e){var o;console.log("[SW-WorkflowExecutor] ◀ Received tool response:",{requestId:e.requestId,success:e.success,hasPending:this.pendingToolRequests.has(e.requestId),hasAddSteps:!!((o=e.addSteps)!=null&&o.length),timestamp:new Date().toISOString()});const t=this.pendingToolRequests.get(e.requestId);if(t)console.log("[SW-WorkflowExecutor] ✓ Resolving pending tool request:",e.requestId),this.pendingToolRequests.delete(e.requestId),t.resolve(e);else{console.log("[SW-WorkflowExecutor] Tool response received after SW restart, attempting recovery:",e.requestId);const n=await E.getPendingToolRequest(e.requestId);if(!n){console.log("[SW-WorkflowExecutor] No stored request found for:",e.requestId);return}console.log("[SW-WorkflowExecutor] Found stored request:",{workflowId:n.workflowId,stepId:n.stepId,toolName:n.toolName});let r=this.workflows.get(n.workflowId);if(r||(r=await E.getWorkflow(n.workflowId),r&&this.workflows.set(r.id,r)),!r){console.log("[SW-WorkflowExecutor] Workflow not found:",n.workflowId),await E.deletePendingToolRequest(e.requestId);return}const a=r.steps.find(i=>i.id===n.stepId);if(!a){console.log("[SW-WorkflowExecutor] Step not found:",n.stepId),await E.deletePendingToolRequest(e.requestId);return}if(e.success){a.status="completed",a.result={success:!0,type:"text",data:e.result};const i=e.addSteps;if(i&&i.length>0){console.log("[SW-WorkflowExecutor] Adding",i.length,"new steps from recovered response");const c=[];for(const l of i)r.steps.find(d=>d.id===l.id)||(r.steps.push({id:l.id,mcp:l.mcp,args:l.args,description:l.description,status:l.status||"pending"}),c.push(l));c.length>0&&this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:r.id,steps:c})}await E.saveWorkflow(r),this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:r.id,stepId:a.id,status:"completed",result:a.result})}else{a.status="failed",a.error=e.error||"Unknown error",a.result={success:!1,type:"error",error:a.error},await E.saveWorkflow(r),this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:r.id,stepId:a.id,status:"failed",error:a.error}),this.config.broadcast({type:"WORKFLOW_FAILED",workflowId:r.id,error:a.error}),await E.deletePendingToolRequest(e.requestId);return}await E.deletePendingToolRequest(e.requestId),console.log("[SW-WorkflowExecutor] Continuing workflow execution after recovery:",r.id),await this.executeWorkflow(r)}}async updateWorkflowStepForTask(e,t,o,n){for(const r of this.workflows.values()){const a=r.steps.find(i=>{var l;const c=i.result;return(c==null?void 0:c.taskId)===e||((l=c==null?void 0:c.taskIds)==null?void 0:l.includes(e))});if(a){a.status=t,t==="completed"&&o?a.result={...a.result,success:!0,data:o}:t==="failed"&&(a.error=n,a.result={...a.result,success:!1,error:n}),a.updatedAt=Date.now(),r.updatedAt=Date.now(),await E.saveWorkflow(r),this.broadcastStepStatus(r.id,a),r.status==="running"&&this.executeWorkflow(r.id);return}}}broadcastRecoveredWorkflows(){for(const e of this.workflows.values())this.config.broadcast({type:"WORKFLOW_RECOVERED",workflowId:e.id,workflow:e})}resendPendingToolRequests(){if(this.pendingToolRequests.size===0)return;const e=[];console.log("[SW-WorkflowExecutor] resendPendingToolRequests:",{pendingCount:this.pendingToolRequests.size,pendingTools:Array.from(this.pendingToolRequests.values()).map(t=>({toolName:t.requestInfo.toolName,workflowId:t.requestInfo.workflowId})),timestamp:new Date().toISOString()});for(const[,t]of this.pendingToolRequests){const{requestInfo:o}=t;if(e.includes(o.toolName)){console.log("[SW-WorkflowExecutor] Skipping resend for tool (already in progress):",{toolName:o.toolName,workflowId:o.workflowId,requestId:o.requestId});continue}this.config.broadcast({type:"MAIN_THREAD_TOOL_REQUEST",requestId:o.requestId,workflowId:o.workflowId,stepId:o.stepId,toolName:o.toolName,args:o.args})}}cancelAllPendingToolRequests(){if(this.pendingToolRequests.size!==0){for(const[e,t]of this.pendingToolRequests)t.reject(new Error("页面刷新导致请求中断,请重试"));this.pendingToolRequests.clear()}}async submitWorkflow(e){var o,n;console.log("[SW-WorkflowExecutor] submitWorkflow:",{workflowId:e.id,existingWorkflowsCount:this.workflows.size,hasContext:!!e.context,referenceImagesCount:((n=(o=e.context)==null?void 0:o.referenceImages)==null?void 0:n.length)||0,timestamp:new Date().toISOString()});const t=this.workflows.get(e.id);if(t){if(t.status==="running"||t.status==="pending"){console.log(`[SW-WorkflowExecutor] Re-claiming active workflow ${e.id}, status: ${t.status}`),this.broadcastWorkflowStatus(t),t.steps.forEach(r=>this.broadcastStepStatus(t.id,r));return}console.warn(`[SW-WorkflowExecutor] Workflow ${e.id} already exists with terminal status ${t.status}, skipping`),this.broadcastWorkflowStatus(t);return}console.log("[SW-WorkflowExecutor] ✓ New workflow, starting execution:",e.id),e.status="pending",e.updatedAt=Date.now(),this.workflows.set(e.id,e),await E.saveWorkflow(e),this.executeWorkflow(e.id)}async cancelWorkflow(e){const t=this.workflows.get(e);if(!t)return;const o=this.abortControllers.get(e);o&&(o.abort(),this.abortControllers.delete(e)),t.status="cancelled",t.updatedAt=Date.now(),this.runningWorkflows.delete(e),await E.saveWorkflow(t),await E.deletePendingToolRequestsByWorkflow(e),this.broadcastWorkflowStatus(t)}getWorkflow(e){return this.workflows.get(e)}getAllWorkflows(){return Array.from(this.workflows.values())}async executeWorkflow(e){console.log("[SW-WorkflowExecutor] executeWorkflow called:",{workflowId:e,timestamp:new Date().toISOString()});const t=this.workflows.get(e);if(!t){console.error(`[WorkflowExecutor] ✗ Workflow ${e} not found`);return}if(this.runningWorkflows.has(e)){console.warn(`[SW-WorkflowExecutor] Workflow ${e} is already running, skipping duplicate execution`);return}this.runningWorkflows.add(e),console.log(`[SW-WorkflowExecutor] ▶ Starting workflow execution: ${e}`);const o=new AbortController;this.abortControllers.set(e,o),t.status="running",t.updatedAt=Date.now(),await E.saveWorkflow(t),this.broadcastWorkflowStatus(t);try{let n=0;for(;;){const a=t.steps.filter(c=>c.status==="completed"||c.status==="failed"||c.status==="skipped"||c.status==="running"?!1:c.dependsOn&&c.dependsOn.length>0?c.dependsOn.every(l=>{const d=t.steps.find(m=>m.id===l);return d&&(d.status==="completed"||d.status==="skipped")}):!0),i=t.steps.some(c=>c.status==="running");if(a.length===0){if(i||t.steps.every(l=>l.status==="completed"||l.status==="failed"||l.status==="skipped"))break;console.warn("[WorkflowExecutor] Workflow stuck: no executable steps and none running");break}for(const c of a){if(o.signal.aborted)throw new Error("Workflow cancelled");if(n++,await this.executeStep(t,c,o.signal),c.status==="failed")throw console.error(`[WorkflowExecutor] ✗ Step ${c.id} failed: ${c.error}`),new Error(`Step ${c.id} failed: ${c.error}`);c.status}}t.steps.every(a=>a.status==="completed"||a.status==="failed"||a.status==="skipped")?(t.status="completed",t.completedAt=Date.now(),t.updatedAt=Date.now(),await E.saveWorkflow(t),this.config.broadcast({type:"WORKFLOW_COMPLETED",workflowId:e,workflow:t})):await E.saveWorkflow(t)}catch(n){console.error(`[WorkflowExecutor] ✗ Workflow ${e} failed:`,n),t.status="failed",t.error=n.message,t.updatedAt=Date.now(),await E.saveWorkflow(t),this.config.broadcast({type:"WORKFLOW_FAILED",workflowId:e,error:n.message})}finally{this.runningWorkflows.delete(e),this.abortControllers.delete(e)}}replaceImagePlaceholders(e,t){if(!t||t.length===0)return e;const o=n=>{if(typeof n=="string"){let r=n.replace(/\[图片(\d+)\]/g,(a,i)=>{const c=parseInt(i,10)-1;return c>=0&&c<t.length?t[c]:a});return r=r.replace(/\[Image\s*(\d+)\]/gi,(a,i)=>{const c=parseInt(i,10)-1;return c>=0&&c<t.length?t[c]:a}),r}if(Array.isArray(n))return n.map(r=>o(r));if(n&&typeof n=="object"){const r={};for(const[a,i]of Object.entries(n))r[a]=o(i);return r}return n};return o(e)}async executeStep(e,t,o){var l,d,m,y,w,f;console.log("[SW-WorkflowExecutor] executeStep:",{workflowId:e.id,stepId:t.id,mcp:t.mcp,hasContext:!!e.context,referenceImagesCount:((d=(l=e.context)==null?void 0:l.referenceImages)==null?void 0:d.length)||0,timestamp:new Date().toISOString()});const n=Date.now(),r=((m=e.context)==null?void 0:m.referenceImages)||[];(t.mcp==="generate_image"||t.mcp==="generate_video")&&console.log("[SW-WorkflowExecutor] Image/Video step args before processing:",{stepId:t.id,referenceImagesInContext:r.length,referenceImagesValues:r.slice(0,2).map(p=>p.substring(0,50)+"..."),argsReferenceImages:t.args.referenceImages});const a=this.replaceImagePlaceholders(t.args,r),i=JSON.stringify(t.args),c=JSON.stringify(a);i!==c?(console.log("[SW-WorkflowExecutor] ✓ Replaced image placeholders:",{stepId:t.id,referenceImagesCount:r.length}),t.args=a):r.length>0&&(t.mcp==="generate_image"||t.mcp==="generate_video")&&console.log("[SW-WorkflowExecutor] No placeholders replaced (args unchanged):",{stepId:t.id,referenceImagesCount:r.length}),t.status="running",await E.saveWorkflow(e),this.broadcastStepStatus(e.id,t);try{if(Ze(t.mcp)||!Mt(t.mcp)){const p=await this.requestMainThreadTool(e.id,t.id,t.mcp,t.args);if(!p.success)throw new Error(p.error||"Main thread tool execution failed");if(p.addSteps&&p.addSteps.length>0){const u=[];for(const h of p.addSteps)e.steps.find(g=>g.id===h.id)||(e.steps.push({id:h.id,mcp:h.mcp,args:h.args,description:h.description,status:h.status}),u.push(h));u.length>0&&(await E.saveWorkflow(e),this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:e.id,steps:u}))}const S=p.result;if((t.mcp==="generate_image"||t.mcp==="generate_video")&&p.taskId){t.result={success:!0,type:t.mcp==="generate_image"?"image":"video",data:S,taskId:p.taskId,taskIds:p.taskIds},t.status="running",t.duration=Date.now()-n,this.broadcastStepStatus(e.id,t);return}t.result={success:!0,type:(S==null?void 0:S.type)||"text",data:S}}else{const p={geminiConfig:this.config.geminiConfig,videoConfig:this.config.videoConfig,signal:o,onProgress:(u,h)=>{},onRemoteId:u=>{}},S=await Ye(t.mcp,t.args,p);if(S.success&&S.type==="canvas"&&((y=S.data)!=null&&y.delegateToMainThread)){const u=await this.requestCanvasOperation(S.data.operation,S.data.args);if(!u.success)throw new Error(u.error||"Canvas operation failed");t.result={success:!0,type:"canvas",data:{completed:!0}}}else if(S.success&&S.type==="image"&&((w=S.data)!=null&&w.url)){const u=S.data,h=await this.requestCanvasOperation("canvas_insert",{items:[{type:"image",url:u.url}]});h.success||console.warn("[WorkflowExecutor] Failed to insert image to canvas:",h.error),t.result={success:!0,type:"image",data:S.data}}else if(S.success&&S.type==="video"&&((f=S.data)!=null&&f.url)){const u=S.data,h=await this.requestCanvasOperation("canvas_insert",{items:[{type:"video",url:u.url}]});h.success||console.warn("[WorkflowExecutor] Failed to insert video to canvas:",h.error),t.result={success:!0,type:"video",data:S.data}}else if(t.result={success:S.success,type:S.type||"text",data:S.data,error:S.error},!S.success)throw new Error(S.error||"Step execution failed");if(S.addSteps&&S.addSteps.length>0){console.log(`[SW-WorkflowExecutor] Adding ${S.addSteps.length} new steps from ${t.mcp}`);const u=[];for(const h of S.addSteps)e.steps.find(g=>g.id===h.id)||(e.steps.push({id:h.id,mcp:h.mcp,args:h.args,description:h.description,status:h.status}),u.push(h));u.length>0&&this.config.broadcast({type:"WORKFLOW_STEPS_ADDED",workflowId:e.id,steps:u})}}t.status="completed",t.duration=Date.now()-n}catch(p){t.status="failed",t.error=p.message,t.duration=Date.now()-n,t.result={success:!1,type:"error",error:p.message}}await E.saveWorkflow(e),this.broadcastStepStatus(e.id,t)}async requestMainThreadTool(e,t,o,n){if(this.config.requestMainThreadTool)return this.config.requestMainThreadTool(e,t,o,n);const r=`tool_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return new Promise((a,i)=>{const c=setTimeout(()=>{this.pendingToolRequests.delete(r),i(new Error(`Main thread tool request timed out: ${o}`))},3e5);this.pendingToolRequests.set(r,{resolve:l=>{clearTimeout(c),E.deletePendingToolRequest(r),a(l)},reject:l=>{clearTimeout(c),E.deletePendingToolRequest(r),i(l)},requestInfo:{requestId:r,workflowId:e,stepId:t,toolName:o,args:n},timeout:c}),E.savePendingToolRequest({requestId:r,workflowId:e,stepId:t,toolName:o,args:n,createdAt:Date.now()}),this.config.broadcast({type:"MAIN_THREAD_TOOL_REQUEST",requestId:r,workflowId:e,stepId:t,toolName:o,args:n})})}async requestCanvasOperation(e,t){if(this.config.requestCanvasOperation)return this.config.requestCanvasOperation(e,t);const o=`canvas_${Date.now()}_${Math.random().toString(36).substr(2,9)}`;return this.config.broadcast({type:"CANVAS_OPERATION_REQUEST",requestId:o,operation:e,params:t}),{success:!0}}broadcastWorkflowStatus(e){this.config.broadcast({type:"WORKFLOW_STATUS",workflowId:e.id,status:e.status,updatedAt:e.updatedAt})}broadcastStepStatus(e,t){this.config.broadcast({type:"WORKFLOW_STEP_STATUS",workflowId:e,stepId:t.id,status:t.status,result:t.result,error:t.error,duration:t.duration})}}function xt(s=0){return`tc_${Date.now()}_${s}_${Math.random().toString(36).substr(2,9)}`}function oe(s){const e=s.trim();try{return JSON.parse(e)}catch{try{return JSON.parse(co(e))}catch{return null}}}function vt(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 no(s){const e=s.trim();if(!e.startsWith("{")||!e.endsWith("}")||!e.includes('"content"')||!e.includes('"next"'))return!1;let t=0,o=0,n=!1,r=!1;for(const a of e){if(r){r=!1;continue}if(a==="\\"){r=!0;continue}if(a==='"'){n=!n;continue}n||(a==="{"?t++:a==="}"?t--:a==="["?o++:a==="]"&&o--)}return t===0&&o===0}function Nt(s){const e=vt(s);if(!no(e))return null;let t=oe(e);if(!t){const r=e.match(/\{\s*"content"\s*:\s*"[^"]*"\s*,\s*"next"\s*:\s*\[[\s\S]*?\]\s*\}/);r&&(t=oe(r[0]))}if(!t){const r=e.match(/\{[\s\S]*"content"[\s\S]*"next"[\s\S]*\}/);r&&(t=oe(r[0]))}if(!t||typeof t.content!="string")return null;const n=(Array.isArray(t.next)?t.next:[]).filter(r=>typeof r=="object"&&r!==null&&typeof r.mcp=="string"&&typeof r.args=="object").map(r=>({mcp:r.mcp,args:r.args}));return{content:t.content,next:n}}function ao(s){const e=Nt(s);if(e&&e.next.length>0)return e.next.map((a,i)=>({id:xt(i),name:a.mcp,arguments:a.args}));const t=[],o=a=>{if(!a.name||typeof a.name!="string")return null;const i=a.arguments||a.params||a.parameters||{};return{id:xt(),name:a.name,arguments:typeof i=="object"&&i!==null?i:{}}},n=/```tool_call\s*\n?([\s\S]*?)\n?```/gi;let r;for(;(r=n.exec(s))!==null;){const a=oe(r[1]);if(a){const i=o(a);i&&t.push(i)}}if(t.length===0){const a=/```(?:json)?\s*\n?([\s\S]*?)\n?```/gi;for(;(r=a.exec(s))!==null;){const i=oe(r[1]);if(i){const c=o(i);c&&t.push(c)}}}if(t.length===0){const a=/<tool_call>([\s\S]*?)<\/tool_call>/gi;for(;(r=a.exec(s))!==null;){const i=oe(r[1]);if(i){const c=o(i);c&&t.push(c)}}}if(t.length===0){const a=/\{[\s\S]*?"name"\s*:\s*"(?:generate_image|generate_video|generate_grid_image|generate_photo_wall)"[\s\S]*?\}/g;for(;(r=a.exec(s))!==null;){const i=oe(r[0]);if(i){const c=o(i);if(c){t.push(c);break}}}}return t}function io(s){const e=Nt(s);if(e)return e.content;let t=vt(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 io(s){let e=s.trim();const t=e.indexOf("{");t>0&&(e=e.substring(t));const o=e.lastIndexOf("}");return o<e.length-1&&o>0&&(e=e.substring(0,o+1)),e=e.replace(/:\s*"([^"]*)\n([^"]*)"/g,(n,r,a)=>`: "${r}\\n${a}"`),e=e.replace(/'([^']*?)'/g,(n,r)=>!r.includes(":")||r.length>50?`"${r}"`:n),e=e.replace(/([{,]\s*)(\w+)(\s*:)/g,'$1"$2"$3'),e=e.replace(/,(\s*[}\]])/g,"$1"),e=e.replace(/,\s*,/g,","),e=e.replace(/\/\/[^\n]*/g,""),e=e.replace(/\/\*[\s\S]*?\*\//g,""),e=e.replace(/:\s*undefined\b/g,": null"),e}function co(s){return no(s).map(t=>({...t,status:"pending"}))}class lo{constructor(e){this.workflows=new Map,this.abortControllers=new Map,this.workflowClients=new Map,this.pendingToolRequests=new Map,this.storageRestored=!1,this.config=e,this.restoreFromStorage()}async restoreFromStorage(){try{const e=await E.getAllChatWorkflows();for(const t of e){if(t.status==="completed"||t.status==="cancelled"||t.status==="failed"){this.workflows.set(t.id,t);continue}await this.handleInterruptedWorkflow(t)}this.storageRestored=!0}catch(e){console.error("[ChatWorkflowHandler] Failed to restore from storage:",e),this.storageRestored=!0}}async handleInterruptedWorkflow(e){let t;switch(e.status){case"streaming":t="AI 响应流传输时中断,请重试";break;case"parsing":t="工具调用解析时中断,请重试";break;case"executing_tools":t="工具执行时中断,请重试";break;case"pending":t="工作流尚未开始执行,请重试";break;default:t="工作流执行时中断,请重试"}e.status="failed",e.error=t,e.updatedAt=Date.now();for(const o of e.toolCalls)(o.status==="running"||o.status==="pending")&&(o.status="failed",o.result={success:!1,error:"Service Worker 重启导致执行中断"});this.workflows.set(e.id,e),await E.saveChatWorkflow(e)}updateConfig(e){this.config={...this.config,...e}}async startWorkflow(e,t,o){console.log("[SW-ChatWorkflow] ▶ startWorkflow:",{chatId:e,clientId:o,existingWorkflows:this.workflows.size,timestamp:new Date().toISOString()});const n=this.workflows.get(e);if(n){if(n.status==="streaming"||n.status==="pending"||n.status==="executing_tools"){console.log("[SW-ChatWorkflow] Re-claiming active workflow:",{chatId:e,status:n.status}),this.broadcastStatus(n);return}console.warn("[SW-ChatWorkflow] Workflow already exists, skipping:",{chatId:e,status:n.status}),this.broadcastStatus(n);return}this.workflowClients.set(e,o);const r={id:e,status:"pending",params:t,content:"",toolCalls:[],createdAt:Date.now(),updatedAt:Date.now()};this.workflows.set(e,r),await E.saveChatWorkflow(r);const a=new AbortController;this.abortControllers.set(e,a),this.executeWorkflow(r,a.signal)}async cancelWorkflow(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e));const o=this.workflows.get(e);o&&(o.status="cancelled",o.updatedAt=Date.now(),await E.saveChatWorkflow(o),this.broadcastStatus(o))}broadcastRecoveredWorkflows(){for(const e of this.workflows.values())this.config.broadcast({type:"CHAT_WORKFLOW_RECOVERED",chatId:e.id,workflow:e})}getWorkflow(e){return this.workflows.get(e)}getAllWorkflows(){return Array.from(this.workflows.values()).filter(e=>e.status!=="completed"&&e.status!=="failed"&&e.status!=="cancelled")}handleMainThreadToolResponse(e){const t=this.pendingToolRequests.get(e.requestId);t&&(this.pendingToolRequests.delete(e.requestId),t.resolve(e))}async executeWorkflow(e,t){try{e.status="streaming",await E.saveChatWorkflow(e),this.broadcastStatus(e);const o=await this.streamChat(e,t);if(e.content=o,t.aborted)throw new Error("Workflow cancelled");e.status="parsing",await E.saveChatWorkflow(e),this.broadcastStatus(e);const n=co(o),r=ao(o);e.toolCalls=n,e.aiAnalysis=r,n.length>0&&this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_CALLS",chatId:e.id,aiAnalysis:r,toolCalls:n}),n.length>0&&(e.status="executing_tools",await E.saveChatWorkflow(e),this.broadcastStatus(e),await this.executeTools(e,t)),e.status="completed",e.completedAt=Date.now(),e.updatedAt=Date.now(),await E.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_COMPLETE",chatId:e.id,content:e.content,aiAnalysis:e.aiAnalysis,toolCalls:e.toolCalls})}catch(o){o.message==="Workflow cancelled"?e.status="cancelled":(e.status="failed",e.error=o.message,this.config.broadcast({type:"CHAT_WORKFLOW_FAILED",chatId:e.id,error:o.message})),e.updatedAt=Date.now(),await E.saveChatWorkflow(e)}finally{this.abortControllers.delete(e.id)}}async streamChat(e,t){var f,p,S,u,h,g;const{params:o}=e,{geminiConfig:n}=this.config,r=this.convertToGeminiMessages(o),a=o.temporaryModel||n.modelName||"gemini-2.5-flash";console.log("[SW-ChatWorkflow] streamChat called:",{workflowId:e.id,model:a,messagesCount:r.length,timestamp:new Date().toISOString()});const i={model:a,messages:r,stream:!0},{debugFetch:c}=await Promise.resolve().then(()=>N),l=await c(`${n.baseUrl}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`},body:JSON.stringify(i),signal:t},{label:`💬 工作流对话 (${a})`,logRequestBody:!0,isStreaming:!0});if(!l.ok){const T=await l.text();throw new Error(`Chat request failed: ${l.status} - ${T}`)}if(!l.body)throw new Error("No response body");const d=l.body.getReader(),m=new TextDecoder;let y="",w="";try{for(;;){const{done:T,value:_}=await d.read();if(T)break;w+=m.decode(_,{stream:!0});const C=w.split(`
5
- `);w=C.pop()||"";for(const D of C)if(D.startsWith("data: ")){const b=D.slice(6).trim();if(b==="[DONE]")continue;try{const z=(S=(p=(f=JSON.parse(b).choices)==null?void 0:f[0])==null?void 0:p.delta)==null?void 0:S.content;z&&(y+=z,this.config.broadcast({type:"CHAT_WORKFLOW_STREAM",chatId:e.id,content:y}))}catch{}}}if(w.startsWith("data: ")){const T=w.slice(6).trim();if(T&&T!=="[DONE]")try{const C=(g=(h=(u=JSON.parse(T).choices)==null?void 0:u[0])==null?void 0:h.delta)==null?void 0:g.content;C&&(y+=C,this.config.broadcast({type:"CHAT_WORKFLOW_STREAM",chatId:e.id,content:y}))}catch{}}}finally{d.releaseLock()}if(l.__debugLogId&&y){const{updateLogResponseBody:T}=await Promise.resolve().then(()=>N);T(l.__debugLogId,y)}return y}async executeTools(e,t){const o=this.workflowClients.get(e.id);for(const n of e.toolCalls){if(t.aborted)throw new Error("Workflow cancelled");n.status="running",this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_START",chatId:e.id,toolCallId:n.id,toolName:n.name});try{let r;if(Ze(n.name)||!xt(n.name)){if(!o)throw new Error("No client ID found for workflow");const a=await this.config.requestMainThreadTool(o,e.id,n.id,n.name,n.arguments);r={success:a.success,data:a.result,error:a.error}}else{const a={geminiConfig:this.config.geminiConfig,videoConfig:this.config.videoConfig,signal:t},i=await Ye(n.name,n.arguments,a);r={success:i.success,data:i.data,error:i.error,taskId:i.taskId}}n.status=r.success?"completed":"failed",n.result=r,await E.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_COMPLETE",chatId:e.id,toolCallId:n.id,success:r.success,result:r.data,error:r.error,taskId:r.taskId})}catch(r){n.status="failed",n.result={success:!1,error:r.message},await E.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_COMPLETE",chatId:e.id,toolCallId:n.id,success:!1,error:r.message})}}}convertToGeminiMessages(e){var o;const t=[];e.systemPrompt&&t.push({role:"system",content:[{type:"text",text:e.systemPrompt}]});for(const n of e.messages){const r=[];if(n.content&&r.push({type:"text",text:n.content}),n.attachments)for(const a of n.attachments)a.type==="image"&&r.push({type:"image_url",image_url:{url:`data:${a.mimeType};base64,${a.data}`}});t.push({role:n.role,content:r})}if(e.newContent||(o=e.attachments)!=null&&o.length){const n=[];if(e.newContent&&n.push({type:"text",text:e.newContent}),e.attachments)for(const r of e.attachments)r.type==="image"&&n.push({type:"image_url",image_url:{url:`data:${r.mimeType};base64,${r.data}`}});t.push({role:"user",content:n})}return t}broadcastStatus(e){this.config.broadcast({type:"CHAT_WORKFLOW_STATUS",chatId:e.id,status:e.status,updatedAt:e.updatedAt})}}let M=null,j=null,le=null,ue=null;function et(s,e,t){le=e,ue=t,M=new oo({geminiConfig:e,videoConfig:t,broadcast:n=>he(n)});const o=Je();o&&o.setTaskStatusChangeCallback((n,r,a,i)=>{M==null||M.updateWorkflowStepForTask(n,r,a,i)}),j=new lo({geminiConfig:e,videoConfig:t,broadcast:n=>he(n),sendToClient:(n,r)=>st(n,r),requestMainThreadTool:async(n,r,a,i,c)=>{const l=`chat_tool_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return new Promise((d,m)=>{const y=setTimeout(()=>{de.delete(l),E.deletePendingToolRequest(l),m(new Error(`Tool request timed out: ${i}`))},3e5);de.set(l,{resolve:w=>{clearTimeout(y),E.deletePendingToolRequest(l),d(w)},reject:w=>{clearTimeout(y),E.deletePendingToolRequest(l),m(w)},requestInfo:{requestId:l,chatId:r,toolCallId:a,toolName:i,args:c,clientId:n},timeout:y}),E.savePendingToolRequest({requestId:l,workflowId:r,stepId:a,toolName:i,args:c,createdAt:Date.now(),clientId:n}),st(n,{type:"MAIN_THREAD_TOOL_REQUEST",requestId:l,workflowId:r,stepId:a,toolName:i,args:c})})}})}const de=new Map;function uo(s,e){if(!M){console.warn("[WorkflowHandler] Not initialized");return}s&&(le={...le||{},...s}),e&&(ue={...ue||{},...e}),!(!le||!ue)&&(M.updateConfig({geminiConfig:le,videoConfig:ue}),j&&j.updateConfig({geminiConfig:le,videoConfig:ue}))}function ho(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 tt(s,e){if(s.type.startsWith("CHAT_WORKFLOW_")){fo(s,e);return}if(!M){console.error("[WorkflowHandler] ✗ Not initialized, ignoring message:",s.type);return}const t=s;switch(t.type){case"WORKFLOW_SUBMIT":console.log("[SW-WorkflowHandler] ▶ WORKFLOW_SUBMIT received:",{workflowId:t.workflow.id,clientId:e,timestamp:new Date().toISOString()}),M.submitWorkflow(t.workflow);break;case"WORKFLOW_CANCEL":M.cancelWorkflow(t.workflowId);break;case"WORKFLOW_GET_STATUS":{const o=M.getWorkflow(t.workflowId);he({type:"WORKFLOW_STATUS_RESPONSE",workflowId:t.workflowId,workflow:o||null});break}case"WORKFLOW_GET_ALL":{const o=M.getAllWorkflows();he({type:"WORKFLOW_ALL_RESPONSE",workflows:o});break}}}function fo(s,e){var t;if(!j){console.error("[WorkflowHandler] ✗ Chat workflow handler not initialized");return}switch(s.type){case"CHAT_WORKFLOW_START":console.log("[SW-Workflow] ▶ CHAT_WORKFLOW_START received:",{chatId:s.chatId,clientId:e,stepsCount:(t=s.params.steps)==null?void 0:t.length,timestamp:new Date().toISOString()}),j.startWorkflow(s.chatId,s.params,e);break;case"CHAT_WORKFLOW_CANCEL":j.cancelWorkflow(s.chatId);break;case"CHAT_WORKFLOW_GET_STATUS":{const o=j.getWorkflow(s.chatId);he({type:"CHAT_WORKFLOW_STATUS_RESPONSE",chatId:s.chatId,workflow:o||null});break}case"CHAT_WORKFLOW_GET_ALL":{const o=j.getAllWorkflows();he({type:"CHAT_WORKFLOW_ALL_RESPONSE",workflows:o});break}}}async function go(s){const e=de.get(s.requestId);if(e){de.delete(s.requestId),e.resolve(s);return}if(await E.deletePendingToolRequest(s.requestId),!M){console.error("[WorkflowHandler] ✗ Not initialized, ignoring tool response");return}M.handleMainThreadToolResponse(s)}function po(){if(M&&(M.broadcastRecoveredWorkflows(),M.resendPendingToolRequests()),j&&j.broadcastRecoveredWorkflows(),de.size!==0)for(const[,s]of de){const{requestInfo:e}=s;st(e.clientId,{type:"MAIN_THREAD_TOOL_REQUEST",requestId:e.requestId,workflowId:e.chatId,stepId:e.toolCallId,toolName:e.toolName,args:e.args})}}function he(s){Rt(s)}async function st(s,e){await Me(s,e)||Rt(e)}const be=[],mo=100;let ot=!1,J=null;function wo(s){ot=s}function rt(){return ot}function Bt(s){J=s}function Ut(){return[...be]}function So(s,e){const t=be.find(o=>o.id===s);t&&(t.responseBody=e.length>5e3?e.substring(0,5e3)+"...(truncated)":e,J&&J({...t}))}async function yo(s){return new Promise((e,t)=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.onerror=t,o.readAsDataURL(s)})}async function To(s){const e=[];for(const[t,o]of s.entries())if(o instanceof Blob){const n={name:t,value:`[${o.type||"binary"}] ${o.size} bytes`,isFile:!0,mimeType:o.type};if(o.type.startsWith("image/")&&o.size<5*1024*1024)try{n.dataUrl=await yo(o)}catch{}o instanceof File&&(n.fileName=o.name),e.push(n)}else e.push({name:t,value:String(o).length>500?String(o).substring(0,500)+"...":String(o)});return e}async function Eo(s,e,t){if(!ot)return fetch(s,e);const o=typeof s=="string"?s:s instanceof URL?s.href:s.url,n=(e==null?void 0:e.method)||"GET",r=Date.now(),a=Math.random().toString(36).substring(2,10);let i,c,l;if(e!=null&&e.body){if(e.body instanceof FormData)try{c=await To(e.body)}catch{i="[FormData - unable to parse]"}else if(t!=null&&t.logRequestBody)try{const m=typeof e.body=="string"?e.body:JSON.stringify(e.body),y=/data:image\/([^;]+);base64,([A-Za-z0-9+/=]+)/g;let w,f=0;for(l=[];(w=y.exec(m))!==null;){const u=`image/${w[1]}`,h=w[2];h.length>1e3&&(l.push({key:`image[${f}]`,dataUrl:`data:${u};base64,${h}`,mimeType:u,size:Math.round(h.length*.75/1024)}),f++)}l.length===0&&(l=void 0);let p=m.replace(/data:image\/([^;]+);base64,[A-Za-z0-9+/=]+/g,(u,h)=>`[📷 image/${h}]`);i=!o.includes("/chat/completions")&&p.length>3e3?p.substring(0,3e3)+"...(truncated)":p}catch{i="[unable to serialize body]"}}const d={id:a,timestamp:r,url:o,method:n,requestType:"sw-internal",details:(t==null?void 0:t.label)||`SW Internal: ${n} ${new URL(o).pathname}`,requestBody:i,formData:c,base64Images:l,isStreaming:t==null?void 0:t.isStreaming};be.unshift(d),be.length>mo&&be.pop(),J&&J({...d});try{const m=await fetch(s,e);if(d.status=m.status,d.statusText=m.statusText,d.duration=Date.now()-r,t!=null&&t.isStreaming)d.responseBody="[流式响应 - 数据通过 SSE/Stream 实时传输,无法捕获完整响应体]";else if(t!=null&&t.logResponseBody)try{const y=m.headers.get("content-type")||"";if(y.includes("application/json")||y.includes("text/")){const f=await m.clone().text();d.responseBody=f.length>2e3?f.substring(0,2e3)+"...(truncated)":f}}catch{}return J&&J({...d}),m.__debugLogId=a,m}catch(m){const y=m.message||String(m);let w="NETWORK_ERROR";throw y.includes("ERR_CONNECTION_CLOSED")?w="ERR_CONNECTION_CLOSED":y.includes("ERR_CONNECTION_REFUSED")?w="ERR_CONNECTION_REFUSED":y.includes("ERR_CONNECTION_RESET")?w="ERR_CONNECTION_RESET":y.includes("ERR_CONNECTION_TIMED_OUT")||y.includes("timeout")?w="ERR_TIMEOUT":y.includes("ERR_NAME_NOT_RESOLVED")?w="ERR_DNS_FAILED":y.includes("ERR_INTERNET_DISCONNECTED")?w="ERR_OFFLINE":y.includes("ERR_SSL")||y.includes("certificate")?w="ERR_SSL":y.includes("Failed to fetch")?w="FETCH_FAILED":(y.includes("AbortError")||y.includes("aborted"))&&(w="ABORTED"),d.status=0,d.statusText=w,d.error=y,d.duration=Date.now()-r,J&&J({...d}),m}}const N=Object.freeze(Object.defineProperty({__proto__:null,debugFetch:Eo,getInternalFetchLogs:Ut,isDebugFetchEnabled:rt,setDebugFetchBroadcast:Bt,setDebugFetchEnabled:wo,updateLogResponseBody:So},Symbol.toStringTag,{value:"Module"})),Co=typeof location<"u"&&(location.hostname==="localhost"||location.hostname==="127.0.0.1"),nt={degradeTimeout:60*1e3,failThreshold:3,fetchTimeout:1e4},at=[{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}],fe=new Map;function qt(){at.forEach(s=>{fe.has(s.name)||fe.set(s.name,{name:s.name,isHealthy:!0,lastCheckTime:0,failCount:0,lastSuccessTime:Date.now()})})}qt();function Ft(s){const e=fe.get(s);e&&(e.isHealthy=!0,e.failCount=0,e.lastSuccessTime=Date.now(),e.lastCheckTime=Date.now())}function ve(s){const e=fe.get(s);e&&(e.failCount++,e.lastCheckTime=Date.now(),e.failCount>=nt.failThreshold&&(e.isHealthy=!1,console.warn(`[CDN Fallback] ${s} marked as unhealthy after ${e.failCount} failures`)))}function _o(s){const e=fe.get(s);return e?e.isHealthy?!0:Date.now()-e.lastCheckTime>nt.degradeTimeout?(console.log(`[CDN Fallback] Trying to recover ${s}...`),!0):!1:!1}function bo(){return at.filter(s=>s.enabled&&_o(s.name)).sort((s,e)=>s.priority-e.priority)}function Gt(s,e,t){return s.urlTemplate.replace("{version}",e).replace("{path}",t.startsWith("/")?t.slice(1):t)}async function it(s,e=nt.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 Ao(s,e,t){if(Co)return console.log("[CDN Fallback] 开发模式,跳过 CDN 回退"),null;const o=bo();for(const n of o){const r=Gt(n,e,s);try{console.log(`[CDN Fallback] Trying ${n.name}: ${r}`);const a=await it(r);if(a.ok)return Ft(n.name),console.log(`[CDN Fallback] Success from ${n.name}`),{response:a,source:n.name};console.warn(`[CDN Fallback] ${n.name} returned ${a.status}`),ve(n.name)}catch(a){console.warn(`[CDN Fallback] ${n.name} failed:`,a),ve(n.name)}}try{const n=`${t}/${s.startsWith("/")?s.slice(1):s}`;console.log(`[CDN Fallback] Trying local server: ${n}`);const r=await it(n);if(r.ok)return console.log("[CDN Fallback] Success from local server"),{response:r,source:"local"}}catch(n){console.warn("[CDN Fallback] Local server failed:",n)}return console.error(`[CDN Fallback] All sources failed for: ${s}`),null}async function Ro(s){const e=new Map;for(const t of at){if(!t.enabled)continue;const o=Gt(t,s,t.healthCheckPath);try{const r=(await it(o,5e3)).ok;e.set(t.name,r),r?Ft(t.name):ve(t.name)}catch{e.set(t.name,!1),ve(t.name)}}return e}function Do(){return Array.from(fe.entries()).map(([s,e])=>({name:s,status:e}))}function Wo(){qt(),console.log("[CDN Fallback] All CDN status reset")}const R=self;Zs(R),ks();const re={log:console.log.bind(console),info:console.info.bind(console),warn:console.warn.bind(console),error:console.error.bind(console)};function Lo(){console.log=(...s)=>{re.log(...s),rt()&&Be("log",s)},console.info=(...s)=>{re.info(...s),rt()&&Be("info",s)},console.warn=(...s)=>{re.warn(...s),Be("warn",s)},console.error=(...s)=>{re.error(...s),Be("error",s)}}function Be(s,e){const t=e.map(n=>{if(typeof n=="object")try{return JSON.stringify(n)}catch{return String(n)}return String(n)}).join(" "),o=t.startsWith("[SW]")||t.startsWith("[SW-")?t:`[SW] ${t}`;typeof ct=="function"&&ct({logLevel:s,logMessage:o,logSource:"service-worker"})}let ct=null;Lo(),Bt(s=>{R.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_DEBUG_LOG",entry:{...s,type:"fetch"}})})})}),Promise.resolve().then(()=>I).then(({setLLMApiLogBroadcast:s})=>{s(e=>{R.clients.matchAll().then(t=>{t.forEach(o=>{o.postMessage({type:"SW_DEBUG_LLM_API_LOG",log:e})})})})});const Z="0.5.21",Ue=`drawnix-v${Z}`,x="drawnix-images",ge=`drawnix-static-v${Z}`,qe="drawnix-fonts",Io="/__aitu_cache__/",Oo="/asset-library/",lt=location.hostname==="localhost"||location.hostname==="127.0.0.1",ko=[{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"}],Mo=/\.(jpg|jpeg|png|gif|webp|svg|bmp|ico)$/i,xo=/\.(mp4|webm|ogg|mov|avi|mkv|flv|wmv|m4v)$/i,G=new Map,ne=new Map,$t=30*1e3,Ae=new Map,q=new Map,Po=300*1e3,Ht=10,pe=new Set,me=new Set,No=3600*1e3,ut=new Map;function Kt(s){me.add(s),ut.set(s,Date.now()),console.warn(`Service Worker: 标记 ${s} 为 CORS 问题域名,后续请求将跳过 SW`)}function vo(s){if(!me.has(s))return!1;const e=ut.get(s);return e&&Date.now()-e>No?(me.delete(s),ut.delete(s),!1):!0}const Re=[],Bo=7,V=[],Uo=500;let F=!1,we=0;const qo=15e3;let Q=null;function zt(){if(!F)return;const s=Date.now();we>0&&s-we>qo?(re.log("Service Worker: Debug heartbeat timeout, auto-disabling debug mode"),F=!1,we=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"})})}),Q&&(clearTimeout(Q),Q=null)):F&&(Q=setTimeout(zt,5e3))}function $(s){if(!F)return"";const e=Math.random().toString(36).substring(2,10),t={...s,id:e,timestamp:Date.now()};return V.unshift(t),V.length>Uo&&V.pop(),jt(t),e}function P(s,e){if(!F||!s)return;const t=V.find(o=>o.id===s);t&&(Object.assign(t,e),jt(t))}async function jt(s){try{(await R.clients.matchAll()).forEach(t=>{t.postMessage({type:"SW_DEBUG_LOG",entry:s})})}catch{}}function Fe(){return new Promise((s,e)=>{const t=indexedDB.open("ConsoleLogDB",1);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const n=o.target.result;if(!n.objectStoreNames.contains("logs")){const r=n.createObjectStore("logs",{keyPath:"id"});r.createIndex("timestamp","timestamp",{unique:!1}),r.createIndex("logLevel","logLevel",{unique:!1})}}})}async function Fo(s){try{const e=await Fe(),t=e.transaction(["logs"],"readwrite");return t.objectStore("logs").add(s),new Promise((n,r)=>{t.oncomplete=()=>{e.close(),n()},t.onerror=()=>{e.close(),r(t.error)}})}catch(e){console.warn("Service Worker: 无法保存控制台日志:",e)}}async function Vt(){try{const s=await Fe(),o=s.transaction(["logs"],"readonly").objectStore("logs").index("timestamp");return new Promise((n,r)=>{const a=o.openCursor(null,"prev"),i=[];a.onsuccess=()=>{const c=a.result;c?(i.push(c.value),c.continue()):(s.close(),n(i))},a.onerror=()=>{s.close(),r(a.error)}})}catch(s){return console.warn("Service Worker: 无法加载控制台日志:",s),[]}}async function Go(){try{const s=await Fe(),o=s.transaction(["logs"],"readwrite").objectStore("logs").index("timestamp"),n=Date.now()-Bo*24*60*60*1e3,r=IDBKeyRange.upperBound(n);return new Promise((a,i)=>{const c=o.openCursor(r);let l=0;c.onsuccess=()=>{const d=c.result;d?(d.delete(),l++,d.continue()):(s.close(),l>0&&console.log(`Service Worker: 清理了 ${l} 条过期控制台日志`),a(l))},c.onerror=()=>{s.close(),i(c.error)}})}catch(s){return console.warn("Service Worker: 无法清理过期日志:",s),0}}async function Qt(){try{const s=await Fe(),e=s.transaction(["logs"],"readwrite");return e.objectStore("logs").clear(),new Promise((o,n)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),n(e.error)}})}catch(s){console.warn("Service Worker: 无法清空控制台日志:",s)}}function Xt(s){if(!F)return;const t={id:Math.random().toString(36).substring(2,10),timestamp:Date.now(),type:"console",...s};Re.unshift(t),Fo(t),$o(t)}ct=Xt;async function $o(s){try{(await R.clients.matchAll()).forEach(t=>{t.postMessage({type:"SW_CONSOLE_LOG",entry:s})})}catch{}}function Ho(){let s=0;return q.forEach(e=>{e.blob&&(s+=e.blob.size)}),s}function Ge(){return{version:Z,cacheNames:[Ue,x,ge,qe],pendingImageRequests:G.size,pendingVideoRequests:Ae.size,videoBlobCacheSize:q.size,videoBlobCacheTotalBytes:Ho(),completedImageRequestsSize:ne.size,failedDomainsCount:pe.size,failedDomains:Array.from(pe),corsFailedDomainsCount:me.size,corsFailedDomains:Array.from(me),debugLogsCount:V.length,consoleLogsCount:Re.length,debugModeEnabled:F,workflowHandlerInitialized:ae,memoryStats:{pendingRequestsMapSize:G.size,completedRequestsMapSize:ne.size,videoBlobCacheMapSize:q.size,failedDomainsSetSize:pe.size,corsFailedDomainsSetSize:me.size,debugLogsArraySize:V.length,consoleLogsArraySize:Re.length}}}function Jt(s){for(const e of ko)if(s.hostname===e.hostname&&s.pathname.includes(e.pathPattern))return e;return null}function Ko(s,e){return Mo.test(s.pathname)||e.destination==="image"||Jt(s)!==null}function zo(s,e){return xo.test(s.pathname)||e.destination==="video"||s.pathname.includes("/video/")||s.hash.startsWith("#merged-video-")||s.hash.includes("video")}function jo(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 Vo(){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=>pe.add(c.domain)),e()},a.onerror=()=>t(a.error)}else e()},s.onupgradeneeded=o=>{const n=o.target.result;n.objectStoreNames.contains("failedDomains")||n.createObjectStore("failedDomains",{keyPath:"domain"})}})}catch(s){console.warn("Service Worker: 无法加载失败域名列表:",s)}}async function Qo(s){try{const e=indexedDB.open("ServiceWorkerDB",1);return new Promise((t,o)=>{e.onerror=()=>o(e.error),e.onsuccess=()=>{const r=e.result.transaction(["failedDomains"],"readwrite");r.objectStore("failedDomains").put({domain:s,timestamp:Date.now()}),r.oncomplete=()=>{t()},r.onerror=()=>o(r.error)},e.onupgradeneeded=n=>{const r=n.target.result;r.objectStoreNames.contains("failedDomains")||r.createObjectStore("failedDomains",{keyPath:"domain"})}})}catch(e){console.warn("Service Worker: 无法保存失败域名:",e)}}function Xo(s){s&&R.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_NEW_VERSION_READY",version:Z})})})}async function Jo(s){try{const e=await s.keys();if(e.length<=10)return;const t=[];for(const a of e)try{const i=await s.match(a);if(i){const c=i.headers.get("sw-cache-date"),l=i.headers.get("sw-image-size");t.push({request:a,cacheDate:c?parseInt(c):0,imageSize:l?parseInt(l):0})}}catch(i){console.warn("Service Worker: Error reading cache entry:",i)}t.sort((a,i)=>a.cacheDate-i.cacheDate);const o=Math.max(1,Math.floor(t.length*.25));let n=0,r=0;for(let a=0;a<o&&a<t.length;a++)try{await s.delete(t[a].request),n++,r+=t[a].imageSize}catch(i){console.warn("Service Worker: Error deleting cache entry:",i)}}catch(e){console.warn("Service Worker: Cache cleanup failed:",e)}}const Yo=["/","/index.html","/manifest.json","/favicon.ico","/icons/favicon-new.svg"];R.addEventListener("install",s=>{const e=[];e.push(Vo()),lt||e.push(caches.open(ge).then(async t=>{const n=(await Promise.allSettled(Yo.map(async r=>{try{const a=await fetch(r,{cache:"reload"});return a.ok?(await t.put(r,a),{url:r,success:!0}):{url:r,success:!1,status:a.status}}catch(a){return{url:r,success:!1,error:String(a)}}}))).filter(r=>r.status==="rejected"||r.status==="fulfilled"&&!r.value.success);n.length>0&&console.warn("Service Worker: Some static files failed to cache:",n.length)}).catch(t=>{console.warn("Service Worker: Cache pre-loading failed:",t)})),s.waitUntil(Promise.all(e).then(async()=>{const t=await caches.keys(),o=t.some(a=>a.startsWith("drawnix-static-v")&&a!==ge),n=t.some(a=>a.startsWith("drawnix-v")&&a!==Ue&&a!==x&&!a.startsWith("drawnix-static-v"));Xo(o||n)}))}),R.addEventListener("activate",s=>{s.waitUntil(caches.keys().then(async e=>{const t=e.filter(r=>r.startsWith("drawnix-images-v")&&r!==x);if(t.length>0){const r=await caches.open(x);for(const a of t)try{const i=await caches.open(a),c=await i.keys();for(const l of c){const d=await i.match(l);d&&await r.put(l,d)}await caches.delete(a)}catch(i){console.warn(`Failed to migrate cache ${a}:`,i)}}const o=e.filter(r=>r.startsWith("drawnix-static-v")&&r!==ge),n=e.filter(r=>r.startsWith("drawnix-v")&&r!==Ue&&r!==x&&!r.startsWith("drawnix-static-v"));return(o.length>0||n.length>0)&&setTimeout(async()=>{for(const r of[...o,...n])try{await caches.delete(r)}catch(a){console.warn("Failed to delete old cache:",r,a)}},3e4),Go().catch(r=>{console.warn("Failed to cleanup expired console logs:",r)}),R.clients.claim()}))});const Zo=["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 er(s){if(!s||typeof s!="object")return!1;const e=s;return e.type?Zo.includes(e.type):!1}let ae=!1,Se=null,ye=null;const $e=[];function Yt(s){F&&R.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_POSTMESSAGE_LOG",entry:s})})})}Os(Yt),R.addEventListener("message",s=>{var n,r,a,i,c,l,d,m,y,w,f,p,S;const e=((n=s.data)==null?void 0:n.type)||"unknown",t=((r=s.source)==null?void 0:r.id)||"";let o="";if(Ke()&&(o=Rs(e,s.data,t),o&&F)){const h=Ce().find(g=>g.id===o);h&&Yt(h)}if(s.data&&er(s.data)){const u=((a=s.source)==null?void 0:a.id)||"";if(eo(s.data,u),s.data.type==="TASK_QUEUE_INIT"){const{geminiConfig:h,videoConfig:g}=s.data;if(Se=h,ye=g,!ae&&(et(R,h,g),ae=!0,$e.length>0)){for(const T of $e)tt(T.message,T.clientId);$e.length=0}po()}if(s.data.type==="TASK_QUEUE_UPDATE_CONFIG"){const{geminiConfig:h,videoConfig:g}=s.data;h&&(Se={...Se,...h}),g&&(ye={...ye,...g}),uo(h,g)}return}if(s.data&&ho(s.data)){const u=((i=s.source)==null?void 0:i.id)||"";if(!ae&&Se&&ye&&(et(R,Se,ye),ae=!0),!ae){(async()=>{try{const{geminiConfig:h,videoConfig:g}=await E.loadConfig();if(h&&g)Se=h,ye=g,et(R,h,g),ae=!0,tt(s.data,u);else{console.warn("[SW] Cannot initialize workflow handler: no config in storage, requesting config from main thread");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});$e.push({message:s.data,clientId:u})}}catch(h){console.error("[SW] Failed to load config from storage:",h)}})();return}tt(s.data,u);return}if(s.data&&s.data.type==="MAIN_THREAD_TOOL_RESPONSE"){go(s.data);return}if(s.data&&s.data.type==="SKIP_WAITING")R.skipWaiting(),R.clients.matchAll().then(u=>{u.forEach(h=>{h.postMessage({type:"SW_UPDATED"})})});else if(s.data&&s.data.type==="GET_UPGRADE_STATUS")(c=s.source)==null||c.postMessage({type:"UPGRADE_STATUS",version:Z});else if(s.data&&s.data.type==="FORCE_UPGRADE")R.skipWaiting(),R.clients.matchAll().then(u=>{u.forEach(h=>{h.postMessage({type:"SW_UPDATED"})})});else if(s.data&&s.data.type==="DELETE_CACHE"){const{url:u}=s.data;u&&lr(u).then(()=>{R.clients.matchAll().then(h=>{h.forEach(g=>{g.postMessage({type:"CACHE_DELETED",url:u})})})}).catch(h=>{console.error("Service Worker: Failed to delete cache:",h)})}else if(s.data&&s.data.type==="DELETE_CACHE_BATCH"){const{urls:u}=s.data;u&&Array.isArray(u)&&ur(u).then(()=>{}).catch(h=>{console.error("Service Worker: Failed to batch delete caches:",h)})}else if(s.data&&s.data.type==="CLEAR_ALL_CACHE")dr().then(()=>{}).catch(u=>{console.error("Service Worker: Failed to clear all cache:",u)});else if(s.data&&s.data.type==="SW_DEBUG_ENABLE")F=!0,we=Date.now(),Promise.resolve().then(()=>N).then(({setDebugFetchEnabled:u})=>{u(!0)}),je(!0),re.log("Service Worker: Debug mode enabled"),Q&&clearTimeout(Q),Q=setTimeout(zt,5e3),R.clients.matchAll().then(u=>{u.forEach(h=>{h.postMessage({type:"SW_DEBUG_ENABLED"})})}),(l=s.source)==null||l.postMessage({type:"SW_DEBUG_STATUS",status:Ge()});else if(s.data&&s.data.type==="SW_DEBUG_HEARTBEAT")F&&(we=Date.now());else if(s.data&&s.data.type==="SW_DEBUG_DISABLE")F=!1,we=0,Q&&(clearTimeout(Q),Q=null),Promise.resolve().then(()=>N).then(({setDebugFetchEnabled:u})=>{u(!1)}),je(!1),Re.length=0,V.length=0,Qt().catch(()=>{}),re.log("Service Worker: Debug mode disabled, logs cleared"),R.clients.matchAll().then(u=>{u.forEach(h=>{h.postMessage({type:"SW_DEBUG_DISABLED"})})}),(d=s.source)==null||d.postMessage({type:"SW_DEBUG_STATUS",status:Ge()});else if(s.data&&s.data.type==="SW_DEBUG_GET_STATUS")(async()=>{var g;const u=Ge(),h=await cr();(g=s.source)==null||g.postMessage({type:"SW_DEBUG_STATUS",status:{...u,cacheStats:h}})})();else if(s.data&&s.data.type==="SW_DEBUG_GET_LOGS"){const{limit:u=100,offset:h=0,filter:g}=s.data,T=Ut().map(b=>({...b,type:"fetch"})),_=new Map;for(const b of V)_.set(b.id,b);for(const b of T)_.set(b.id,b);let C=Array.from(_.values()).sort((b,O)=>O.timestamp-b.timestamp);g&&(g.type&&(C=C.filter(b=>b.type===g.type)),g.requestType&&(C=C.filter(b=>b.requestType===g.requestType)),g.url&&(C=C.filter(b=>{var O;return(O=b.url)==null?void 0:O.includes(g.url)})),g.status&&(C=C.filter(b=>b.status===g.status)));const D=C.slice(h,h+u);(m=s.source)==null||m.postMessage({type:"SW_DEBUG_LOGS",logs:D,total:C.length,offset:h,limit:u})}else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_LOGS")V.length=0,(y=s.source)==null||y.postMessage({type:"SW_DEBUG_LOGS_CLEARED"});else if(s.data&&s.data.type==="SW_CDN_GET_STATUS")(w=s.source)==null||w.postMessage({type:"SW_CDN_STATUS",status:Do()});else if(s.data&&s.data.type==="SW_CDN_RESET_STATUS")Wo(),(f=s.source)==null||f.postMessage({type:"SW_CDN_STATUS_RESET"});else if(s.data&&s.data.type==="SW_CDN_HEALTH_CHECK")(async()=>{var h;const u=await Ro(Z);(h=s.source)==null||h.postMessage({type:"SW_CDN_HEALTH_CHECK_RESULT",results:Object.fromEntries(u)})})();else if(s.data&&s.data.type==="SW_DEBUG_GET_CACHE_ENTRIES"){const{cacheName:u,limit:h=50,offset:g=0}=s.data;(async()=>{var T,_;try{const C=await caches.open(u||x),D=await C.keys(),b=[];for(let O=g;O<Math.min(g+h,D.length);O++){const z=D[O],X=await C.match(z);if(X){const De=X.headers.get("sw-cache-date"),We=X.headers.get("sw-image-size")||X.headers.get("content-length");b.push({url:z.url,cacheDate:De?parseInt(De):void 0,size:We?parseInt(We):void 0})}}(T=s.source)==null||T.postMessage({type:"SW_DEBUG_CACHE_ENTRIES",cacheName:u||x,entries:b,total:D.length,offset:g,limit:h})}catch(C){(_=s.source)==null||_.postMessage({type:"SW_DEBUG_CACHE_ENTRIES",error:String(C)})}})()}else if(s.data&&s.data.type==="SW_CONSOLE_LOG_REPORT"){const{logLevel:u,logMessage:h,logStack:g,logSource:T,url:_}=s.data;Xt({logLevel:u,logMessage:h,logStack:g,logSource:T,url:_})}else if(s.data&&s.data.type==="SW_DEBUG_GET_CONSOLE_LOGS")(async()=>{var u,h;try{const{limit:g=500,offset:T=0,filter:_}=s.data;let C=await Vt();if(_&&(_.logLevel&&(C=C.filter(b=>b.logLevel===_.logLevel)),_.search)){const b=_.search.toLowerCase();C=C.filter(O=>{var z,X;return((z=O.logMessage)==null?void 0:z.toLowerCase().includes(b))||((X=O.logStack)==null?void 0:X.toLowerCase().includes(b))})}const D=C.slice(T,T+g);(u=s.source)==null||u.postMessage({type:"SW_DEBUG_CONSOLE_LOGS",logs:D,total:C.length,offset:T,limit:g})}catch(g){(h=s.source)==null||h.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 u;Re.length=0,await Qt(),(u=s.source)==null||u.postMessage({type:"SW_DEBUG_CONSOLE_LOGS_CLEARED"})})();else if(s.data&&s.data.type==="SW_DEBUG_EXPORT_LOGS")(async()=>{var T;const u=await Vt(),h=Ce(),g={exportTime:new Date().toISOString(),swVersion:Z,userAgent:"",status:Ge(),fetchLogs:V,consoleLogs:u,postmessageLogs:h};(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:u=200,offset:h=0,filter:g}=s.data;let T=Ce();if(g&&(g.direction&&(T=T.filter(C=>C.direction===g.direction)),g.messageType)){const C=g.messageType.toLowerCase();T=T.filter(D=>{var b;return(b=D.messageType)==null?void 0:b.toLowerCase().includes(C)})}const _=T.slice(h,h+u);(p=s.source)==null||p.postMessage({type:"SW_DEBUG_POSTMESSAGE_LOGS",logs:_,total:T.length,offset:h,limit:u,stats:Is()})}else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_POSTMESSAGE_LOGS")Ds(),(S=s.source)==null||S.postMessage({type:"SW_DEBUG_POSTMESSAGE_LOGS_CLEARED"});else if(s.data&&s.data.type==="CRASH_SNAPSHOT"){const u=s.data.snapshot;u&&(sr(u),R.clients.matchAll().then(h=>{h.forEach(g=>{g.postMessage({type:"SW_DEBUG_NEW_CRASH_SNAPSHOT",snapshot:u})})}))}else s.data&&s.data.type==="SW_DEBUG_GET_CRASH_SNAPSHOTS"?(async()=>{var u,h;try{const g=await or();(u=s.source)==null||u.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS",snapshots:g,total:g.length})}catch(g){(h=s.source)==null||h.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS",snapshots:[],total:0,error:String(g)})}})():s.data&&s.data.type==="SW_DEBUG_CLEAR_CRASH_SNAPSHOTS"?(async()=>{var u;await rr(),(u=s.source)==null||u.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS_CLEARED"})})():s.data&&s.data.type==="SW_DEBUG_GET_LLM_API_LOGS"?(async()=>{var u,h;try{const{getAllLLMApiLogs:g}=await Promise.resolve().then(()=>I),T=await g();(u=s.source)==null||u.postMessage({type:"SW_DEBUG_LLM_API_LOGS",logs:T,total:T.length})}catch(g){(h=s.source)==null||h.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 h;const{clearAllLLMApiLogs:u}=await Promise.resolve().then(()=>I);await u(),(h=s.source)==null||h.postMessage({type:"SW_DEBUG_LLM_API_LOGS_CLEARED"})})()});const tr="MemorySnapshotDB",ee="snapshots",Zt=50;async function dt(){return new Promise((s,e)=>{const t=indexedDB.open(tr,1);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const n=o.target.result;if(!n.objectStoreNames.contains(ee)){const r=n.createObjectStore(ee,{keyPath:"id"});r.createIndex("timestamp","timestamp",{unique:!1}),r.createIndex("type","type",{unique:!1})}}})}async function sr(s){try{const e=await dt(),t=e.transaction(ee,"readwrite"),o=t.objectStore(ee);o.put(s);const n=o.count();n.onsuccess=()=>{const r=n.result;if(r>Zt){const i=o.index("timestamp").openCursor();let c=0;const l=r-Zt;i.onsuccess=d=>{const m=d.target.result;m&&c<l&&(o.delete(m.value.id),c++,m.continue())}}},await new Promise((r,a)=>{t.oncomplete=()=>{e.close(),r()},t.onerror=()=>{e.close(),a(t.error)}})}catch(e){console.warn("[SW] Failed to save crash snapshot:",e)}}async function or(){try{const s=await dt(),o=s.transaction(ee,"readonly").objectStore(ee).index("timestamp");return new Promise((n,r)=>{const a=o.getAll();a.onsuccess=()=>{s.close();const i=a.result.sort((c,l)=>l.timestamp-c.timestamp);n(i)},a.onerror=()=>{s.close(),r(a.error)}})}catch(s){return console.warn("[SW] Failed to get crash snapshots:",s),[]}}async function rr(){try{const s=await dt(),e=s.transaction(ee,"readwrite");e.objectStore(ee).clear(),await new Promise((o,n)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),n(e.error)}}),console.log("[SW] Crash snapshots cleared")}catch(s){console.warn("[SW] Failed to clear crash snapshots:",s)}}const nr=["ConsoleLogDB","ServiceWorkerDB","sw-task-queue","aitu-workspace","drawnix-unified-cache","drawnix-kv-storage","drawnix-prompts","drawnix-chat-db","MemorySnapshotDB"];function ar(s){try{const e=JSON.stringify(s);return new Blob([e]).size}catch{return 0}}async function ir(s){return new Promise(e=>{try{const t=indexedDB.open(s);t.onerror=()=>e({count:0,totalSize:0}),t.onsuccess=()=>{const o=t.result,n=Array.from(o.objectStoreNames);if(n.length===0){o.close(),e({count:0,totalSize:0});return}let r=0,a=0,i=0,c=0;const l=10;try{const d=o.transaction(n,"readonly");for(const m of n){const y=d.objectStore(m),w=y.count();w.onsuccess=()=>{const f=w.result;if(r+=f,f>0){const p=y.openCursor();let S=0;p.onsuccess=u=>{const h=u.target.result;if(h&&S<l)a+=ar(h.value),i++,S++,h.continue();else if(c++,c===n.length){o.close();const g=i>0?a/i:0,T=Math.round(g*r);e({count:r,totalSize:T})}},p.onerror=()=>{if(c++,c===n.length){o.close();const u=i>0?a/i:0,h=Math.round(u*r);e({count:r,totalSize:h})}}}else c++,c===n.length&&(o.close(),e({count:r,totalSize:0}))},w.onerror=()=>{if(c++,c===n.length){o.close();const f=i>0?a/i:0,p=Math.round(f*r);e({count:r,totalSize:p})}}}}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 cr(){const s={},e=[Ue,x,ge,qe];for(const t of e)try{const o=await caches.open(t),n=await o.keys();let r=0;const a=Math.min(n.length,100);let i=0;for(let c=0;c<a;c++){const l=await o.match(n[c]);if(l){const d=l.headers.get("sw-image-size")||l.headers.get("content-length");d&&(i+=parseInt(d))}}a>0&&n.length>a?r=Math.round(i/a*n.length):r=i,s[t]={count:n.length,totalSize:r,type:"cache"}}catch{s[t]={count:0,totalSize:0,type:"cache"}}for(const t of nr)try{const o=await ir(t);o.count>0&&(s[`[IDB] ${t}`]={...o,type:"indexeddb"})}catch{}return s}async function lr(s){try{await(await caches.open(x)).delete(s)}catch(e){throw console.error("Service Worker: Failed to delete cache entry:",s,e),e}}async function ur(s){try{const e=await caches.open(x);let t=0;for(const o of s)try{await e.delete(o),t++}catch(n){console.warn("Service Worker: Failed to delete cache in batch:",o,n)}}catch(e){throw console.error("Service Worker: Failed to batch delete caches:",e),e}}async function dr(){try{const s=await caches.open(x),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 es(s,e,t){try{(await R.clients.matchAll()).forEach(n=>{n.postMessage({type:"IMAGE_CACHED",url:s,size:e,mimeType:t,timestamp:Date.now()})})}catch(o){console.warn("Service Worker: Failed to notify image cached:",o)}}async function hr(){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(r=>{r.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:"){$({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(Io)){const o=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"cache-url",details:"Intercepting cache URL request"});s.respondWith(gr(s.request).then(n=>(P(o,{status:n.status,statusText:n.statusText,responseType:n.type,duration:Date.now()-t,cached:n.status===200}),n)).catch(n=>{throw P(o,{error:String(n),duration:Date.now()-t}),n}));return}if(e.pathname.startsWith(Oo)){const o=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"asset-library",details:"Intercepting asset library request"});s.respondWith(pr(s.request).then(n=>(P(o,{status:n.status,statusText:n.statusText,responseType:n.type,duration:Date.now()-t,cached:n.status===200}),n)).catch(n=>{throw P(o,{error:String(n),duration:Date.now()-t}),n}));return}if(e.hostname==="cdn.i666.fun"){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"passthrough",details:"Passthrough: cdn.i666.fun (fallback domain)",status:0,duration:0});return}if(e.hostname.endsWith(".volces.com")||e.hostname.endsWith(".volccdn.com")){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"passthrough",details:"Passthrough: Volcengine domain (no CORS)",status:0,duration:0});return}if(e.hostname.endsWith(".aliyuncs.com")){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"passthrough",details:"Passthrough: Aliyun OSS domain (no CORS)",status:0,duration:0});return}if(vo(e.hostname)){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"passthrough",details:`Passthrough: ${e.hostname} (CORS failed domain, auto-detected)`,status:0,duration:0});return}if(zo(e,s.request)){const o=Date.now(),n=s.request.headers.get("range"),r=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"video",headers:n?{range:n}:void 0,details:n?`Video Range request: ${n}`:"Video request"});s.respondWith(mr(s.request).then(a=>(P(r,{status:a.status,statusText:a.statusText,responseType:a.type,duration:Date.now()-o,responseHeaders:{"content-type":a.headers.get("content-type")||"","content-length":a.headers.get("content-length")||"","content-range":a.headers.get("content-range")||""}}),a)).catch(a=>{throw P(r,{error:String(a),duration:Date.now()-o}),a}));return}if(jo(e,s.request)){const o=Date.now(),n=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"font",details:"Font request"});s.respondWith(fr(s.request).then(r=>(P(n,{status:r.status,statusText:r.statusText,responseType:r.type,duration:Date.now()-o,cached:r.headers.has("sw-cache-date")}),r)).catch(r=>{throw P(n,{error:String(r),duration:Date.now()-o}),r}));return}if(e.origin!==location.origin&&Ko(e,s.request)){const o=Date.now(),n=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"image",details:"External image request"});s.respondWith(Tr(s.request).then(r=>(P(n,{status:r.status,statusText:r.statusText,responseType:r.type,duration:Date.now()-o,cached:r.headers.has("sw-cache-date"),size:parseInt(r.headers.get("content-length")||"0")}),r)).catch(r=>{throw P(n,{error:String(r),duration:Date.now()-o}),r}));return}if(s.request.method==="GET"){const o=s.request.mode==="navigate",n=s.request.destination!=="";if(o||n){const r=Date.now(),a=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"static",details:o?"Navigation request":`Static resource (${s.request.destination})`});s.respondWith(wr(s.request).then(i=>(P(a,{status:i.status,statusText:i.statusText,responseType:i.type,duration:Date.now()-r}),i)).catch(i=>{throw P(a,{error:String(i),duration:Date.now()-r}),i}));return}}if(F){const o=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"xhr",details:`XHR/API request (${s.request.method})`});s.respondWith((async()=>{try{const n=s.request.clone();let r,a={};if(s.request.headers.forEach((m,y)=>{a[y]=m}),["POST","PUT","PATCH"].includes(s.request.method))try{const m=s.request.headers.get("content-type")||"";m.includes("application/json")?(r=await n.text(),r.length>2e3&&(r=r.substring(0,2e3)+"... (truncated)")):m.includes("application/x-www-form-urlencoded")?(r=await n.text(),r.length>2e3&&(r=r.substring(0,2e3)+"... (truncated)")):r=`[${m||"binary data"}]`}catch{r="[unable to read body]"}P(o,{headers:a,details:r?`XHR/API request (${s.request.method})
4
+ `),t.trim()}function co(s){let e=s.trim();const t=e.indexOf("{");t>0&&(e=e.substring(t));const o=e.lastIndexOf("}");return o<e.length-1&&o>0&&(e=e.substring(0,o+1)),e=e.replace(/:\s*"([^"]*)\n([^"]*)"/g,(n,r,a)=>`: "${r}\\n${a}"`),e=e.replace(/'([^']*?)'/g,(n,r)=>!r.includes(":")||r.length>50?`"${r}"`:n),e=e.replace(/([{,]\s*)(\w+)(\s*:)/g,'$1"$2"$3'),e=e.replace(/,(\s*[}\]])/g,"$1"),e=e.replace(/,\s*,/g,","),e=e.replace(/\/\/[^\n]*/g,""),e=e.replace(/\/\*[\s\S]*?\*\//g,""),e=e.replace(/:\s*undefined\b/g,": null"),e}function lo(s){return ao(s).map(t=>({...t,status:"pending"}))}class uo{constructor(e){this.workflows=new Map,this.abortControllers=new Map,this.workflowClients=new Map,this.pendingToolRequests=new Map,this.storageRestored=!1,this.config=e,this.restoreFromStorage()}async restoreFromStorage(){try{const e=await E.getAllChatWorkflows();for(const t of e){if(t.status==="completed"||t.status==="cancelled"||t.status==="failed"){this.workflows.set(t.id,t);continue}await this.handleInterruptedWorkflow(t)}this.storageRestored=!0}catch(e){console.error("[ChatWorkflowHandler] Failed to restore from storage:",e),this.storageRestored=!0}}async handleInterruptedWorkflow(e){let t;switch(e.status){case"streaming":t="AI 响应流传输时中断,请重试";break;case"parsing":t="工具调用解析时中断,请重试";break;case"executing_tools":t="工具执行时中断,请重试";break;case"pending":t="工作流尚未开始执行,请重试";break;default:t="工作流执行时中断,请重试"}e.status="failed",e.error=t,e.updatedAt=Date.now();for(const o of e.toolCalls)(o.status==="running"||o.status==="pending")&&(o.status="failed",o.result={success:!1,error:"Service Worker 重启导致执行中断"});this.workflows.set(e.id,e),await E.saveChatWorkflow(e)}updateConfig(e){this.config={...this.config,...e}}async startWorkflow(e,t,o){console.log("[SW-ChatWorkflow] ▶ startWorkflow:",{chatId:e,clientId:o,existingWorkflows:this.workflows.size,timestamp:new Date().toISOString()});const n=this.workflows.get(e);if(n){if(n.status==="streaming"||n.status==="pending"||n.status==="executing_tools"){console.log("[SW-ChatWorkflow] Re-claiming active workflow:",{chatId:e,status:n.status}),this.broadcastStatus(n);return}console.warn("[SW-ChatWorkflow] Workflow already exists, skipping:",{chatId:e,status:n.status}),this.broadcastStatus(n);return}this.workflowClients.set(e,o);const r={id:e,status:"pending",params:t,content:"",toolCalls:[],createdAt:Date.now(),updatedAt:Date.now()};this.workflows.set(e,r),await E.saveChatWorkflow(r);const a=new AbortController;this.abortControllers.set(e,a),this.executeWorkflow(r,a.signal)}async cancelWorkflow(e){const t=this.abortControllers.get(e);t&&(t.abort(),this.abortControllers.delete(e));const o=this.workflows.get(e);o&&(o.status="cancelled",o.updatedAt=Date.now(),await E.saveChatWorkflow(o),this.broadcastStatus(o))}broadcastRecoveredWorkflows(){for(const e of this.workflows.values())this.config.broadcast({type:"CHAT_WORKFLOW_RECOVERED",chatId:e.id,workflow:e})}getWorkflow(e){return this.workflows.get(e)}getAllWorkflows(){return Array.from(this.workflows.values()).filter(e=>e.status!=="completed"&&e.status!=="failed"&&e.status!=="cancelled")}handleMainThreadToolResponse(e){const t=this.pendingToolRequests.get(e.requestId);t&&(this.pendingToolRequests.delete(e.requestId),t.resolve(e))}async executeWorkflow(e,t){try{e.status="streaming",await E.saveChatWorkflow(e),this.broadcastStatus(e);const o=await this.streamChat(e,t);if(e.content=o,t.aborted)throw new Error("Workflow cancelled");e.status="parsing",await E.saveChatWorkflow(e),this.broadcastStatus(e);const n=lo(o),r=io(o);e.toolCalls=n,e.aiAnalysis=r,n.length>0&&this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_CALLS",chatId:e.id,aiAnalysis:r,toolCalls:n}),n.length>0&&(e.status="executing_tools",await E.saveChatWorkflow(e),this.broadcastStatus(e),await this.executeTools(e,t)),e.status="completed",e.completedAt=Date.now(),e.updatedAt=Date.now(),await E.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_COMPLETE",chatId:e.id,content:e.content,aiAnalysis:e.aiAnalysis,toolCalls:e.toolCalls})}catch(o){o.message==="Workflow cancelled"?e.status="cancelled":(e.status="failed",e.error=o.message,this.config.broadcast({type:"CHAT_WORKFLOW_FAILED",chatId:e.id,error:o.message})),e.updatedAt=Date.now(),await E.saveChatWorkflow(e)}finally{this.abortControllers.delete(e.id)}}async streamChat(e,t){var f,p,S,u,h,g;const{params:o}=e,{geminiConfig:n}=this.config,r=this.convertToGeminiMessages(o),a=o.temporaryModel||n.modelName||"gemini-2.5-flash";console.log("[SW-ChatWorkflow] streamChat called:",{workflowId:e.id,model:a,messagesCount:r.length,timestamp:new Date().toISOString()});const i={model:a,messages:r,stream:!0},{debugFetch:c}=await Promise.resolve().then(()=>v),l=await c(`${n.baseUrl}/chat/completions`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n.apiKey}`},body:JSON.stringify(i),signal:t},{label:`💬 工作流对话 (${a})`,logRequestBody:!0,isStreaming:!0});if(!l.ok){const T=await l.text();throw new Error(`Chat request failed: ${l.status} - ${T}`)}if(!l.body)throw new Error("No response body");const d=l.body.getReader(),m=new TextDecoder;let y="",w="";try{for(;;){const{done:T,value:_}=await d.read();if(T)break;w+=m.decode(_,{stream:!0});const C=w.split(`
5
+ `);w=C.pop()||"";for(const D of C)if(D.startsWith("data: ")){const b=D.slice(6).trim();if(b==="[DONE]")continue;try{const z=(S=(p=(f=JSON.parse(b).choices)==null?void 0:f[0])==null?void 0:p.delta)==null?void 0:S.content;z&&(y+=z,this.config.broadcast({type:"CHAT_WORKFLOW_STREAM",chatId:e.id,content:y}))}catch{}}}if(w.startsWith("data: ")){const T=w.slice(6).trim();if(T&&T!=="[DONE]")try{const C=(g=(h=(u=JSON.parse(T).choices)==null?void 0:u[0])==null?void 0:h.delta)==null?void 0:g.content;C&&(y+=C,this.config.broadcast({type:"CHAT_WORKFLOW_STREAM",chatId:e.id,content:y}))}catch{}}}finally{d.releaseLock()}if(l.__debugLogId&&y){const{updateLogResponseBody:T}=await Promise.resolve().then(()=>v);T(l.__debugLogId,y)}return y}async executeTools(e,t){const o=this.workflowClients.get(e.id);for(const n of e.toolCalls){if(t.aborted)throw new Error("Workflow cancelled");n.status="running",this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_START",chatId:e.id,toolCallId:n.id,toolName:n.name});try{let r;if(Ze(n.name)||!Mt(n.name)){if(!o)throw new Error("No client ID found for workflow");const a=await this.config.requestMainThreadTool(o,e.id,n.id,n.name,n.arguments);r={success:a.success,data:a.result,error:a.error}}else{const a={geminiConfig:this.config.geminiConfig,videoConfig:this.config.videoConfig,signal:t},i=await Ye(n.name,n.arguments,a);r={success:i.success,data:i.data,error:i.error,taskId:i.taskId}}n.status=r.success?"completed":"failed",n.result=r,await E.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_COMPLETE",chatId:e.id,toolCallId:n.id,success:r.success,result:r.data,error:r.error,taskId:r.taskId})}catch(r){n.status="failed",n.result={success:!1,error:r.message},await E.saveChatWorkflow(e),this.config.broadcast({type:"CHAT_WORKFLOW_TOOL_COMPLETE",chatId:e.id,toolCallId:n.id,success:!1,error:r.message})}}}convertToGeminiMessages(e){var o;const t=[];e.systemPrompt&&t.push({role:"system",content:[{type:"text",text:e.systemPrompt}]});for(const n of e.messages){const r=[];if(n.content&&r.push({type:"text",text:n.content}),n.attachments)for(const a of n.attachments)a.type==="image"&&r.push({type:"image_url",image_url:{url:`data:${a.mimeType};base64,${a.data}`}});t.push({role:n.role,content:r})}if(e.newContent||(o=e.attachments)!=null&&o.length){const n=[];if(e.newContent&&n.push({type:"text",text:e.newContent}),e.attachments)for(const r of e.attachments)r.type==="image"&&n.push({type:"image_url",image_url:{url:`data:${r.mimeType};base64,${r.data}`}});t.push({role:"user",content:n})}return t}broadcastStatus(e){this.config.broadcast({type:"CHAT_WORKFLOW_STATUS",chatId:e.id,status:e.status,updatedAt:e.updatedAt})}}let P=null,j=null,le=null,ue=null;function et(s,e,t){le=e,ue=t,P=new ro({geminiConfig:e,videoConfig:t,broadcast:n=>he(n)});const o=Je();o&&o.setTaskStatusChangeCallback((n,r,a,i)=>{P==null||P.updateWorkflowStepForTask(n,r,a,i)}),j=new uo({geminiConfig:e,videoConfig:t,broadcast:n=>he(n),sendToClient:(n,r)=>st(n,r),requestMainThreadTool:async(n,r,a,i,c)=>{const l=`chat_tool_${Date.now()}_${Math.random().toString(36).slice(2,11)}`;return new Promise((d,m)=>{const y=setTimeout(()=>{de.delete(l),E.deletePendingToolRequest(l),m(new Error(`Tool request timed out: ${i}`))},3e5);de.set(l,{resolve:w=>{clearTimeout(y),E.deletePendingToolRequest(l),d(w)},reject:w=>{clearTimeout(y),E.deletePendingToolRequest(l),m(w)},requestInfo:{requestId:l,chatId:r,toolCallId:a,toolName:i,args:c,clientId:n},timeout:y}),E.savePendingToolRequest({requestId:l,workflowId:r,stepId:a,toolName:i,args:c,createdAt:Date.now(),clientId:n}),st(n,{type:"MAIN_THREAD_TOOL_REQUEST",requestId:l,workflowId:r,stepId:a,toolName:i,args:c})})}})}const de=new Map;function ho(s,e){if(!P){console.warn("[WorkflowHandler] Not initialized");return}s&&(le={...le||{},...s}),e&&(ue={...ue||{},...e}),!(!le||!ue)&&(P.updateConfig({geminiConfig:le,videoConfig:ue}),j&&j.updateConfig({geminiConfig:le,videoConfig:ue}))}function fo(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 tt(s,e){if(s.type.startsWith("CHAT_WORKFLOW_")){go(s,e);return}if(!P){console.error("[WorkflowHandler] ✗ Not initialized, ignoring message:",s.type);return}const t=s;switch(t.type){case"WORKFLOW_SUBMIT":console.log("[SW-WorkflowHandler] ▶ WORKFLOW_SUBMIT received:",{workflowId:t.workflow.id,clientId:e,timestamp:new Date().toISOString()}),P.submitWorkflow(t.workflow);break;case"WORKFLOW_CANCEL":P.cancelWorkflow(t.workflowId);break;case"WORKFLOW_GET_STATUS":{const o=P.getWorkflow(t.workflowId);he({type:"WORKFLOW_STATUS_RESPONSE",workflowId:t.workflowId,workflow:o||null});break}case"WORKFLOW_GET_ALL":{const o=P.getAllWorkflows();he({type:"WORKFLOW_ALL_RESPONSE",workflows:o});break}}}function go(s,e){var t;if(!j){console.error("[WorkflowHandler] ✗ Chat workflow handler not initialized");return}switch(s.type){case"CHAT_WORKFLOW_START":console.log("[SW-Workflow] ▶ CHAT_WORKFLOW_START received:",{chatId:s.chatId,clientId:e,stepsCount:(t=s.params.steps)==null?void 0:t.length,timestamp:new Date().toISOString()}),j.startWorkflow(s.chatId,s.params,e);break;case"CHAT_WORKFLOW_CANCEL":j.cancelWorkflow(s.chatId);break;case"CHAT_WORKFLOW_GET_STATUS":{const o=j.getWorkflow(s.chatId);he({type:"CHAT_WORKFLOW_STATUS_RESPONSE",chatId:s.chatId,workflow:o||null});break}case"CHAT_WORKFLOW_GET_ALL":{const o=j.getAllWorkflows();he({type:"CHAT_WORKFLOW_ALL_RESPONSE",workflows:o});break}}}async function po(s){const e=de.get(s.requestId);if(e){de.delete(s.requestId),e.resolve(s);return}if(await E.deletePendingToolRequest(s.requestId),!P){console.error("[WorkflowHandler] ✗ Not initialized, ignoring tool response");return}P.handleMainThreadToolResponse(s)}function mo(){if(P&&(P.broadcastRecoveredWorkflows(),P.resendPendingToolRequests()),j&&j.broadcastRecoveredWorkflows(),de.size!==0)for(const[,s]of de){const{requestInfo:e}=s;st(e.clientId,{type:"MAIN_THREAD_TOOL_REQUEST",requestId:e.requestId,workflowId:e.chatId,stepId:e.toolCallId,toolName:e.toolName,args:e.args})}}function he(s){Rt(s)}async function st(s,e){await Pe(s,e)||Rt(e)}const be=[],wo=100;let ot=!1,J=null;function So(s){ot=s}function rt(){return ot}function Bt(s){J=s}function Ut(){return[...be]}function yo(s,e){const t=be.find(o=>o.id===s);t&&(t.responseBody=e.length>5e3?e.substring(0,5e3)+"...(truncated)":e,J&&J({...t}))}async function To(s){return new Promise((e,t)=>{const o=new FileReader;o.onloadend=()=>e(o.result),o.onerror=t,o.readAsDataURL(s)})}async function Eo(s){const e=[];for(const[t,o]of s.entries())if(o instanceof Blob){const n={name:t,value:`[${o.type||"binary"}] ${o.size} bytes`,isFile:!0,mimeType:o.type};if(o.type.startsWith("image/")&&o.size<5*1024*1024)try{n.dataUrl=await To(o)}catch{}o instanceof File&&(n.fileName=o.name),e.push(n)}else e.push({name:t,value:String(o).length>500?String(o).substring(0,500)+"...":String(o)});return e}async function Co(s,e,t){if(!ot)return fetch(s,e);const o=typeof s=="string"?s:s instanceof URL?s.href:s.url,n=(e==null?void 0:e.method)||"GET",r=Date.now(),a=Math.random().toString(36).substring(2,10);let i,c,l;if(e!=null&&e.body){if(e.body instanceof FormData)try{c=await Eo(e.body)}catch{i="[FormData - unable to parse]"}else if(t!=null&&t.logRequestBody)try{const m=typeof e.body=="string"?e.body:JSON.stringify(e.body),y=/data:image\/([^;]+);base64,([A-Za-z0-9+/=]+)/g;let w,f=0;for(l=[];(w=y.exec(m))!==null;){const u=`image/${w[1]}`,h=w[2];h.length>1e3&&(l.push({key:`image[${f}]`,dataUrl:`data:${u};base64,${h}`,mimeType:u,size:Math.round(h.length*.75/1024)}),f++)}l.length===0&&(l=void 0);let p=m.replace(/data:image\/([^;]+);base64,[A-Za-z0-9+/=]+/g,(u,h)=>`[📷 image/${h}]`);i=!o.includes("/chat/completions")&&p.length>3e3?p.substring(0,3e3)+"...(truncated)":p}catch{i="[unable to serialize body]"}}const d={id:a,timestamp:r,url:o,method:n,requestType:"sw-internal",details:(t==null?void 0:t.label)||`SW Internal: ${n} ${new URL(o).pathname}`,requestBody:i,formData:c,base64Images:l,isStreaming:t==null?void 0:t.isStreaming};be.unshift(d),be.length>wo&&be.pop(),J&&J({...d});try{const m=await fetch(s,e);if(d.status=m.status,d.statusText=m.statusText,d.duration=Date.now()-r,t!=null&&t.isStreaming)d.responseBody="[流式响应 - 数据通过 SSE/Stream 实时传输,无法捕获完整响应体]";else if(t!=null&&t.logResponseBody)try{const y=m.headers.get("content-type")||"";if(y.includes("application/json")||y.includes("text/")){const f=await m.clone().text();d.responseBody=f.length>2e3?f.substring(0,2e3)+"...(truncated)":f}}catch{}return J&&J({...d}),m.__debugLogId=a,m}catch(m){const y=m.message||String(m);let w="NETWORK_ERROR";throw y.includes("ERR_CONNECTION_CLOSED")?w="ERR_CONNECTION_CLOSED":y.includes("ERR_CONNECTION_REFUSED")?w="ERR_CONNECTION_REFUSED":y.includes("ERR_CONNECTION_RESET")?w="ERR_CONNECTION_RESET":y.includes("ERR_CONNECTION_TIMED_OUT")||y.includes("timeout")?w="ERR_TIMEOUT":y.includes("ERR_NAME_NOT_RESOLVED")?w="ERR_DNS_FAILED":y.includes("ERR_INTERNET_DISCONNECTED")?w="ERR_OFFLINE":y.includes("ERR_SSL")||y.includes("certificate")?w="ERR_SSL":y.includes("Failed to fetch")?w="FETCH_FAILED":(y.includes("AbortError")||y.includes("aborted"))&&(w="ABORTED"),d.status=0,d.statusText=w,d.error=y,d.duration=Date.now()-r,J&&J({...d}),m}}const v=Object.freeze(Object.defineProperty({__proto__:null,debugFetch:Co,getInternalFetchLogs:Ut,isDebugFetchEnabled:rt,setDebugFetchBroadcast:Bt,setDebugFetchEnabled:So,updateLogResponseBody:yo},Symbol.toStringTag,{value:"Module"})),_o=typeof location<"u"&&(location.hostname==="localhost"||location.hostname==="127.0.0.1"),nt={degradeTimeout:60*1e3,failThreshold:3,fetchTimeout:1e4},at=[{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}],fe=new Map;function qt(){at.forEach(s=>{fe.has(s.name)||fe.set(s.name,{name:s.name,isHealthy:!0,lastCheckTime:0,failCount:0,lastSuccessTime:Date.now()})})}qt();function Ft(s){const e=fe.get(s);e&&(e.isHealthy=!0,e.failCount=0,e.lastSuccessTime=Date.now(),e.lastCheckTime=Date.now())}function Ne(s){const e=fe.get(s);e&&(e.failCount++,e.lastCheckTime=Date.now(),e.failCount>=nt.failThreshold&&(e.isHealthy=!1,console.warn(`[CDN Fallback] ${s} marked as unhealthy after ${e.failCount} failures`)))}function bo(s){const e=fe.get(s);return e?e.isHealthy?!0:Date.now()-e.lastCheckTime>nt.degradeTimeout?(console.log(`[CDN Fallback] Trying to recover ${s}...`),!0):!1:!1}function Ao(){return at.filter(s=>s.enabled&&bo(s.name)).sort((s,e)=>s.priority-e.priority)}function Gt(s){const e=/^\/?(aitu-app@[\d.]+\/)/;return s.replace(e,"/")}function $t(s,e,t){const o=Gt(t);return s.urlTemplate.replace("{version}",e).replace("{path}",o.startsWith("/")?o.slice(1):o)}async function it(s,e=nt.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 Ro(s,e,t){if(_o)return console.log("[CDN Fallback] 开发模式,跳过 CDN 回退"),null;const o=Ao();for(const n of o){const r=$t(n,e,s);try{console.log(`[CDN Fallback] Trying ${n.name}: ${r}`);const a=await it(r);if(a.ok)return Ft(n.name),console.log(`[CDN Fallback] Success from ${n.name}`),{response:a,source:n.name};console.warn(`[CDN Fallback] ${n.name} returned ${a.status}`),Ne(n.name)}catch(a){console.warn(`[CDN Fallback] ${n.name} failed:`,a),Ne(n.name)}}try{const n=Gt(s),r=`${t}/${n.startsWith("/")?n.slice(1):n}`;console.log(`[CDN Fallback] Trying local server: ${r}`);const a=await it(r);if(a.ok)return console.log("[CDN Fallback] Success from local server"),{response:a,source:"local"}}catch(n){console.warn("[CDN Fallback] Local server failed:",n)}return console.error(`[CDN Fallback] All sources failed for: ${s}`),null}async function Do(s){const e=new Map;for(const t of at){if(!t.enabled)continue;const o=$t(t,s,t.healthCheckPath);try{const r=(await it(o,5e3)).ok;e.set(t.name,r),r?Ft(t.name):Ne(t.name)}catch{e.set(t.name,!1),Ne(t.name)}}return e}function Wo(){return Array.from(fe.entries()).map(([s,e])=>({name:s,status:e}))}function Lo(){qt(),console.log("[CDN Fallback] All CDN status reset")}const R=self;eo(R),Ps();const re={log:console.log.bind(console),info:console.info.bind(console),warn:console.warn.bind(console),error:console.error.bind(console)};function Io(){console.log=(...s)=>{re.log(...s),rt()&&Be("log",s)},console.info=(...s)=>{re.info(...s),rt()&&Be("info",s)},console.warn=(...s)=>{re.warn(...s),Be("warn",s)},console.error=(...s)=>{re.error(...s),Be("error",s)}}function Be(s,e){const t=e.map(n=>{if(typeof n=="object")try{return JSON.stringify(n)}catch{return String(n)}return String(n)}).join(" "),o=t.startsWith("[SW]")||t.startsWith("[SW-")?t:`[SW] ${t}`;typeof ct=="function"&&ct({logLevel:s,logMessage:o,logSource:"service-worker"})}let ct=null;Io(),Bt(s=>{R.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_DEBUG_LOG",entry:{...s,type:"fetch"}})})})}),Promise.resolve().then(()=>I).then(({setLLMApiLogBroadcast:s})=>{s(e=>{R.clients.matchAll().then(t=>{t.forEach(o=>{o.postMessage({type:"SW_DEBUG_LLM_API_LOG",log:e})})})})});const Z="0.5.22",Ue=`drawnix-v${Z}`,M="drawnix-images",ge=`drawnix-static-v${Z}`,qe="drawnix-fonts",Oo="/__aitu_cache__/",ko="/asset-library/",lt=location.hostname==="localhost"||location.hostname==="127.0.0.1",Po=[{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"}],Mo=/\.(jpg|jpeg|png|gif|webp|svg|bmp|ico)$/i,xo=/\.(mp4|webm|ogg|mov|avi|mkv|flv|wmv|m4v)$/i,G=new Map,ne=new Map,Ht=30*1e3,Ae=new Map,q=new Map,vo=300*1e3,Kt=10,pe=new Set,me=new Set,No=3600*1e3,ut=new Map;function zt(s){me.add(s),ut.set(s,Date.now()),console.warn(`Service Worker: 标记 ${s} 为 CORS 问题域名,后续请求将跳过 SW`)}function Bo(s){if(!me.has(s))return!1;const e=ut.get(s);return e&&Date.now()-e>No?(me.delete(s),ut.delete(s),!1):!0}const Re=[],Uo=7,V=[],qo=500;let F=!1,we=0;const Fo=15e3;let Q=null;function jt(){if(!F)return;const s=Date.now();we>0&&s-we>Fo?(re.log("Service Worker: Debug heartbeat timeout, auto-disabling debug mode"),F=!1,we=0,je(!1),Promise.resolve().then(()=>v).then(({setDebugFetchEnabled:e})=>{e(!1)}),R.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_DEBUG_DISABLED"})})}),Q&&(clearTimeout(Q),Q=null)):F&&(Q=setTimeout(jt,5e3))}function $(s){if(!F)return"";const e=Math.random().toString(36).substring(2,10),t={...s,id:e,timestamp:Date.now()};return V.unshift(t),V.length>qo&&V.pop(),Vt(t),e}function x(s,e){if(!F||!s)return;const t=V.find(o=>o.id===s);t&&(Object.assign(t,e),Vt(t))}async function Vt(s){try{(await R.clients.matchAll()).forEach(t=>{t.postMessage({type:"SW_DEBUG_LOG",entry:s})})}catch{}}function Fe(){return new Promise((s,e)=>{const t=indexedDB.open("ConsoleLogDB",1);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const n=o.target.result;if(!n.objectStoreNames.contains("logs")){const r=n.createObjectStore("logs",{keyPath:"id"});r.createIndex("timestamp","timestamp",{unique:!1}),r.createIndex("logLevel","logLevel",{unique:!1})}}})}async function Go(s){try{const e=await Fe(),t=e.transaction(["logs"],"readwrite");return t.objectStore("logs").add(s),new Promise((n,r)=>{t.oncomplete=()=>{e.close(),n()},t.onerror=()=>{e.close(),r(t.error)}})}catch(e){console.warn("Service Worker: 无法保存控制台日志:",e)}}async function Qt(){try{const s=await Fe(),o=s.transaction(["logs"],"readonly").objectStore("logs").index("timestamp");return new Promise((n,r)=>{const a=o.openCursor(null,"prev"),i=[];a.onsuccess=()=>{const c=a.result;c?(i.push(c.value),c.continue()):(s.close(),n(i))},a.onerror=()=>{s.close(),r(a.error)}})}catch(s){return console.warn("Service Worker: 无法加载控制台日志:",s),[]}}async function $o(){try{const s=await Fe(),o=s.transaction(["logs"],"readwrite").objectStore("logs").index("timestamp"),n=Date.now()-Uo*24*60*60*1e3,r=IDBKeyRange.upperBound(n);return new Promise((a,i)=>{const c=o.openCursor(r);let l=0;c.onsuccess=()=>{const d=c.result;d?(d.delete(),l++,d.continue()):(s.close(),l>0&&console.log(`Service Worker: 清理了 ${l} 条过期控制台日志`),a(l))},c.onerror=()=>{s.close(),i(c.error)}})}catch(s){return console.warn("Service Worker: 无法清理过期日志:",s),0}}async function Xt(){try{const s=await Fe(),e=s.transaction(["logs"],"readwrite");return e.objectStore("logs").clear(),new Promise((o,n)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),n(e.error)}})}catch(s){console.warn("Service Worker: 无法清空控制台日志:",s)}}function Jt(s){if(!F)return;const t={id:Math.random().toString(36).substring(2,10),timestamp:Date.now(),type:"console",...s};Re.unshift(t),Go(t),Ho(t)}ct=Jt;async function Ho(s){try{(await R.clients.matchAll()).forEach(t=>{t.postMessage({type:"SW_CONSOLE_LOG",entry:s})})}catch{}}function Ko(){let s=0;return q.forEach(e=>{e.blob&&(s+=e.blob.size)}),s}function Ge(){return{version:Z,cacheNames:[Ue,M,ge,qe],pendingImageRequests:G.size,pendingVideoRequests:Ae.size,videoBlobCacheSize:q.size,videoBlobCacheTotalBytes:Ko(),completedImageRequestsSize:ne.size,failedDomainsCount:pe.size,failedDomains:Array.from(pe),corsFailedDomainsCount:me.size,corsFailedDomains:Array.from(me),debugLogsCount:V.length,consoleLogsCount:Re.length,debugModeEnabled:F,workflowHandlerInitialized:ae,memoryStats:{pendingRequestsMapSize:G.size,completedRequestsMapSize:ne.size,videoBlobCacheMapSize:q.size,failedDomainsSetSize:pe.size,corsFailedDomainsSetSize:me.size,debugLogsArraySize:V.length,consoleLogsArraySize:Re.length}}}function Yt(s){for(const e of Po)if(s.hostname===e.hostname&&s.pathname.includes(e.pathPattern))return e;return null}function zo(s,e){return Mo.test(s.pathname)||e.destination==="image"||Yt(s)!==null}function jo(s,e){return xo.test(s.pathname)||e.destination==="video"||s.pathname.includes("/video/")||s.hash.startsWith("#merged-video-")||s.hash.includes("video")}function Vo(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 Qo(){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=>pe.add(c.domain)),e()},a.onerror=()=>t(a.error)}else e()},s.onupgradeneeded=o=>{const n=o.target.result;n.objectStoreNames.contains("failedDomains")||n.createObjectStore("failedDomains",{keyPath:"domain"})}})}catch(s){console.warn("Service Worker: 无法加载失败域名列表:",s)}}async function Xo(s){try{const e=indexedDB.open("ServiceWorkerDB",1);return new Promise((t,o)=>{e.onerror=()=>o(e.error),e.onsuccess=()=>{const r=e.result.transaction(["failedDomains"],"readwrite");r.objectStore("failedDomains").put({domain:s,timestamp:Date.now()}),r.oncomplete=()=>{t()},r.onerror=()=>o(r.error)},e.onupgradeneeded=n=>{const r=n.target.result;r.objectStoreNames.contains("failedDomains")||r.createObjectStore("failedDomains",{keyPath:"domain"})}})}catch(e){console.warn("Service Worker: 无法保存失败域名:",e)}}function Jo(s){s&&R.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_NEW_VERSION_READY",version:Z})})})}async function Yo(s){try{const e=await s.keys();if(e.length<=10)return;const t=[];for(const a of e)try{const i=await s.match(a);if(i){const c=i.headers.get("sw-cache-date"),l=i.headers.get("sw-image-size");t.push({request:a,cacheDate:c?parseInt(c):0,imageSize:l?parseInt(l):0})}}catch(i){console.warn("Service Worker: Error reading cache entry:",i)}t.sort((a,i)=>a.cacheDate-i.cacheDate);const o=Math.max(1,Math.floor(t.length*.25));let n=0,r=0;for(let a=0;a<o&&a<t.length;a++)try{await s.delete(t[a].request),n++,r+=t[a].imageSize}catch(i){console.warn("Service Worker: Error deleting cache entry:",i)}}catch(e){console.warn("Service Worker: Cache cleanup failed:",e)}}const Zo=["/","/index.html","/manifest.json","/favicon.ico","/icons/favicon-new.svg"];R.addEventListener("install",s=>{const e=[];e.push(Qo()),lt||e.push(caches.open(ge).then(async t=>{const n=(await Promise.allSettled(Zo.map(async r=>{try{const a=await fetch(r,{cache:"reload"});return a.ok?(await t.put(r,a),{url:r,success:!0}):{url:r,success:!1,status:a.status}}catch(a){return{url:r,success:!1,error:String(a)}}}))).filter(r=>r.status==="rejected"||r.status==="fulfilled"&&!r.value.success);n.length>0&&console.warn("Service Worker: Some static files failed to cache:",n.length)}).catch(t=>{console.warn("Service Worker: Cache pre-loading failed:",t)})),s.waitUntil(Promise.all(e).then(async()=>{const t=await caches.keys(),o=t.some(a=>a.startsWith("drawnix-static-v")&&a!==ge),n=t.some(a=>a.startsWith("drawnix-v")&&a!==Ue&&a!==M&&!a.startsWith("drawnix-static-v"));Jo(o||n)}))}),R.addEventListener("activate",s=>{s.waitUntil(caches.keys().then(async e=>{const t=e.filter(r=>r.startsWith("drawnix-images-v")&&r!==M);if(t.length>0){const r=await caches.open(M);for(const a of t)try{const i=await caches.open(a),c=await i.keys();for(const l of c){const d=await i.match(l);d&&await r.put(l,d)}await caches.delete(a)}catch(i){console.warn(`Failed to migrate cache ${a}:`,i)}}const o=e.filter(r=>r.startsWith("drawnix-static-v")&&r!==ge),n=e.filter(r=>r.startsWith("drawnix-v")&&r!==Ue&&r!==M&&!r.startsWith("drawnix-static-v"));return(o.length>0||n.length>0)&&setTimeout(async()=>{for(const r of[...o,...n])try{await caches.delete(r)}catch(a){console.warn("Failed to delete old cache:",r,a)}},3e4),$o().catch(r=>{console.warn("Failed to cleanup expired console logs:",r)}),R.clients.claim()}))});const er=["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 tr(s){if(!s||typeof s!="object")return!1;const e=s;return e.type?er.includes(e.type):!1}let ae=!1,Se=null,ye=null;const $e=[];function Zt(s){F&&R.clients.matchAll().then(e=>{e.forEach(t=>{t.postMessage({type:"SW_POSTMESSAGE_LOG",entry:s})})})}ks(Zt),R.addEventListener("message",s=>{var n,r,a,i,c,l,d,m,y,w,f,p,S;const e=((n=s.data)==null?void 0:n.type)||"unknown",t=((r=s.source)==null?void 0:r.id)||"";let o="";if(Ke()&&(o=Ds(e,s.data,t),o&&F)){const h=Ce().find(g=>g.id===o);h&&Zt(h)}if(s.data&&tr(s.data)){const u=((a=s.source)==null?void 0:a.id)||"";if(to(s.data,u),s.data.type==="TASK_QUEUE_INIT"){const{geminiConfig:h,videoConfig:g}=s.data;if(Se=h,ye=g,!ae&&(et(R,h,g),ae=!0,$e.length>0)){for(const T of $e)tt(T.message,T.clientId);$e.length=0}mo()}if(s.data.type==="TASK_QUEUE_UPDATE_CONFIG"){const{geminiConfig:h,videoConfig:g}=s.data;h&&(Se={...Se,...h}),g&&(ye={...ye,...g}),ho(h,g)}return}if(s.data&&fo(s.data)){const u=((i=s.source)==null?void 0:i.id)||"";if(!ae&&Se&&ye&&(et(R,Se,ye),ae=!0),!ae){(async()=>{try{const{geminiConfig:h,videoConfig:g}=await E.loadConfig();if(h&&g)Se=h,ye=g,et(R,h,g),ae=!0,tt(s.data,u);else{console.warn("[SW] Cannot initialize workflow handler: no config in storage, requesting config from main thread");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});$e.push({message:s.data,clientId:u})}}catch(h){console.error("[SW] Failed to load config from storage:",h)}})();return}tt(s.data,u);return}if(s.data&&s.data.type==="MAIN_THREAD_TOOL_RESPONSE"){po(s.data);return}if(s.data&&s.data.type==="SKIP_WAITING")R.skipWaiting(),R.clients.matchAll().then(u=>{u.forEach(h=>{h.postMessage({type:"SW_UPDATED"})})});else if(s.data&&s.data.type==="GET_UPGRADE_STATUS")(c=s.source)==null||c.postMessage({type:"UPGRADE_STATUS",version:Z});else if(s.data&&s.data.type==="FORCE_UPGRADE")R.skipWaiting(),R.clients.matchAll().then(u=>{u.forEach(h=>{h.postMessage({type:"SW_UPDATED"})})});else if(s.data&&s.data.type==="DELETE_CACHE"){const{url:u}=s.data;u&&ur(u).then(()=>{R.clients.matchAll().then(h=>{h.forEach(g=>{g.postMessage({type:"CACHE_DELETED",url:u})})})}).catch(h=>{console.error("Service Worker: Failed to delete cache:",h)})}else if(s.data&&s.data.type==="DELETE_CACHE_BATCH"){const{urls:u}=s.data;u&&Array.isArray(u)&&dr(u).then(()=>{}).catch(h=>{console.error("Service Worker: Failed to batch delete caches:",h)})}else if(s.data&&s.data.type==="CLEAR_ALL_CACHE")hr().then(()=>{}).catch(u=>{console.error("Service Worker: Failed to clear all cache:",u)});else if(s.data&&s.data.type==="SW_DEBUG_ENABLE")F=!0,we=Date.now(),Promise.resolve().then(()=>v).then(({setDebugFetchEnabled:u})=>{u(!0)}),je(!0),re.log("Service Worker: Debug mode enabled"),Q&&clearTimeout(Q),Q=setTimeout(jt,5e3),R.clients.matchAll().then(u=>{u.forEach(h=>{h.postMessage({type:"SW_DEBUG_ENABLED"})})}),(l=s.source)==null||l.postMessage({type:"SW_DEBUG_STATUS",status:Ge()});else if(s.data&&s.data.type==="SW_DEBUG_HEARTBEAT")F&&(we=Date.now());else if(s.data&&s.data.type==="SW_DEBUG_DISABLE")F=!1,we=0,Q&&(clearTimeout(Q),Q=null),Promise.resolve().then(()=>v).then(({setDebugFetchEnabled:u})=>{u(!1)}),je(!1),Re.length=0,V.length=0,Xt().catch(()=>{}),re.log("Service Worker: Debug mode disabled, logs cleared"),R.clients.matchAll().then(u=>{u.forEach(h=>{h.postMessage({type:"SW_DEBUG_DISABLED"})})}),(d=s.source)==null||d.postMessage({type:"SW_DEBUG_STATUS",status:Ge()});else if(s.data&&s.data.type==="SW_DEBUG_GET_STATUS")(async()=>{var g;const u=Ge(),h=await lr();(g=s.source)==null||g.postMessage({type:"SW_DEBUG_STATUS",status:{...u,cacheStats:h}})})();else if(s.data&&s.data.type==="SW_DEBUG_GET_LOGS"){const{limit:u=100,offset:h=0,filter:g}=s.data,T=Ut().map(b=>({...b,type:"fetch"})),_=new Map;for(const b of V)_.set(b.id,b);for(const b of T)_.set(b.id,b);let C=Array.from(_.values()).sort((b,O)=>O.timestamp-b.timestamp);g&&(g.type&&(C=C.filter(b=>b.type===g.type)),g.requestType&&(C=C.filter(b=>b.requestType===g.requestType)),g.url&&(C=C.filter(b=>{var O;return(O=b.url)==null?void 0:O.includes(g.url)})),g.status&&(C=C.filter(b=>b.status===g.status)));const D=C.slice(h,h+u);(m=s.source)==null||m.postMessage({type:"SW_DEBUG_LOGS",logs:D,total:C.length,offset:h,limit:u})}else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_LOGS")V.length=0,(y=s.source)==null||y.postMessage({type:"SW_DEBUG_LOGS_CLEARED"});else if(s.data&&s.data.type==="SW_CDN_GET_STATUS")(w=s.source)==null||w.postMessage({type:"SW_CDN_STATUS",status:Wo()});else if(s.data&&s.data.type==="SW_CDN_RESET_STATUS")Lo(),(f=s.source)==null||f.postMessage({type:"SW_CDN_STATUS_RESET"});else if(s.data&&s.data.type==="SW_CDN_HEALTH_CHECK")(async()=>{var h;const u=await Do(Z);(h=s.source)==null||h.postMessage({type:"SW_CDN_HEALTH_CHECK_RESULT",results:Object.fromEntries(u)})})();else if(s.data&&s.data.type==="SW_DEBUG_GET_CACHE_ENTRIES"){const{cacheName:u,limit:h=50,offset:g=0}=s.data;(async()=>{var T,_;try{const C=await caches.open(u||M),D=await C.keys(),b=[];for(let O=g;O<Math.min(g+h,D.length);O++){const z=D[O],X=await C.match(z);if(X){const De=X.headers.get("sw-cache-date"),We=X.headers.get("sw-image-size")||X.headers.get("content-length");b.push({url:z.url,cacheDate:De?parseInt(De):void 0,size:We?parseInt(We):void 0})}}(T=s.source)==null||T.postMessage({type:"SW_DEBUG_CACHE_ENTRIES",cacheName:u||M,entries:b,total:D.length,offset:g,limit:h})}catch(C){(_=s.source)==null||_.postMessage({type:"SW_DEBUG_CACHE_ENTRIES",error:String(C)})}})()}else if(s.data&&s.data.type==="SW_CONSOLE_LOG_REPORT"){const{logLevel:u,logMessage:h,logStack:g,logSource:T,url:_}=s.data;Jt({logLevel:u,logMessage:h,logStack:g,logSource:T,url:_})}else if(s.data&&s.data.type==="SW_DEBUG_GET_CONSOLE_LOGS")(async()=>{var u,h;try{const{limit:g=500,offset:T=0,filter:_}=s.data;let C=await Qt();if(_&&(_.logLevel&&(C=C.filter(b=>b.logLevel===_.logLevel)),_.search)){const b=_.search.toLowerCase();C=C.filter(O=>{var z,X;return((z=O.logMessage)==null?void 0:z.toLowerCase().includes(b))||((X=O.logStack)==null?void 0:X.toLowerCase().includes(b))})}const D=C.slice(T,T+g);(u=s.source)==null||u.postMessage({type:"SW_DEBUG_CONSOLE_LOGS",logs:D,total:C.length,offset:T,limit:g})}catch(g){(h=s.source)==null||h.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 u;Re.length=0,await Xt(),(u=s.source)==null||u.postMessage({type:"SW_DEBUG_CONSOLE_LOGS_CLEARED"})})();else if(s.data&&s.data.type==="SW_DEBUG_EXPORT_LOGS")(async()=>{var T;const u=await Qt(),h=Ce(),g={exportTime:new Date().toISOString(),swVersion:Z,userAgent:"",status:Ge(),fetchLogs:V,consoleLogs:u,postmessageLogs:h};(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:u=200,offset:h=0,filter:g}=s.data;let T=Ce();if(g&&(g.direction&&(T=T.filter(C=>C.direction===g.direction)),g.messageType)){const C=g.messageType.toLowerCase();T=T.filter(D=>{var b;return(b=D.messageType)==null?void 0:b.toLowerCase().includes(C)})}const _=T.slice(h,h+u);(p=s.source)==null||p.postMessage({type:"SW_DEBUG_POSTMESSAGE_LOGS",logs:_,total:T.length,offset:h,limit:u,stats:Os()})}else if(s.data&&s.data.type==="SW_DEBUG_CLEAR_POSTMESSAGE_LOGS")Ws(),(S=s.source)==null||S.postMessage({type:"SW_DEBUG_POSTMESSAGE_LOGS_CLEARED"});else if(s.data&&s.data.type==="CRASH_SNAPSHOT"){const u=s.data.snapshot;u&&(or(u),R.clients.matchAll().then(h=>{h.forEach(g=>{g.postMessage({type:"SW_DEBUG_NEW_CRASH_SNAPSHOT",snapshot:u})})}))}else s.data&&s.data.type==="SW_DEBUG_GET_CRASH_SNAPSHOTS"?(async()=>{var u,h;try{const g=await rr();(u=s.source)==null||u.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS",snapshots:g,total:g.length})}catch(g){(h=s.source)==null||h.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS",snapshots:[],total:0,error:String(g)})}})():s.data&&s.data.type==="SW_DEBUG_CLEAR_CRASH_SNAPSHOTS"?(async()=>{var u;await nr(),(u=s.source)==null||u.postMessage({type:"SW_DEBUG_CRASH_SNAPSHOTS_CLEARED"})})():s.data&&s.data.type==="SW_DEBUG_GET_LLM_API_LOGS"?(async()=>{var u,h;try{const{getAllLLMApiLogs:g}=await Promise.resolve().then(()=>I),T=await g();(u=s.source)==null||u.postMessage({type:"SW_DEBUG_LLM_API_LOGS",logs:T,total:T.length})}catch(g){(h=s.source)==null||h.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 h;const{clearAllLLMApiLogs:u}=await Promise.resolve().then(()=>I);await u(),(h=s.source)==null||h.postMessage({type:"SW_DEBUG_LLM_API_LOGS_CLEARED"})})()});const sr="MemorySnapshotDB",ee="snapshots",es=50;async function dt(){return new Promise((s,e)=>{const t=indexedDB.open(sr,1);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const n=o.target.result;if(!n.objectStoreNames.contains(ee)){const r=n.createObjectStore(ee,{keyPath:"id"});r.createIndex("timestamp","timestamp",{unique:!1}),r.createIndex("type","type",{unique:!1})}}})}async function or(s){try{const e=await dt(),t=e.transaction(ee,"readwrite"),o=t.objectStore(ee);o.put(s);const n=o.count();n.onsuccess=()=>{const r=n.result;if(r>es){const i=o.index("timestamp").openCursor();let c=0;const l=r-es;i.onsuccess=d=>{const m=d.target.result;m&&c<l&&(o.delete(m.value.id),c++,m.continue())}}},await new Promise((r,a)=>{t.oncomplete=()=>{e.close(),r()},t.onerror=()=>{e.close(),a(t.error)}})}catch(e){console.warn("[SW] Failed to save crash snapshot:",e)}}async function rr(){try{const s=await dt(),o=s.transaction(ee,"readonly").objectStore(ee).index("timestamp");return new Promise((n,r)=>{const a=o.getAll();a.onsuccess=()=>{s.close();const i=a.result.sort((c,l)=>l.timestamp-c.timestamp);n(i)},a.onerror=()=>{s.close(),r(a.error)}})}catch(s){return console.warn("[SW] Failed to get crash snapshots:",s),[]}}async function nr(){try{const s=await dt(),e=s.transaction(ee,"readwrite");e.objectStore(ee).clear(),await new Promise((o,n)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),n(e.error)}}),console.log("[SW] Crash snapshots cleared")}catch(s){console.warn("[SW] Failed to clear crash snapshots:",s)}}const ar=["ConsoleLogDB","ServiceWorkerDB","sw-task-queue","aitu-workspace","drawnix-unified-cache","drawnix-kv-storage","drawnix-prompts","drawnix-chat-db","MemorySnapshotDB"];function ir(s){try{const e=JSON.stringify(s);return new Blob([e]).size}catch{return 0}}async function cr(s){return new Promise(e=>{try{const t=indexedDB.open(s);t.onerror=()=>e({count:0,totalSize:0}),t.onsuccess=()=>{const o=t.result,n=Array.from(o.objectStoreNames);if(n.length===0){o.close(),e({count:0,totalSize:0});return}let r=0,a=0,i=0,c=0;const l=10;try{const d=o.transaction(n,"readonly");for(const m of n){const y=d.objectStore(m),w=y.count();w.onsuccess=()=>{const f=w.result;if(r+=f,f>0){const p=y.openCursor();let S=0;p.onsuccess=u=>{const h=u.target.result;if(h&&S<l)a+=ir(h.value),i++,S++,h.continue();else if(c++,c===n.length){o.close();const g=i>0?a/i:0,T=Math.round(g*r);e({count:r,totalSize:T})}},p.onerror=()=>{if(c++,c===n.length){o.close();const u=i>0?a/i:0,h=Math.round(u*r);e({count:r,totalSize:h})}}}else c++,c===n.length&&(o.close(),e({count:r,totalSize:0}))},w.onerror=()=>{if(c++,c===n.length){o.close();const f=i>0?a/i:0,p=Math.round(f*r);e({count:r,totalSize:p})}}}}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 lr(){const s={},e=[Ue,M,ge,qe];for(const t of e)try{const o=await caches.open(t),n=await o.keys();let r=0;const a=Math.min(n.length,100);let i=0;for(let c=0;c<a;c++){const l=await o.match(n[c]);if(l){const d=l.headers.get("sw-image-size")||l.headers.get("content-length");d&&(i+=parseInt(d))}}a>0&&n.length>a?r=Math.round(i/a*n.length):r=i,s[t]={count:n.length,totalSize:r,type:"cache"}}catch{s[t]={count:0,totalSize:0,type:"cache"}}for(const t of ar)try{const o=await cr(t);o.count>0&&(s[`[IDB] ${t}`]={...o,type:"indexeddb"})}catch{}return s}async function ur(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 dr(s){try{const e=await caches.open(M);let t=0;for(const o of s)try{await e.delete(o),t++}catch(n){console.warn("Service Worker: Failed to delete cache in batch:",o,n)}}catch(e){throw console.error("Service Worker: Failed to batch delete caches:",e),e}}async function hr(){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 ts(s,e,t){try{(await R.clients.matchAll()).forEach(n=>{n.postMessage({type:"IMAGE_CACHED",url:s,size:e,mimeType:t,timestamp:Date.now()})})}catch(o){console.warn("Service Worker: Failed to notify image cached:",o)}}async function fr(){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(r=>{r.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:"){$({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(Oo)){const o=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"cache-url",details:"Intercepting cache URL request"});s.respondWith(pr(s.request).then(n=>(x(o,{status:n.status,statusText:n.statusText,responseType:n.type,duration:Date.now()-t,cached:n.status===200}),n)).catch(n=>{throw x(o,{error:String(n),duration:Date.now()-t}),n}));return}if(e.pathname.startsWith(ko)){const o=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"asset-library",details:"Intercepting asset library request"});s.respondWith(mr(s.request).then(n=>(x(o,{status:n.status,statusText:n.statusText,responseType:n.type,duration:Date.now()-t,cached:n.status===200}),n)).catch(n=>{throw x(o,{error:String(n),duration:Date.now()-t}),n}));return}if(e.hostname==="cdn.i666.fun"){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"passthrough",details:"Passthrough: cdn.i666.fun (fallback domain)",status:0,duration:0});return}if(e.hostname.endsWith(".volces.com")||e.hostname.endsWith(".volccdn.com")){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"passthrough",details:"Passthrough: Volcengine domain (no CORS)",status:0,duration:0});return}if(e.hostname.endsWith(".aliyuncs.com")){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"passthrough",details:"Passthrough: Aliyun OSS domain (no CORS)",status:0,duration:0});return}if(Bo(e.hostname)){$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"passthrough",details:`Passthrough: ${e.hostname} (CORS failed domain, auto-detected)`,status:0,duration:0});return}if(jo(e,s.request)){const o=Date.now(),n=s.request.headers.get("range"),r=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"video",headers:n?{range:n}:void 0,details:n?`Video Range request: ${n}`:"Video request"});s.respondWith(wr(s.request).then(a=>(x(r,{status:a.status,statusText:a.statusText,responseType:a.type,duration:Date.now()-o,responseHeaders:{"content-type":a.headers.get("content-type")||"","content-length":a.headers.get("content-length")||"","content-range":a.headers.get("content-range")||""}}),a)).catch(a=>{throw x(r,{error:String(a),duration:Date.now()-o}),a}));return}if(Vo(e,s.request)){const o=Date.now(),n=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"font",details:"Font request"});s.respondWith(gr(s.request).then(r=>(x(n,{status:r.status,statusText:r.statusText,responseType:r.type,duration:Date.now()-o,cached:r.headers.has("sw-cache-date")}),r)).catch(r=>{throw x(n,{error:String(r),duration:Date.now()-o}),r}));return}if(e.origin!==location.origin&&zo(e,s.request)){const o=Date.now(),n=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"image",details:"External image request"});s.respondWith(Er(s.request).then(r=>(x(n,{status:r.status,statusText:r.statusText,responseType:r.type,duration:Date.now()-o,cached:r.headers.has("sw-cache-date"),size:parseInt(r.headers.get("content-length")||"0")}),r)).catch(r=>{throw x(n,{error:String(r),duration:Date.now()-o}),r}));return}if(s.request.method==="GET"){const o=s.request.mode==="navigate",n=s.request.destination!=="";if(o||n){const r=Date.now(),a=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"static",details:o?"Navigation request":`Static resource (${s.request.destination})`});s.respondWith(Sr(s.request).then(i=>(x(a,{status:i.status,statusText:i.statusText,responseType:i.type,duration:Date.now()-r}),i)).catch(i=>{throw x(a,{error:String(i),duration:Date.now()-r}),i}));return}}if(F){const o=$({type:"fetch",url:s.request.url,method:s.request.method,requestType:"xhr",details:`XHR/API request (${s.request.method})`});s.respondWith((async()=>{try{const n=s.request.clone();let r,a={};if(s.request.headers.forEach((m,y)=>{a[y]=m}),["POST","PUT","PATCH"].includes(s.request.method))try{const m=s.request.headers.get("content-type")||"";m.includes("application/json")?(r=await n.text(),r.length>2e3&&(r=r.substring(0,2e3)+"... (truncated)")):m.includes("application/x-www-form-urlencoded")?(r=await n.text(),r.length>2e3&&(r=r.substring(0,2e3)+"... (truncated)")):r=`[${m||"binary data"}]`}catch{r="[unable to read body]"}x(o,{headers:a,details:r?`XHR/API request (${s.request.method})
6
6
 
7
7
  Request Body:
8
- ${r}`:`XHR/API request (${s.request.method})`});const i=await fetch(s.request),c=i.clone();let l,d={};i.headers.forEach((m,y)=>{d[y]=m});try{const m=i.headers.get("content-type")||"";m.includes("application/json")||m.includes("text/")?(l=await c.text(),l.length>5e3&&(l=l.substring(0,5e3)+"... (truncated)")):l=`[${m||"binary data"}] (${i.headers.get("content-length")||"unknown"} bytes)`}catch{l="[unable to read response body]"}return P(o,{status:i.status,statusText:i.statusText,responseType:i.type,duration:Date.now()-t,responseHeaders:d,size:parseInt(i.headers.get("content-length")||"0"),details:r?`XHR/API request (${s.request.method})
8
+ ${r}`:`XHR/API request (${s.request.method})`});const i=await fetch(s.request),c=i.clone();let l,d={};i.headers.forEach((m,y)=>{d[y]=m});try{const m=i.headers.get("content-type")||"";m.includes("application/json")||m.includes("text/")?(l=await c.text(),l.length>5e3&&(l=l.substring(0,5e3)+"... (truncated)")):l=`[${m||"binary data"}] (${i.headers.get("content-length")||"unknown"} bytes)`}catch{l="[unable to read response body]"}return x(o,{status:i.status,statusText:i.statusText,responseType:i.type,duration:Date.now()-t,responseHeaders:d,size:parseInt(i.headers.get("content-length")||"0"),details:r?`XHR/API request (${s.request.method})
9
9
 
10
10
  Request Body:
11
11
  ${r}
@@ -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(n){throw P(o,{error:String(n),duration:Date.now()-t}),n}})());return}});async function fr(s){new URL(s.url);const e=Math.random().toString(36).substring(2,10);try{const t=await caches.open(qe),o=await t.match(s);if(o)return o;const n=await fetch(s);if(n&&n.status===200){const r=n.clone(),a=new Headers(r.headers);a.set("sw-cache-date",Date.now().toString());const i=new Response(r.body,{status:r.status,statusText:r.statusText,headers:a});t.put(s,i).catch(c=>{console.warn(`Service Worker [Font-${e}]: 缓存字体失败:`,c)})}return n}catch(t){console.error(`Service Worker [Font-${e}]: 字体请求失败:`,t);const n=await(await caches.open(qe)).match(s);return n||new Response("Font loading failed",{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/plain"}})}}async function ht(s,e={}){return fetch(s,e)}async function gr(s){const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=s.headers.get("range"),n=t.pathname.includes("/video/")||/\.(mp4|webm|ogg|mov)$/i.test(t.pathname);try{const r=await caches.open(x);let a=await r.match(s.url);if(a||(a=await r.match(t.pathname)),a){const i=await a.blob();return n?Te(i,o,e):new Response(i,{status:200,statusText:"OK",headers:{"Content-Type":i.type||"image/png","Content-Length":i.size.toString(),"Access-Control-Allow-Origin":"*","Cache-Control":"max-age=31536000"}})}return console.error("Service Worker: Media not found in cache:",{fullUrl:s.url,pathname:t.pathname}),new Response("Media not found",{status:404,statusText:"Not Found",headers:{"Content-Type":"text/plain"}})}catch(r){return console.error("Service Worker: Error handling cache URL request:",r),new Response("Internal error",{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain"}})}}async function pr(s){const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=s.headers.get("range"),n=t.pathname;try{const a=await(await caches.open(x)).match(n);if(a){const i=await a.blob();return t.pathname.match(/\.(mp4|webm|ogg|mov)$/i)&&o?Te(i,o,e):new Response(i,{status:200,statusText:"OK",headers:{"Content-Type":i.type||"application/octet-stream","Content-Length":i.size.toString(),"Accept-Ranges":"bytes","Access-Control-Allow-Origin":"*","Cache-Control":"max-age=31536000"}})}return console.error(`Service Worker [Asset-${e}]: Asset not found in cache:`,n),new Response("Asset not found",{status:404,statusText:"Not Found",headers:{"Content-Type":"text/plain"}})}catch(r){return console.error(`Service Worker [Asset-${e}]: Error handling asset library request:`,r),new Response("Internal error",{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain"}})}}async function mr(s){const e=new URL(s.url),t=Math.random().toString(36).substring(2,10);try{const o=s.headers.get("range"),n=new URL(e);["_t","cache_buster","v","timestamp","nocache","_cb","t","retry","rand"].forEach(d=>n.searchParams.delete(d));const a=n.toString(),i=Ae.get(a);if(i){i.count=(i.count||1)+1;const d=await i.promise;if(!d){const m={method:"GET",headers:new Headers(s.headers),mode:"cors",credentials:"omit"};return await fetch(e,m)}return Te(d,o,t)}if(q.has(a)){const d=q.get(a);if(d)return d.timestamp=Date.now(),Te(d.blob,o,t)}try{const m=await(await caches.open(x)).match(a);if(m){const y=await m.blob();return y.size/(1024*1024)<50&&q.set(a,{blob:y,timestamp:Date.now()}),Te(y,o,t)}}catch(d){console.warn(`Service Worker [Video-${t}]: 检查 Cache API 失败:`,d)}const c=(async()=>{const d={method:"GET",mode:"cors",credentials:"omit",cache:"default"},m=new URL(n),y=await fetch(m,d);if(!y.ok)throw console.error(`Service Worker [Video-${t}]: Video fetch failed:`,y.status),new Error(`Video fetch failed: ${y.status}`);if(y.status===206)return null;const w=await y.blob();if(w.size/(1024*1024)<50){q.set(a,{blob:w,timestamp:Date.now()});try{const p=await caches.open(x),S=new Response(w,{headers:{"Content-Type":w.type||"video/mp4","Content-Length":w.size.toString(),"sw-cache-date":Date.now().toString(),"sw-video-size":w.size.toString()}});await p.put(a,S)}catch(p){console.warn(`Service Worker [Video-${t}]: 持久化到 Cache API 失败:`,p)}}return w})();Ae.set(a,{promise:c,timestamp:Date.now(),count:1,requestId:t}),c.finally(()=>{Ae.get(a)&&Ae.delete(a)});const l=await c;if(l===null){const d={method:"GET",headers:new Headers(s.headers),mode:"cors",credentials:"omit"};return await fetch(e,d)}return Te(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 Te(s,e,t){const o=s.size;if(!e)return new Response(s,{status:200,statusText:"OK",headers:{"Content-Type":"video/mp4","Content-Length":o.toString(),"Accept-Ranges":"bytes","Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":"Content-Range, Accept-Ranges, Content-Length"}});const n=e.match(/bytes=(\d+)-(\d*)/);if(!n)return console.error(`Service Worker [Video-${t}]: Invalid Range header format`),new Response(s,{status:200,statusText:"OK",headers:{"Content-Type":"video/mp4","Accept-Ranges":"bytes"}});const r=parseInt(n[1],10),a=n[2]?parseInt(n[2],10):o-1,i=s.slice(r,a+1),c=a-r+1;return new Response(i,{status:206,statusText:"Partial Content",headers:{"Content-Type":"video/mp4","Content-Range":`bytes ${r}-${a}/${o}`,"Content-Length":c.toString(),"Accept-Ranges":"bytes","Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":"Content-Range, Accept-Ranges, Content-Length"}})}async function wr(s){const e=new URL(s.url),t=s.mode==="navigate"||e.pathname.endsWith(".html"),o=await caches.open(ge);if(lt)try{const i=await ht(s);if(i&&i.status===200&&s.url.startsWith("http"))return o.put(s,i.clone()),i;if(!i.ok){let c=await o.match(s);return!c&&t&&(c=await o.match("/"),c||(c=await o.match("/index.html"))),c||i}return i}catch{let c=await o.match(s);return!c&&t&&(c=await o.match("/"),c||(c=await o.match("/index.html"))),c||(t?ts():new Response("Resource unavailable",{status:503}))}if(t)try{const i=await ht(s,{cache:"reload"});if(i&&i.status===200&&s.url.startsWith("http"))return o.put(s,i.clone()),i;if(!i.ok){let c=await o.match(s);return c||(c=await o.match("/")),c||(c=await o.match("/index.html")),c||i}return i}catch{let c=await o.match(s);return c||(c=await o.match("/")),c||(c=await o.match("/index.html")),c||ts()}const n=await o.match(s);if(n)return n;const r=e.pathname;if(!lt&&(r.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==="font"))try{console.log(`[SW CDN] Trying CDN first for: ${r}`);const i=await Ao(r,Z,location.origin);if(i&&i.response.ok){console.log(`[SW CDN] Success from ${i.source}: ${r}`);const c=i.response.clone();return o.put(s,c),i.response}}catch(i){console.warn("[SW CDN] CDN sources failed, trying local server:",i)}try{const i=await ht(s),c=i.headers.get("Content-Type");if(i.status===200&&(c==null?void 0:c.includes("text/html"))&&(e.pathname.match(/\.(js|css|png|jpg|jpeg|gif|webp|svg|json|woff|woff2|ttf)$/i)||s.destination==="script"||s.destination==="style"||s.destination==="image"||s.destination==="font"))return console.warn("Service Worker: HTML response for static resource (404):",s.url),new Response("Resource not found",{status:404,statusText:"Not Found"});if(i&&i.status===200&&s.url.startsWith("http")&&o.put(s,i.clone()),i.status>=500){const d=await caches.keys();for(const m of d)if(m.startsWith("drawnix-static-v"))try{const w=await(await caches.open(m)).match(s);if(w)return w}catch{}}return i}catch{console.warn("[SW] Network failed, trying old caches:",s.url);const c=await caches.keys();for(const l of c)if(l.startsWith("drawnix-static-v"))try{const m=await(await caches.open(l)).match(s);if(m)return console.log(`[SW] Found resource in ${l} after network failure`),m}catch{}return new Response("Resource unavailable offline",{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/plain"}})}}function ts(){return new Response(`<!DOCTYPE html>
17
+ ${l}`}),i}catch(n){throw x(o,{error:String(n),duration:Date.now()-t}),n}})());return}});async function gr(s){new URL(s.url);const e=Math.random().toString(36).substring(2,10);try{const t=await caches.open(qe),o=await t.match(s);if(o)return o;const n=await fetch(s);if(n&&n.status===200){const r=n.clone(),a=new Headers(r.headers);a.set("sw-cache-date",Date.now().toString());const i=new Response(r.body,{status:r.status,statusText:r.statusText,headers:a});t.put(s,i).catch(c=>{console.warn(`Service Worker [Font-${e}]: 缓存字体失败:`,c)})}return n}catch(t){console.error(`Service Worker [Font-${e}]: 字体请求失败:`,t);const n=await(await caches.open(qe)).match(s);return n||new Response("Font loading failed",{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/plain"}})}}async function ht(s,e={}){return fetch(s,e)}async function pr(s){const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=s.headers.get("range"),n=t.pathname.includes("/video/")||/\.(mp4|webm|ogg|mov)$/i.test(t.pathname);try{const r=await caches.open(M);let a=await r.match(s.url);if(a||(a=await r.match(t.pathname)),a){const i=await a.blob();return n?Te(i,o,e):new Response(i,{status:200,statusText:"OK",headers:{"Content-Type":i.type||"image/png","Content-Length":i.size.toString(),"Access-Control-Allow-Origin":"*","Cache-Control":"max-age=31536000"}})}return console.error("Service Worker: Media not found in cache:",{fullUrl:s.url,pathname:t.pathname}),new Response("Media not found",{status:404,statusText:"Not Found",headers:{"Content-Type":"text/plain"}})}catch(r){return console.error("Service Worker: Error handling cache URL request:",r),new Response("Internal error",{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain"}})}}async function mr(s){const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=s.headers.get("range"),n=t.pathname;try{const a=await(await caches.open(M)).match(n);if(a){const i=await a.blob();return t.pathname.match(/\.(mp4|webm|ogg|mov)$/i)&&o?Te(i,o,e):new Response(i,{status:200,statusText:"OK",headers:{"Content-Type":i.type||"application/octet-stream","Content-Length":i.size.toString(),"Accept-Ranges":"bytes","Access-Control-Allow-Origin":"*","Cache-Control":"max-age=31536000"}})}return console.error(`Service Worker [Asset-${e}]: Asset not found in cache:`,n),new Response("Asset not found",{status:404,statusText:"Not Found",headers:{"Content-Type":"text/plain"}})}catch(r){return console.error(`Service Worker [Asset-${e}]: Error handling asset library request:`,r),new Response("Internal error",{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain"}})}}async function wr(s){const e=new URL(s.url),t=Math.random().toString(36).substring(2,10);try{const o=s.headers.get("range"),n=new URL(e);["_t","cache_buster","v","timestamp","nocache","_cb","t","retry","rand"].forEach(d=>n.searchParams.delete(d));const a=n.toString(),i=Ae.get(a);if(i){i.count=(i.count||1)+1;const d=await i.promise;if(!d){const m={method:"GET",headers:new Headers(s.headers),mode:"cors",credentials:"omit"};return await fetch(e,m)}return Te(d,o,t)}if(q.has(a)){const d=q.get(a);if(d)return d.timestamp=Date.now(),Te(d.blob,o,t)}try{const m=await(await caches.open(M)).match(a);if(m){const y=await m.blob();return y.size/(1024*1024)<50&&q.set(a,{blob:y,timestamp:Date.now()}),Te(y,o,t)}}catch(d){console.warn(`Service Worker [Video-${t}]: 检查 Cache API 失败:`,d)}const c=(async()=>{const d={method:"GET",mode:"cors",credentials:"omit",cache:"default"},m=new URL(n),y=await fetch(m,d);if(!y.ok)throw console.error(`Service Worker [Video-${t}]: Video fetch failed:`,y.status),new Error(`Video fetch failed: ${y.status}`);if(y.status===206)return null;const w=await y.blob();if(w.size/(1024*1024)<50){q.set(a,{blob:w,timestamp:Date.now()});try{const p=await caches.open(M),S=new Response(w,{headers:{"Content-Type":w.type||"video/mp4","Content-Length":w.size.toString(),"sw-cache-date":Date.now().toString(),"sw-video-size":w.size.toString()}});await p.put(a,S)}catch(p){console.warn(`Service Worker [Video-${t}]: 持久化到 Cache API 失败:`,p)}}return w})();Ae.set(a,{promise:c,timestamp:Date.now(),count:1,requestId:t}),c.finally(()=>{Ae.get(a)&&Ae.delete(a)});const l=await c;if(l===null){const d={method:"GET",headers:new Headers(s.headers),mode:"cors",credentials:"omit"};return await fetch(e,d)}return Te(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 Te(s,e,t){const o=s.size;if(!e)return new Response(s,{status:200,statusText:"OK",headers:{"Content-Type":"video/mp4","Content-Length":o.toString(),"Accept-Ranges":"bytes","Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":"Content-Range, Accept-Ranges, Content-Length"}});const n=e.match(/bytes=(\d+)-(\d*)/);if(!n)return console.error(`Service Worker [Video-${t}]: Invalid Range header format`),new Response(s,{status:200,statusText:"OK",headers:{"Content-Type":"video/mp4","Accept-Ranges":"bytes"}});const r=parseInt(n[1],10),a=n[2]?parseInt(n[2],10):o-1,i=s.slice(r,a+1),c=a-r+1;return new Response(i,{status:206,statusText:"Partial Content",headers:{"Content-Type":"video/mp4","Content-Range":`bytes ${r}-${a}/${o}`,"Content-Length":c.toString(),"Accept-Ranges":"bytes","Access-Control-Allow-Origin":"*","Access-Control-Expose-Headers":"Content-Range, Accept-Ranges, Content-Length"}})}async function Sr(s){const e=new URL(s.url),t=s.mode==="navigate"||e.pathname.endsWith(".html"),o=await caches.open(ge);if(lt)try{const i=await ht(s);if(i&&i.status===200&&s.url.startsWith("http"))return o.put(s,i.clone()),i;if(!i.ok){let c=await o.match(s);return!c&&t&&(c=await o.match("/"),c||(c=await o.match("/index.html"))),c||i}return i}catch{let c=await o.match(s);return!c&&t&&(c=await o.match("/"),c||(c=await o.match("/index.html"))),c||(t?ss():new Response("Resource unavailable",{status:503}))}if(t)try{const i=await ht(s,{cache:"reload"});if(i&&i.status===200&&s.url.startsWith("http"))return o.put(s,i.clone()),i;if(!i.ok){let c=await o.match(s);return c||(c=await o.match("/")),c||(c=await o.match("/index.html")),c||i}return i}catch{let c=await o.match(s);return c||(c=await o.match("/")),c||(c=await o.match("/index.html")),c||ss()}const n=await o.match(s);if(n)return n;const r=e.pathname;if(!lt&&(r.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==="font"))try{console.log(`[SW CDN] Trying CDN first for: ${r}`);const i=await Ro(r,Z,location.origin);if(i&&i.response.ok){console.log(`[SW CDN] Success from ${i.source}: ${r}`);const c=i.response.clone();return o.put(s,c),i.response}}catch(i){console.warn("[SW CDN] CDN sources failed, trying local server:",i)}try{const i=await ht(s),c=i.headers.get("Content-Type");if(i.status===200&&(c==null?void 0:c.includes("text/html"))&&(e.pathname.match(/\.(js|css|png|jpg|jpeg|gif|webp|svg|json|woff|woff2|ttf)$/i)||s.destination==="script"||s.destination==="style"||s.destination==="image"||s.destination==="font"))return console.warn("Service Worker: HTML response for static resource (404):",s.url),new Response("Resource not found",{status:404,statusText:"Not Found"});if(i&&i.status===200&&s.url.startsWith("http")&&o.put(s,i.clone()),i.status>=500){const d=await caches.keys();for(const m of d)if(m.startsWith("drawnix-static-v"))try{const w=await(await caches.open(m)).match(s);if(w)return w}catch{}}return i}catch{console.warn("[SW] Network failed, trying old caches:",s.url);const c=await caches.keys();for(const l of c)if(l.startsWith("drawnix-static-v"))try{const m=await(await caches.open(l)).match(s);if(m)return console.log(`[SW] Found resource in ${l} after network failure`),m}catch{}return new Response("Resource unavailable offline",{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/plain"}})}}function ss(){return new Response(`<!DOCTYPE html>
18
18
  <html lang="zh-CN">
19
19
  <head>
20
20
  <meta charset="UTF-8">
@@ -55,4 +55,4 @@ ${l}`}),i}catch(n){throw P(o,{error:String(n),duration:Date.now()-t}),n}})());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 ft=15e3,ss=3e4;function os(s,e,t){return Promise.race([s,new Promise((o,n)=>{setTimeout(()=>n(new Error(t)),e)})])}function Sr(){const s=Date.now(),e=[];if(q.forEach((t,o)=>{s-t.timestamp>Po&&e.push(o)}),e.length>0&&e.forEach(t=>q.delete(t)),q.size>Ht){const t=Array.from(q.entries()).sort((r,a)=>r[1].timestamp-a[1].timestamp),o=q.size-Ht,n=t.slice(0,o);n.length>0&&n.forEach(([r])=>q.delete(r))}}function yr(){const s=Date.now(),e=[];G.forEach((o,n)=>{s-o.timestamp>ss&&e.push(n)}),e.length>0&&(console.warn(`Service Worker: 清理 ${e.length} 个过期的 pending 请求`),e.forEach(o=>G.delete(o)));const t=[];ne.forEach((o,n)=>{s-o.timestamp>$t&&t.push(n)}),t.length>0&&t.forEach(o=>ne.delete(o)),Sr()}async function Tr(s){try{const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=t.searchParams.has("bypass_sw")||t.searchParams.has("direct_fetch");["_t","cache_buster","v","timestamp","nocache","_cb","t","retry","_retry","rand","_force","bypass_sw","direct_fetch"].forEach(l=>t.searchParams.delete(l));const r=new Request(t.toString(),{method:s.method,headers:s.headers,mode:s.mode,credentials:s.credentials}),a=t.toString(),i=ne.get(a);if(i){if(Date.now()-i.timestamp<$t)return i.response.clone();ne.delete(a)}if(G.has(a)){const l=G.get(a);if(l){const d=Date.now()-l.timestamp;if(d>ss)console.warn(`Service Worker [${e}]: 发现过期的 pending 请求 (${d}ms),清理并重新发起:`,a),G.delete(a);else{l.count=(l.count||1)+1,l.duplicateRequestIds=l.duplicateRequestIds||[],l.duplicateRequestIds.push(e);try{const m=await os(l.promise,ft,"Image request timeout");return m&&m.clone?m.clone():m}catch(m){if(m.message==="Image request timeout")return console.warn(`Service Worker [${e}]: 重复请求等待超时,清理并返回超时响应让前端直接加载`),G.delete(a),rs(s.url,e);throw m}}}}yr();const c=Er(r,s.url,a,e,o);G.set(a,{promise:c,timestamp:Date.now(),count:1,originalRequestId:e,duplicateRequestIds:[]}),c.then(l=>{l&&l.ok&&ne.set(a,{response:l.clone(),timestamp:Date.now()})}).catch(()=>{}).finally(()=>{G.get(a)&&G.delete(a)});try{return await os(c,ft,"Image request timeout")}catch(l){if(l.message==="Image request timeout")return console.warn(`Service Worker [${e}]: 图片请求超时(${ft}ms),清理并返回超时响应让前端直接加载:`,s.url),G.delete(a),rs(s.url,e);throw l}}catch(e){throw console.error("Service Worker fetch error:",e),e}}function rs(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 Er(s,e,t,o,n=!1){try{const r=await caches.open(x);if(!n){const f=await r.match(s);if(f){const S=await f.clone().blob();if(S.size===0)console.warn(`Service Worker [${o}]: 检测到空缓存,删除并重新获取:`,e),await r.delete(s);else if(f.headers.get("sw-cache-date")){const h=Date.now(),g=new Response(S,{status:f.status,statusText:f.statusText,headers:{...Object.fromEntries(f.headers.entries()),"sw-cache-date":h.toString()}});return s.url.startsWith("http")&&await r.put(s,g.clone()),g}else{const h=new Response(S,{status:f.status,statusText:f.statusText,headers:{...Object.fromEntries(f.headers.entries()),"sw-cache-date":Date.now().toString()}});return s.url.startsWith("http")&&await r.put(s,h.clone()),h}}}const a=new URL(e),i=Jt(a);let c=null,l=!1;i&&i.fallbackDomain&&(c=e.replace(i.hostname,i.fallbackDomain),pe.has(i.hostname)&&(l=!0));let d,m=[{method:"GET",mode:"no-cors",cache:"no-cache",credentials:"omit",referrerPolicy:"no-referrer"},{method:"GET",mode:"cors",cache:"no-cache",credentials:"omit",referrerPolicy:"no-referrer"},{method:"GET",cache:"no-cache"}],y;l?y=[c]:(y=[e],c&&y.push(c));let w=null;for(let f=0;f<y.length;f++){const p=y[f],S=f>0;for(let u of m)try{let h,g=!1;for(let T=0;T<=2;T++)try{if(d=await fetch(p,u),d&&(d.status!==0||d.type==="opaque"))break}catch(_){h=_;const C=_.message||"";if(C.includes("CORS")||C.includes("cross-origin")||C.includes("Access-Control-Allow-Origin")||C.includes("Failed to fetch")||C.includes("NetworkError")||C.includes("TypeError")){g=!0;break}T<2&&await new Promise(D=>setTimeout(D,Math.pow(2,T)*1e3))}if(g){const T=new URL(p).hostname;Kt(T),console.log(`Service Worker [${o}]: CORS 错误,尝试 no-cors 模式获取图片:`,e);try{const _=await fetch(e,{mode:"no-cors",credentials:"omit",referrerPolicy:"no-referrer"});if(_.type==="opaque")return console.log(`Service Worker [${o}]: no-cors 模式成功获取 opaque 响应`),_}catch(_){console.warn(`Service Worker [${o}]: no-cors 模式也失败:`,_)}return new Response(null,{status:200,headers:{"Content-Type":"image/png","X-SW-CORS-Bypass":"true"}})}if(d&&(d.status!==0||d.type==="opaque"))break;h&&(w=h)}catch(h){w=h;continue}if(d&&(d.status!==0||d.type==="opaque"))break;i&&i.fallbackDomain&&f===0&&!l&&(pe.add(i.hostname),Qo(i.hostname).catch(u=>{console.warn("Service Worker: 保存失败域名到数据库时出错:",u)}))}if(!d||d.status===0&&d.type!=="opaque"){let f="All fetch attempts failed";return i&&i.fallbackDomain&&(l?f=`备用域名${i.fallbackDomain}也失败了`:f=`All fetch attempts failed for both ${i.hostname} and ${i.fallbackDomain} domains`),console.error(`Service Worker [${o}]: ${f}`,w),new Response("Image load failed after all attempts",{status:404,statusText:"Image Not Found",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET","Access-Control-Allow-Headers":"*"}})}if(d.type==="opaque"){console.log(`Service Worker [${o}]: 返回 opaque 响应,依赖浏览器 disk cache`);const f=new URL(e).hostname;return Kt(f),d}if(d.ok){const p=await d.clone().blob(),S=p.size/(1024*1024),u=new Response(p,{status:200,statusText:"OK",headers:{"Content-Type":d.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":p.size.toString()}});try{s.url.startsWith("http")&&(await r.put(s,u.clone()),await es(e,p.size,p.type),await hr())}catch(h){console.warn(`Service Worker: Failed to cache normal response (${S.toFixed(2)}MB, 可能超出存储限制):`,h),await Jo(r);try{s.url.startsWith("http")&&(await r.put(s,u.clone()),await es(e,p.size,p.type))}catch(g){console.error("Service Worker: Still failed to cache after cleanup:",g)}}return u}throw new Error(`HTTP ${d.status}: ${d.statusText}`)}catch(r){console.error("Service Worker fetch error:",r);const a=new URL(e);return r.message.includes("SSL_PROTOCOL_ERROR")||r.message.includes("ERR_SSL_PROTOCOL_ERROR")||r.message.includes("net::ERR_CERT")||r.message.includes("ERR_INSECURE_RESPONSE")?(console.warn("Service Worker: 检测到SSL/证书错误,尝试跳过Service Worker处理"),fetch(e,{method:"GET",mode:"no-cors",cache:"no-cache",credentials:"omit"}).catch(()=>new Response("SSL Error - Image not accessible",{status:404,statusText:"SSL Protocol Error",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*"}}))):a.pathname.match(/\.(jpg|jpeg|png|gif|webp|svg|bmp|ico)$/i)||a.searchParams.has("_t")||a.searchParams.has("cache_buster")||a.searchParams.has("timestamp")?new Response("Image not found",{status:404,statusText:"Not Found",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*"}}):new Response(`Network Error: ${r.message}`,{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*"}})}}const te=[],Cr=50,_r="llm-api-logs",br=1,se="logs",ns=500;let ie=null;function gt(){return new Promise((s,e)=>{const t=indexedDB.open(_r,br);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const n=o.target.result;if(!n.objectStoreNames.contains(se)){const r=n.createObjectStore(se,{keyPath:"id"});r.createIndex("timestamp","timestamp",{unique:!1}),r.createIndex("taskType","taskType",{unique:!1}),r.createIndex("status","status",{unique:!1})}}})}async function as(s){try{const e=await gt(),t=e.transaction(se,"readwrite"),o=t.objectStore(se);o.put(s);const n=o.count();n.onsuccess=()=>{const r=n.result;if(r>ns){const a=o.index("timestamp"),i=r-ns;let c=0;a.openCursor().onsuccess=l=>{const d=l.target.result;d&&c<i&&(d.delete(),c++,d.continue())}}},await new Promise((r,a)=>{t.oncomplete=()=>{e.close(),r()},t.onerror=()=>{e.close(),a(t.error)}})}catch(e){console.warn("[LLMApiLogger] Failed to save log to DB:",e)}}async function is(s){await as(s)}async function cs(){try{const s=await gt(),o=s.transaction(se,"readonly").objectStore(se).index("timestamp");return new Promise((n,r)=>{const a=o.getAll();a.onsuccess=()=>{s.close();const i=a.result.reverse();n(i)},a.onerror=()=>{s.close(),r(a.error)}})}catch(s){return console.warn("[LLMApiLogger] Failed to get logs from DB:",s),te}}async function Ar(s){const e=te.find(t=>t.taskId===s&&t.status==="success"&&t.resultUrl);if(e)return e;try{return(await cs()).find(n=>n.taskId===s&&n.status==="success"&&n.resultUrl)||null}catch(t){return console.warn("[LLMApiLogger] Failed to find log by taskId:",t),null}}async function Rr(){te.length=0;try{const s=await gt(),e=s.transaction(se,"readwrite");e.objectStore(se).clear(),await new Promise((o,n)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),n(e.error)}})}catch(s){console.warn("[LLMApiLogger] Failed to clear logs from DB:",s)}}function Dr(s){ie=s}function Wr(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?Or(s.prompt):void 0,requestBody:s.requestBody,hasReferenceImages:s.hasReferenceImages,referenceImageCount:s.referenceImageCount,status:"pending",taskId:s.taskId,workflowId:s.workflowId};return te.unshift(t),te.length>Cr&&te.pop(),as(t),ie&&ie({...t}),e}function Lr(s,e){const t=te.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?pt(e.resultText,1e3):void 0,t.responseBody=e.responseBody?pt(e.responseBody,2e3):void 0,is(t),ie&&ie({...t}))}function Ir(s,e){const t=te.find(o=>o.id===s);t&&(t.status="error",t.httpStatus=e.httpStatus,t.duration=e.duration,t.errorMessage=kr(e.errorMessage),t.responseBody=e.responseBody?pt(e.responseBody,2e3):void 0,is(t),ie&&ie({...t}))}function Or(s){return s.length<=200?s:s.substring(0,200)+"..."}function pt(s,e){return s.length<=e?s:s.substring(0,e)+"..."}function kr(s){return s.length<=500?s:s.substring(0,500)+"..."}const I=Object.freeze(Object.defineProperty({__proto__:null,clearAllLLMApiLogs:Rr,completeLLMApiLog:Lr,failLLMApiLog:Ir,findSuccessLogByTaskId:Ar,getAllLLMApiLogs:cs,setLLMApiLogBroadcast:Dr,startLLMApiLog:Wr},Symbol.toStringTag,{value:"Module"}));async function Mr(s,e,t,o,n,r,a){try{if(Ze(e)){mt(s,{success:!1,error:`Tool "${e}" requires main thread execution`,type:"error"},r,a);return}const i=await Ye(e,t,{geminiConfig:o,videoConfig:n,onProgress:()=>{}});mt(s,i,r,a)}catch(i){mt(s,{success:!1,error:i.message||"Tool execution failed",type:"error"},r)}}function mt(s,e,t,o){const n={type:"MCP_TOOL_RESULT",requestId:s,success:e.success,data:e.data,error:e.error,resultType:e.type};Me(t,n)}const xr=Object.freeze(Object.defineProperty({__proto__:null,executeMCPTool:Mr},Symbol.toStringTag,{value:"Module"}))})();
58
+ </html>`,{status:503,statusText:"Service Unavailable",headers:{"Content-Type":"text/html; charset=utf-8","Cache-Control":"no-store"}})}const ft=15e3,os=3e4;function rs(s,e,t){return Promise.race([s,new Promise((o,n)=>{setTimeout(()=>n(new Error(t)),e)})])}function yr(){const s=Date.now(),e=[];if(q.forEach((t,o)=>{s-t.timestamp>vo&&e.push(o)}),e.length>0&&e.forEach(t=>q.delete(t)),q.size>Kt){const t=Array.from(q.entries()).sort((r,a)=>r[1].timestamp-a[1].timestamp),o=q.size-Kt,n=t.slice(0,o);n.length>0&&n.forEach(([r])=>q.delete(r))}}function Tr(){const s=Date.now(),e=[];G.forEach((o,n)=>{s-o.timestamp>os&&e.push(n)}),e.length>0&&(console.warn(`Service Worker: 清理 ${e.length} 个过期的 pending 请求`),e.forEach(o=>G.delete(o)));const t=[];ne.forEach((o,n)=>{s-o.timestamp>Ht&&t.push(n)}),t.length>0&&t.forEach(o=>ne.delete(o)),yr()}async function Er(s){try{const e=Math.random().toString(36).substring(2,10),t=new URL(s.url),o=t.searchParams.has("bypass_sw")||t.searchParams.has("direct_fetch");["_t","cache_buster","v","timestamp","nocache","_cb","t","retry","_retry","rand","_force","bypass_sw","direct_fetch"].forEach(l=>t.searchParams.delete(l));const r=new Request(t.toString(),{method:s.method,headers:s.headers,mode:s.mode,credentials:s.credentials}),a=t.toString(),i=ne.get(a);if(i){if(Date.now()-i.timestamp<Ht)return i.response.clone();ne.delete(a)}if(G.has(a)){const l=G.get(a);if(l){const d=Date.now()-l.timestamp;if(d>os)console.warn(`Service Worker [${e}]: 发现过期的 pending 请求 (${d}ms),清理并重新发起:`,a),G.delete(a);else{l.count=(l.count||1)+1,l.duplicateRequestIds=l.duplicateRequestIds||[],l.duplicateRequestIds.push(e);try{const m=await rs(l.promise,ft,"Image request timeout");return m&&m.clone?m.clone():m}catch(m){if(m.message==="Image request timeout")return console.warn(`Service Worker [${e}]: 重复请求等待超时,清理并返回超时响应让前端直接加载`),G.delete(a),ns(s.url,e);throw m}}}}Tr();const c=Cr(r,s.url,a,e,o);G.set(a,{promise:c,timestamp:Date.now(),count:1,originalRequestId:e,duplicateRequestIds:[]}),c.then(l=>{l&&l.ok&&ne.set(a,{response:l.clone(),timestamp:Date.now()})}).catch(()=>{}).finally(()=>{G.get(a)&&G.delete(a)});try{return await rs(c,ft,"Image request timeout")}catch(l){if(l.message==="Image request timeout")return console.warn(`Service Worker [${e}]: 图片请求超时(${ft}ms),清理并返回超时响应让前端直接加载:`,s.url),G.delete(a),ns(s.url,e);throw l}}catch(e){throw console.error("Service Worker fetch error:",e),e}}function ns(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 Cr(s,e,t,o,n=!1){try{const r=await caches.open(M);if(!n){const f=await r.match(s);if(f){const S=await f.clone().blob();if(S.size===0)console.warn(`Service Worker [${o}]: 检测到空缓存,删除并重新获取:`,e),await r.delete(s);else if(f.headers.get("sw-cache-date")){const h=Date.now(),g=new Response(S,{status:f.status,statusText:f.statusText,headers:{...Object.fromEntries(f.headers.entries()),"sw-cache-date":h.toString()}});return s.url.startsWith("http")&&await r.put(s,g.clone()),g}else{const h=new Response(S,{status:f.status,statusText:f.statusText,headers:{...Object.fromEntries(f.headers.entries()),"sw-cache-date":Date.now().toString()}});return s.url.startsWith("http")&&await r.put(s,h.clone()),h}}}const a=new URL(e),i=Yt(a);let c=null,l=!1;i&&i.fallbackDomain&&(c=e.replace(i.hostname,i.fallbackDomain),pe.has(i.hostname)&&(l=!0));let d,m=[{method:"GET",mode:"no-cors",cache:"no-cache",credentials:"omit",referrerPolicy:"no-referrer"},{method:"GET",mode:"cors",cache:"no-cache",credentials:"omit",referrerPolicy:"no-referrer"},{method:"GET",cache:"no-cache"}],y;l?y=[c]:(y=[e],c&&y.push(c));let w=null;for(let f=0;f<y.length;f++){const p=y[f],S=f>0;for(let u of m)try{let h,g=!1;for(let T=0;T<=2;T++)try{if(d=await fetch(p,u),d&&(d.status!==0||d.type==="opaque"))break}catch(_){h=_;const C=_.message||"";if(C.includes("CORS")||C.includes("cross-origin")||C.includes("Access-Control-Allow-Origin")||C.includes("Failed to fetch")||C.includes("NetworkError")||C.includes("TypeError")){g=!0;break}T<2&&await new Promise(D=>setTimeout(D,Math.pow(2,T)*1e3))}if(g){const T=new URL(p).hostname;zt(T),console.log(`Service Worker [${o}]: CORS 错误,尝试 no-cors 模式获取图片:`,e);try{const _=await fetch(e,{mode:"no-cors",credentials:"omit",referrerPolicy:"no-referrer"});if(_.type==="opaque")return console.log(`Service Worker [${o}]: no-cors 模式成功获取 opaque 响应`),_}catch(_){console.warn(`Service Worker [${o}]: no-cors 模式也失败:`,_)}return new Response(null,{status:200,headers:{"Content-Type":"image/png","X-SW-CORS-Bypass":"true"}})}if(d&&(d.status!==0||d.type==="opaque"))break;h&&(w=h)}catch(h){w=h;continue}if(d&&(d.status!==0||d.type==="opaque"))break;i&&i.fallbackDomain&&f===0&&!l&&(pe.add(i.hostname),Xo(i.hostname).catch(u=>{console.warn("Service Worker: 保存失败域名到数据库时出错:",u)}))}if(!d||d.status===0&&d.type!=="opaque"){let f="All fetch attempts failed";return i&&i.fallbackDomain&&(l?f=`备用域名${i.fallbackDomain}也失败了`:f=`All fetch attempts failed for both ${i.hostname} and ${i.fallbackDomain} domains`),console.error(`Service Worker [${o}]: ${f}`,w),new Response("Image load failed after all attempts",{status:404,statusText:"Image Not Found",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET","Access-Control-Allow-Headers":"*"}})}if(d.type==="opaque"){console.log(`Service Worker [${o}]: 返回 opaque 响应,依赖浏览器 disk cache`);const f=new URL(e).hostname;return zt(f),d}if(d.ok){const p=await d.clone().blob(),S=p.size/(1024*1024),u=new Response(p,{status:200,statusText:"OK",headers:{"Content-Type":d.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":p.size.toString()}});try{s.url.startsWith("http")&&(await r.put(s,u.clone()),await ts(e,p.size,p.type),await fr())}catch(h){console.warn(`Service Worker: Failed to cache normal response (${S.toFixed(2)}MB, 可能超出存储限制):`,h),await Yo(r);try{s.url.startsWith("http")&&(await r.put(s,u.clone()),await ts(e,p.size,p.type))}catch(g){console.error("Service Worker: Still failed to cache after cleanup:",g)}}return u}throw new Error(`HTTP ${d.status}: ${d.statusText}`)}catch(r){console.error("Service Worker fetch error:",r);const a=new URL(e);return r.message.includes("SSL_PROTOCOL_ERROR")||r.message.includes("ERR_SSL_PROTOCOL_ERROR")||r.message.includes("net::ERR_CERT")||r.message.includes("ERR_INSECURE_RESPONSE")?(console.warn("Service Worker: 检测到SSL/证书错误,尝试跳过Service Worker处理"),fetch(e,{method:"GET",mode:"no-cors",cache:"no-cache",credentials:"omit"}).catch(()=>new Response("SSL Error - Image not accessible",{status:404,statusText:"SSL Protocol Error",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*"}}))):a.pathname.match(/\.(jpg|jpeg|png|gif|webp|svg|bmp|ico)$/i)||a.searchParams.has("_t")||a.searchParams.has("cache_buster")||a.searchParams.has("timestamp")?new Response("Image not found",{status:404,statusText:"Not Found",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*"}}):new Response(`Network Error: ${r.message}`,{status:500,statusText:"Internal Server Error",headers:{"Content-Type":"text/plain","Access-Control-Allow-Origin":"*"}})}}const te=[],_r=50,br="llm-api-logs",Ar=1,se="logs",as=500;let ie=null;function gt(){return new Promise((s,e)=>{const t=indexedDB.open(br,Ar);t.onerror=()=>e(t.error),t.onsuccess=()=>s(t.result),t.onupgradeneeded=o=>{const n=o.target.result;if(!n.objectStoreNames.contains(se)){const r=n.createObjectStore(se,{keyPath:"id"});r.createIndex("timestamp","timestamp",{unique:!1}),r.createIndex("taskType","taskType",{unique:!1}),r.createIndex("status","status",{unique:!1})}}})}async function is(s){try{const e=await gt(),t=e.transaction(se,"readwrite"),o=t.objectStore(se);o.put(s);const n=o.count();n.onsuccess=()=>{const r=n.result;if(r>as){const a=o.index("timestamp"),i=r-as;let c=0;a.openCursor().onsuccess=l=>{const d=l.target.result;d&&c<i&&(d.delete(),c++,d.continue())}}},await new Promise((r,a)=>{t.oncomplete=()=>{e.close(),r()},t.onerror=()=>{e.close(),a(t.error)}})}catch(e){console.warn("[LLMApiLogger] Failed to save log to DB:",e)}}async function cs(s){await is(s)}async function ls(){try{const s=await gt(),o=s.transaction(se,"readonly").objectStore(se).index("timestamp");return new Promise((n,r)=>{const a=o.getAll();a.onsuccess=()=>{s.close();const i=a.result.reverse();n(i)},a.onerror=()=>{s.close(),r(a.error)}})}catch(s){return console.warn("[LLMApiLogger] Failed to get logs from DB:",s),te}}async function Rr(s){const e=te.find(t=>t.taskId===s&&t.status==="success"&&t.resultUrl);if(e)return e;try{return(await ls()).find(n=>n.taskId===s&&n.status==="success"&&n.resultUrl)||null}catch(t){return console.warn("[LLMApiLogger] Failed to find log by taskId:",t),null}}async function Dr(){te.length=0;try{const s=await gt(),e=s.transaction(se,"readwrite");e.objectStore(se).clear(),await new Promise((o,n)=>{e.oncomplete=()=>{s.close(),o()},e.onerror=()=>{s.close(),n(e.error)}})}catch(s){console.warn("[LLMApiLogger] Failed to clear logs from DB:",s)}}function Wr(s){ie=s}function Lr(s){const e=`llm-${Date.now()}-${Math.random().toString(36).substring(2,8)}`,t={id:e,timestamp:Date.now(),endpoint:s.endpoint,model:s.model,taskType:s.taskType,prompt:s.prompt?kr(s.prompt):void 0,requestBody:s.requestBody,hasReferenceImages:s.hasReferenceImages,referenceImageCount:s.referenceImageCount,status:"pending",taskId:s.taskId,workflowId:s.workflowId};return te.unshift(t),te.length>_r&&te.pop(),is(t),ie&&ie({...t}),e}function Ir(s,e){const t=te.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?pt(e.resultText,1e3):void 0,t.responseBody=e.responseBody?pt(e.responseBody,2e3):void 0,cs(t),ie&&ie({...t}))}function Or(s,e){const t=te.find(o=>o.id===s);t&&(t.status="error",t.httpStatus=e.httpStatus,t.duration=e.duration,t.errorMessage=Pr(e.errorMessage),t.responseBody=e.responseBody?pt(e.responseBody,2e3):void 0,cs(t),ie&&ie({...t}))}function kr(s){return s.length<=200?s:s.substring(0,200)+"..."}function pt(s,e){return s.length<=e?s:s.substring(0,e)+"..."}function Pr(s){return s.length<=500?s:s.substring(0,500)+"..."}const I=Object.freeze(Object.defineProperty({__proto__:null,clearAllLLMApiLogs:Dr,completeLLMApiLog:Ir,failLLMApiLog:Or,findSuccessLogByTaskId:Rr,getAllLLMApiLogs:ls,setLLMApiLogBroadcast:Wr,startLLMApiLog:Lr},Symbol.toStringTag,{value:"Module"}));async function Mr(s,e,t,o,n,r,a){try{if(Ze(e)){mt(s,{success:!1,error:`Tool "${e}" requires main thread execution`,type:"error"},r,a);return}const i=await Ye(e,t,{geminiConfig:o,videoConfig:n,onProgress:()=>{}});mt(s,i,r,a)}catch(i){mt(s,{success:!1,error:i.message||"Tool execution failed",type:"error"},r)}}function mt(s,e,t,o){const n={type:"MCP_TOOL_RESULT",requestId:s,success:e.success,data:e.data,error:e.error,resultType:e.type};Pe(t,n)}const xr=Object.freeze(Object.defineProperty({__proto__:null,executeMCPTool:Mr},Symbol.toStringTag,{value:"Module"}))})();