hyper-scheduler 1.1.1 → 1.1.2

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.
@@ -407,9 +407,12 @@ class FloatingTrigger extends HTMLElement {
407
407
  __publicField(this, "_offsetX", 0);
408
408
  __publicField(this, "_offsetY", 0);
409
409
  __publicField(this, "_isCollapsed", false);
410
+ // 新增:收起状态
411
+ // 内部状态:保存展开时的位置
412
+ __publicField(this, "_savedX", 0);
413
+ __publicField(this, "_savedY", 0);
410
414
  this._shadow = this.attachShadow({ mode: "open" });
411
415
  }
412
- // 新增:收起状态
413
416
  static get observedAttributes() {
414
417
  return ["position", "bg-color", "text-color"];
415
418
  }
@@ -417,7 +420,9 @@ class FloatingTrigger extends HTMLElement {
417
420
  this.loadState();
418
421
  this.render();
419
422
  this.addEventListeners();
420
- this.applyPosition();
423
+ requestAnimationFrame(() => {
424
+ this.applyPosition();
425
+ });
421
426
  window.addEventListener("resize", this.onResize.bind(this));
422
427
  }
423
428
  disconnectedCallback() {
@@ -429,7 +434,9 @@ class FloatingTrigger extends HTMLElement {
429
434
  attributeChangedCallback(name, _oldVal, newVal) {
430
435
  if (name === "position") {
431
436
  this._position = newVal || "bottom-right";
432
- this.applyPosition();
437
+ if (!this.style.getPropertyValue("--hs-trigger-position-set")) {
438
+ this.resetPositionToDefault();
439
+ }
433
440
  } else if (name === "bg-color") {
434
441
  this._bgColor = newVal || "";
435
442
  this.updateStyles();
@@ -443,9 +450,11 @@ class FloatingTrigger extends HTMLElement {
443
450
  const savedPos = localStorage.getItem(STORAGE_KEY_POS);
444
451
  if (savedPos) {
445
452
  const { x, y } = JSON.parse(savedPos);
446
- this.style.setProperty("--hs-trigger-left", `${x}px`);
447
- this.style.setProperty("--hs-trigger-top", `${y}px`);
453
+ this._savedX = parseFloat(x);
454
+ this._savedY = parseFloat(y);
448
455
  this.style.setProperty("--hs-trigger-position-set", "true");
456
+ } else {
457
+ this.resetPositionToDefault();
449
458
  }
450
459
  const savedCollapsed = localStorage.getItem(STORAGE_KEY_COLLAPSED);
451
460
  if (savedCollapsed === "true") {
@@ -453,60 +462,45 @@ class FloatingTrigger extends HTMLElement {
453
462
  }
454
463
  } catch (e) {
455
464
  console.warn("[FloatingTrigger] Failed to load state:", e);
465
+ this.resetPositionToDefault();
456
466
  }
457
467
  }
468
+ resetPositionToDefault() {
469
+ const width = 48;
470
+ const height = 48;
471
+ const padding = 20;
472
+ if (this._position.includes("left")) this._savedX = padding;
473
+ else this._savedX = window.innerWidth - width - padding;
474
+ if (this._position.includes("top")) this._savedY = padding;
475
+ else this._savedY = window.innerHeight - height - padding;
476
+ }
458
477
  saveState() {
459
- const button = this._shadow.querySelector("button");
460
- if (!button) return;
478
+ localStorage.setItem(STORAGE_KEY_POS, JSON.stringify({ x: this._savedX, y: this._savedY }));
461
479
  localStorage.setItem(STORAGE_KEY_COLLAPSED, String(this._isCollapsed));
462
- if (!this._isCollapsed) {
463
- const rect = button.getBoundingClientRect();
464
- localStorage.setItem(STORAGE_KEY_POS, JSON.stringify({ x: rect.left, y: rect.top }));
465
- } else {
466
- try {
467
- const savedPos = localStorage.getItem(STORAGE_KEY_POS);
468
- if (savedPos) {
469
- const { x } = JSON.parse(savedPos);
470
- const rect = button.getBoundingClientRect();
471
- localStorage.setItem(STORAGE_KEY_POS, JSON.stringify({ x, y: rect.top }));
472
- }
473
- } catch (e) {
474
- }
475
- }
476
480
  }
477
481
  applyPosition() {
478
482
  const button = this._shadow.querySelector("button");
479
483
  if (!button) return;
480
- const maxX = window.innerWidth - button.offsetWidth;
481
- const maxY = window.innerHeight - button.offsetHeight;
484
+ const width = this._isCollapsed ? 24 : 48;
485
+ const height = 48;
486
+ const maxX = window.innerWidth - width;
487
+ const maxY = window.innerHeight - height;
488
+ let targetX, targetY;
482
489
  if (this._isCollapsed) {
483
- let currentY = parseFloat(this.style.getPropertyValue("--hs-trigger-top") || "20");
484
- currentY = Math.max(0, Math.min(currentY, maxY));
485
- button.style.right = "0px";
486
- button.style.left = "auto";
487
- button.style.top = `${currentY}px`;
488
- button.style.bottom = "auto";
489
- this.style.setProperty("--hs-trigger-top", `${currentY}px`);
490
+ targetX = maxX;
491
+ targetY = Math.max(0, Math.min(this._savedY, maxY));
490
492
  } else {
491
- if (!this.style.getPropertyValue("--hs-trigger-position-set")) {
492
- const pos = this._position;
493
- button.style.top = pos.includes("top") ? "20px" : "auto";
494
- button.style.bottom = pos.includes("bottom") ? "20px" : "auto";
495
- button.style.left = pos.includes("left") ? "20px" : "auto";
496
- button.style.right = pos.includes("right") ? "20px" : "auto";
497
- } else {
498
- let currentX = parseFloat(this.style.getPropertyValue("--hs-trigger-left") || "0");
499
- let currentY = parseFloat(this.style.getPropertyValue("--hs-trigger-top") || "0");
500
- currentX = Math.max(0, Math.min(currentX, maxX));
501
- currentY = Math.max(0, Math.min(currentY, maxY));
502
- this.style.setProperty("--hs-trigger-left", `${currentX}px`);
503
- this.style.setProperty("--hs-trigger-top", `${currentY}px`);
504
- button.style.left = `${currentX}px`;
505
- button.style.top = `${currentY}px`;
506
- button.style.right = "auto";
507
- button.style.bottom = "auto";
493
+ targetX = Math.max(0, Math.min(this._savedX, maxX));
494
+ targetY = Math.max(0, Math.min(this._savedY, maxY));
495
+ if (targetX !== this._savedX || targetY !== this._savedY) {
496
+ this._savedX = targetX;
497
+ this._savedY = targetY;
508
498
  }
509
499
  }
500
+ button.style.left = `${targetX}px`;
501
+ button.style.top = `${targetY}px`;
502
+ this.style.setProperty("--hs-trigger-left", `${targetX}px`);
503
+ this.style.setProperty("--hs-trigger-top", `${targetY}px`);
510
504
  this.updateCollapsedState();
511
505
  }
512
506
  updateStyles() {
@@ -564,38 +558,38 @@ class FloatingTrigger extends HTMLElement {
564
558
  if (e.target.closest(".collapse-btn")) return;
565
559
  this._isDragging = true;
566
560
  this._wasDragging = false;
567
- this._offsetX = e.clientX - btn.getBoundingClientRect().left;
568
- this._offsetY = e.clientY - btn.getBoundingClientRect().top;
561
+ const rect = btn.getBoundingClientRect();
562
+ this._offsetX = e.clientX - rect.left;
563
+ this._offsetY = e.clientY - rect.top;
569
564
  const startX = e.clientX;
570
565
  const startY = e.clientY;
571
566
  let hasMoved = false;
567
+ btn.style.transition = "none";
572
568
  const onMouseMove = (moveEvent) => {
573
569
  if (!this._isDragging) return;
574
570
  if (!hasMoved && (Math.abs(moveEvent.clientX - startX) > 2 || Math.abs(moveEvent.clientY - startY) > 2)) {
575
571
  hasMoved = true;
576
572
  this._wasDragging = true;
577
573
  btn.style.cursor = "grabbing";
578
- btn.style.transition = "none";
579
574
  }
580
575
  if (hasMoved) {
581
576
  let newX = moveEvent.clientX - this._offsetX;
582
577
  let newY = moveEvent.clientY - this._offsetY;
583
- const maxX = window.innerWidth - btn.offsetWidth;
584
- const maxY = window.innerHeight - btn.offsetHeight;
578
+ const width = this._isCollapsed ? 24 : 48;
579
+ const height = 48;
580
+ const maxX = window.innerWidth - width;
581
+ const maxY = window.innerHeight - height;
585
582
  newX = Math.max(0, Math.min(newX, maxX));
586
583
  newY = Math.max(0, Math.min(newY, maxY));
587
584
  if (this._isCollapsed) {
588
- btn.style.left = "auto";
589
- btn.style.right = "0px";
585
+ newX = window.innerWidth - 24;
586
+ this._savedY = newY;
590
587
  } else {
591
- btn.style.left = `${newX}px`;
592
- btn.style.right = "auto";
593
- this.style.setProperty("--hs-trigger-left", `${newX}px`);
588
+ this._savedX = newX;
589
+ this._savedY = newY;
594
590
  }
591
+ btn.style.left = `${newX}px`;
595
592
  btn.style.top = `${newY}px`;
596
- btn.style.bottom = "auto";
597
- this.style.setProperty("--hs-trigger-position-set", "true");
598
- this.style.setProperty("--hs-trigger-top", `${newY}px`);
599
593
  }
600
594
  };
601
595
  const onMouseUp = () => {
@@ -620,11 +614,9 @@ class FloatingTrigger extends HTMLElement {
620
614
  }
621
615
  render() {
622
616
  const posStyles = `
623
- top: var(--hs-trigger-top, ${this._position.includes("top") ? "20px" : "auto"});
624
- bottom: var(--hs-trigger-bottom, ${this._position.includes("bottom") ? "20px" : "auto"});
625
- left: var(--hs-trigger-left, ${this._position.includes("left") ? "20px" : "auto"});
626
- right: var(--hs-trigger-right, ${this._position.includes("right") ? "20px" : "auto"});
627
- transform: translateX(0);
617
+ left: 0;
618
+ top: 0;
619
+ transform: translateZ(0); /* 开启硬件加速 */
628
620
  `;
629
621
  const bgStyle = this._bgColor ? `background: ${this._bgColor};` : "";
630
622
  const colorStyle = this._textColor ? `color: ${this._textColor};` : "";
@@ -636,21 +628,27 @@ class FloatingTrigger extends HTMLElement {
636
628
  ${posStyles}
637
629
  width: 48px;
638
630
  height: 48px;
639
- border-radius: 12px; /* 更现代的圆角 */
631
+ border-radius: 12px;
640
632
  background: var(--hs-primary);
641
633
  color: white;
642
634
  ${bgStyle}
643
635
  ${colorStyle}
644
636
  border: none;
645
- box-shadow: 0 4px 12px rgba(0,0,0,0.15); /* 更柔和的阴影 */
637
+ box-shadow: 0 4px 12px rgba(0,0,0,0.15);
646
638
  cursor: pointer;
647
639
  display: flex;
648
640
  align-items: center;
649
641
  justify-content: center;
650
642
  font-family: var(--hs-font-family);
651
643
  z-index: var(--hs-z-index);
652
- transition: transform 0.3s cubic-bezier(0.25, 0.8, 0.25, 1), background 0.2s, box-shadow 0.2s;
653
- overflow: visible; /* 允许子元素(收起按钮)溢出或显示 */
644
+ /* 添加平滑过渡动画 */
645
+ transition: width 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),
646
+ left 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),
647
+ top 0.3s cubic-bezier(0.25, 0.8, 0.25, 1),
648
+ border-radius 0.3s,
649
+ background 0.2s,
650
+ box-shadow 0.2s;
651
+ overflow: visible;
654
652
  }
655
653
  .icon {
656
654
  transition: transform 0.2s;
@@ -679,13 +677,14 @@ class FloatingTrigger extends HTMLElement {
679
677
  display: flex;
680
678
  align-items: center;
681
679
  justify-content: center;
682
- opacity: 1; /* 默认可见 */
680
+ opacity: 1;
683
681
  transition: opacity 0.2s, background 0.2s;
684
682
  color: white;
685
683
  font-weight: bold;
684
+ z-index: 2;
686
685
  }
687
686
  .collapse-btn::before {
688
- content: '—'; /* 最小化图标 */
687
+ content: '—';
689
688
  font-size: 12px;
690
689
  color: currentColor;
691
690
  }
@@ -701,27 +700,24 @@ class FloatingTrigger extends HTMLElement {
701
700
  width: 24px;
702
701
  height: 48px;
703
702
  border-radius: 12px 0 0 12px;
704
- transform: none; /* 完全展示,不再隐藏 */
705
- opacity: 1;
706
- right: 0 !important; /* 强制右对齐 */
707
- left: auto !important;
703
+ /* 不再强制 left/right,由 JS 控制 left 实现动画 */
708
704
  }
709
705
  button.collapsed:hover {
710
- width: 28px; /* hover 时稍微变宽 */
711
- opacity: 1;
706
+ width: 28px;
712
707
  }
708
+
713
709
  button.collapsed .icon {
714
710
  display: none;
715
711
  }
716
712
  button.collapsed .collapse-btn {
717
- position: static; /* 充满父容器 */
713
+ position: static;
718
714
  width: 100%;
719
715
  height: 100%;
720
716
  border-radius: 0;
721
717
  background: transparent;
722
718
  }
723
719
  button.collapsed .collapse-btn::before {
724
- content: '‹'; /* 展开图标 (左箭头) */
720
+ content: '‹';
725
721
  font-size: 20px;
726
722
  line-height: 48px;
727
723
  }
@@ -731,9 +727,6 @@ class FloatingTrigger extends HTMLElement {
731
727
  <span class="icon">${ICONS.chart}</span>
732
728
  </button>
733
729
  `;
734
- this.applyPosition();
735
- this.updateCollapsedState();
736
- this.updateStyles();
737
730
  }
738
731
  }
739
732
  customElements.define("hs-floating-trigger", FloatingTrigger);
@@ -0,0 +1 @@
1
+ "use strict";var t=Object.defineProperty,e=(e,s,n)=>((e,s,n)=>s in e?t(e,s,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[s]=n)(e,"symbol"!=typeof s?s+"":s,n);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s=require("./index.cjs"),n={header:{title:"DevTools",searchPlaceholder:"Search IDs/Tags... 🔍",toggleDock:"Toggle Dock Position",toggleTheme:"Toggle Theme",close:"Close"},stats:{loading:"Loading...",fps:"FPS",status:"Status",active:"Active",total:"Total",mainThread:"Main Thread",scheduler:"Scheduler",running:"Running",stopped:"Stopped"},tabs:{tasks:"Tasks List",timeline:"Timeline"},list:{idTags:"ID / Tags",status:"Status",driver:"Driver",driverWorker:"Worker (Web Worker)",driverMain:"Main (setTimeout)",schedule:"Schedule",count:"Count",lastRun:"Last Run",actions:"Actions",noTags:"(No Tags)",tip:"✨ Tip: Click a row for details & history."},detail:{back:"Back",details:"Task Details",config:"Config",history:"Execution History",lastRuns:"Last {n} runs",avgDuration:"Avg Duration",startTime:"Start Time",duration:"Duration",drift:"Drift",status:"Status",noHistory:"No execution history",noTask:"No task selected",success:"Success",failed:"Failed",error:"Error"},timeline:{zoom:"Zoom",timeRange:"Time Range: Last {n}s",legend:"Legend",instant:"Instant",duration:"Duration",workerDriver:"Worker Driver",mainDriver:"Main Driver"},status:{running:"Running",paused:"Paused",stopped:"Stopped",idle:"Scheduled",error:"Error"},actions:{trigger:"Trigger now",start:"Start task",stop:"Stop task",remove:"Remove task"}},i={header:{title:"调试工具",searchPlaceholder:"搜索 ID/标签... 🔍",toggleDock:"切换停靠位置",toggleTheme:"切换主题",close:"关闭"},stats:{loading:"加载中...",fps:"帧率",status:"状态",active:"活跃",total:"总数",mainThread:"主线程",scheduler:"调度器",running:"运行中",stopped:"已停止"},tabs:{tasks:"任务列表",timeline:"时间线"},list:{idTags:"ID / 标签",status:"状态",driver:"驱动",driverWorker:"Worker (Web Worker)",driverMain:"主线程 (setTimeout)",schedule:"调度规则",count:"次数",lastRun:"最后运行",actions:"操作",noTags:"(无标签)",tip:"✨ 提示: 点击行查看详情和历史记录。"},detail:{back:"返回",details:"任务详情",config:"配置",history:"执行历史",lastRuns:"最近 {n} 次运行",avgDuration:"平均耗时",startTime:"开始时间",duration:"耗时",drift:"偏差",status:"状态",noHistory:"暂无执行历史",noTask:"未选择任务",success:"成功",failed:"失败",error:"错误"},timeline:{zoom:"缩放",timeRange:"时间范围: 最近 {n}秒",legend:"图例",instant:"瞬间",duration:"耗时",workerDriver:"Worker 驱动",mainDriver:"主线程 驱动"},status:{running:"执行中",paused:"已暂停",stopped:"已停止",idle:"调度中",error:"错误"},actions:{trigger:"立即触发",start:"启动任务",stop:"停止任务",remove:"删除任务"}};let o=n;function a(t){o="zh"===t?i:n}function r(t,e){const s=t.split(".");let n=o;for(const i of s){if(!n||"object"!=typeof n||!(i in n))return t;n=n[i]}return"string"!=typeof n?t:e?n.replace(/\{(\w+)\}/g,(t,s)=>void 0!==e[s]?String(e[s]):`{${s}}`):n}class h{constructor(){e(this,"state"),e(this,"listeners"),e(this,"scheduler"),this.state={isOpen:!1,activeTab:"tasks",theme:"auto",dockPosition:"right",panelSize:{width:500,height:500},language:"en",filterText:"",selectedTaskId:null,tasks:new Map,history:new Map,fps:0,schedulerRunning:!1},this.listeners=new Map}setScheduler(t){this.scheduler=t}getState(){return this.state}subscribe(t,e){return this.listeners.has(t)||this.listeners.set(t,new Set),this.listeners.get(t).add(e),()=>{var s;null==(s=this.listeners.get(t))||s.delete(e)}}notify(t,e){var s;null==(s=this.listeners.get(t))||s.forEach(t=>t(e))}toggle(){this.state.isOpen=!this.state.isOpen,this.notify("isOpen",this.state.isOpen)}setTheme(t){this.state.theme=t,this.notify("theme",this.state.theme)}setLanguageSync(t){a(t),this.state.language=t}setLanguage(t){a(t),this.state.language=t,this.notify("language",this.state.language)}setPanelSize(t){this.state.panelSize={...this.state.panelSize,...t};try{localStorage.setItem("hs-panel-size",JSON.stringify(this.state.panelSize))}catch(e){}this.notify("panelSize",this.state.panelSize)}setTab(t){this.state.activeTab=t,this.notify("activeTab",this.state.activeTab)}setDockPosition(t){this.state.dockPosition=t,this.notify("dockPosition",this.state.dockPosition)}setFilterText(t){this.state.filterText=t,this.notify("filterText",this.state.filterText)}updateTask(t){const e=new Map(this.state.tasks);if(e.set(t.id,t),this.state.tasks=e,this.notify("tasks",this.state.tasks),"history"in t&&Array.isArray(t.history)){const e=new Map(this.state.history);e.set(t.id,t.history),this.state.history=e,this.notify("history",this.state.history)}}selectTask(t){this.state.selectedTaskId=t,this.notify("selectedTaskId",t)}addHistory(t,e){const s=[...this.state.history.get(t)||[]];s.push(e),s.length>50&&s.splice(0,s.length-50);const n=new Map(this.state.history);n.set(t,s),this.state.history=n,this.notify("history",n)}async triggerTask(t){this.scheduler&&await this.scheduler.trigger(t)}stopTask(t){console.log("[DevToolsStore] stopTask:",t),this.scheduler&&this.scheduler.pause(t)}startTask(t){console.log("[DevToolsStore] startTask:",t),this.scheduler&&this.scheduler.resume(t)}removeTask(t){if(this.scheduler){this.scheduler.remove(t);const e=new Map(this.state.tasks);e.delete(t),this.state.tasks=e,this.notify("tasks",this.state.tasks)}}setSchedulerRunning(t){this.state.schedulerRunning=t,this.notify("schedulerRunning",t)}}const l='\n :host {\n --hs-font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;\n --hs-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;\n --hs-font-size: 12px;\n --hs-line-height: 1.5;\n --hs-panel-width: 400px;\n --hs-panel-height: 300px;\n \n /* 等宽数字字体 */\n --hs-font-monospaced-num: var(--hs-font-mono);\n\n /* Light Theme (Default) */\n --hs-bg: #ffffff;\n --hs-bg-secondary: #f3f4f6;\n --hs-text: #1f2937;\n --hs-text-secondary: #6b7280;\n --hs-border: #e5e7eb;\n --hs-primary: #3b82f6;\n --hs-primary-hover: #2563eb;\n --hs-danger: #ef4444;\n --hs-danger-hover: #dc2626;\n --hs-success: #10b981;\n --hs-warning: #f59e0b;\n \n --hs-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);\n --hs-radius: 6px;\n --hs-header-height: 40px;\n --hs-z-index: 9999;\n --hs-z-index-overlay: 9998;\n\n /* Default display styles for the host itself */\n background: var(--hs-bg);\n color: var(--hs-text);\n font-family: var(--hs-font-family);\n font-size: var(--hs-font-size);\n line-height: var(--hs-line-height);\n }\n\n :host([theme="dark"]) {\n --hs-bg: #111827;\n --hs-bg-secondary: #1f2937;\n --hs-text: #f9fafb;\n --hs-text-secondary: #9ca3af;\n --hs-border: #374151;\n --hs-primary: #60a5fa;\n --hs-primary-hover: #3b82f6;\n --hs-danger: #f87171;\n --hs-danger-hover: #ef4444;\n --hs-success: #34d399;\n --hs-warning: #fbbf24;\n \n --hs-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.5), 0 2px 4px -1px rgba(0, 0, 0, 0.3);\n }\n\n :host {\n background: var(--hs-bg);\n color: var(--hs-text);\n }\n',d={back:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="19" y1="12" x2="5" y2="12"></line><polyline points="12 19 5 12 12 5"></polyline></svg>',trigger:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="13 2 3 14 12 14 11 22 21 10 12 10 13 2"></polygon></svg>',pause:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="6" y="4" width="4" height="16"></rect><rect x="14" y="4" width="4" height="16"></rect></svg>',resume:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polygon points="5 3 19 12 5 21 5 3"></polygon></svg>',remove:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"></polyline><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"></path></svg>',close:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"></line><line x1="6" y1="6" x2="18" y2="18"></line></svg>',sun:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="5"></circle><line x1="12" y1="1" x2="12" y2="3"></line><line x1="12" y1="21" x2="12" y2="23"></line><line x1="4.22" y1="4.22" x2="5.64" y2="5.64"></line><line x1="18.36" y1="18.36" x2="19.78" y2="19.78"></line><line x1="1" y1="12" x2="3" y2="12"></line><line x1="21" y1="12" x2="23" y2="12"></line><line x1="4.22" y1="19.78" x2="5.64" y2="18.36"></line><line x1="18.36" y1="5.64" x2="19.78" y2="4.22"></line></svg>',moon:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"></path></svg>',dock:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="18" rx="2" ry="2"></rect><line x1="2" y1="15" x2="22" y2="15"></line></svg>',dockRight:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="2" y="3" width="20" height="18" rx="2" ry="2"></rect><line x1="15" y1="3" x2="15" y2="21"></line></svg>',chart:'<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="20" x2="18" y2="10"></line><line x1="12" y1="20" x2="12" y2="4"></line><line x1="6" y1="20" x2="6" y2="14"></line></svg>'},c="hs-trigger-position",p="hs-trigger-collapsed";class g extends HTMLElement{constructor(){super(),e(this,"_shadow"),e(this,"_position","bottom-right"),e(this,"_bgColor",""),e(this,"_textColor",""),e(this,"_isDragging",!1),e(this,"_wasDragging",!1),e(this,"_offsetX",0),e(this,"_offsetY",0),e(this,"_isCollapsed",!1),e(this,"_savedX",0),e(this,"_savedY",0),this._shadow=this.attachShadow({mode:"open"})}static get observedAttributes(){return["position","bg-color","text-color"]}connectedCallback(){this.loadState(),this.render(),this.addEventListeners(),requestAnimationFrame(()=>{this.applyPosition()}),window.addEventListener("resize",this.onResize.bind(this))}disconnectedCallback(){window.removeEventListener("resize",this.onResize.bind(this))}onResize(){this.applyPosition()}attributeChangedCallback(t,e,s){"position"===t?(this._position=s||"bottom-right",this.style.getPropertyValue("--hs-trigger-position-set")||this.resetPositionToDefault()):"bg-color"===t?(this._bgColor=s||"",this.updateStyles()):"text-color"===t&&(this._textColor=s||"",this.updateStyles())}loadState(){try{const t=localStorage.getItem(c);if(t){const{x:e,y:s}=JSON.parse(t);this._savedX=parseFloat(e),this._savedY=parseFloat(s),this.style.setProperty("--hs-trigger-position-set","true")}else this.resetPositionToDefault();"true"===localStorage.getItem(p)&&(this._isCollapsed=!0)}catch(t){console.warn("[FloatingTrigger] Failed to load state:",t),this.resetPositionToDefault()}}resetPositionToDefault(){this._position.includes("left")?this._savedX=20:this._savedX=window.innerWidth-48-20,this._position.includes("top")?this._savedY=20:this._savedY=window.innerHeight-48-20}saveState(){localStorage.setItem(c,JSON.stringify({x:this._savedX,y:this._savedY})),localStorage.setItem(p,String(this._isCollapsed))}applyPosition(){const t=this._shadow.querySelector("button");if(!t)return;const e=this._isCollapsed?24:48,s=window.innerWidth-e,n=window.innerHeight-48;let i,o;this._isCollapsed?(i=s,o=Math.max(0,Math.min(this._savedY,n))):(i=Math.max(0,Math.min(this._savedX,s)),o=Math.max(0,Math.min(this._savedY,n)),i===this._savedX&&o===this._savedY||(this._savedX=i,this._savedY=o)),t.style.left=`${i}px`,t.style.top=`${o}px`,this.style.setProperty("--hs-trigger-left",`${i}px`),this.style.setProperty("--hs-trigger-top",`${o}px`),this.updateCollapsedState()}updateStyles(){const t=this._shadow.querySelector("button");t&&(t.style.background=this._bgColor||"var(--hs-primary)",t.style.color=this._textColor||"white",this._bgColor?t.style.setProperty("--hs-trigger-bg-hover",`${this._bgColor}; filter: brightness(1.1);`):t.style.removeProperty("--hs-trigger-bg-hover"))}updateCollapsedState(){const t=this._shadow.querySelector("button");t&&(this._isCollapsed?t.classList.add("collapsed"):t.classList.remove("collapsed"))}addEventListeners(){const t=this._shadow.querySelector("button");if(!t)return;t.addEventListener("click",t=>{if(this._wasDragging)return t.preventDefault(),t.stopPropagation(),void(this._wasDragging=!1);this.dispatchEvent(new CustomEvent("toggle",{bubbles:!0,composed:!0}))});const e=this._shadow.querySelector(".collapse-btn");null==e||e.addEventListener("click",t=>{t.stopPropagation(),t.preventDefault(),this._isCollapsed=!this._isCollapsed,this.applyPosition(),this.saveState()}),t.addEventListener("dblclick",t=>{this._isCollapsed&&(t.stopPropagation(),this._isCollapsed=!1,this.applyPosition(),this.saveState())}),t.addEventListener("mousedown",e=>{if(0!==e.button)return;if(e.target.closest(".collapse-btn"))return;this._isDragging=!0,this._wasDragging=!1;const s=t.getBoundingClientRect();this._offsetX=e.clientX-s.left,this._offsetY=e.clientY-s.top;const n=e.clientX,i=e.clientY;let o=!1;t.style.transition="none";const a=e=>{if(this._isDragging&&(!o&&(Math.abs(e.clientX-n)>2||Math.abs(e.clientY-i)>2)&&(o=!0,this._wasDragging=!0,t.style.cursor="grabbing"),o)){let s=e.clientX-this._offsetX,n=e.clientY-this._offsetY;const i=this._isCollapsed?24:48,o=48,a=window.innerWidth-i,r=window.innerHeight-o;s=Math.max(0,Math.min(s,a)),n=Math.max(0,Math.min(n,r)),this._isCollapsed?(s=window.innerWidth-24,this._savedY=n):(this._savedX=s,this._savedY=n),t.style.left=`${s}px`,t.style.top=`${n}px`}},r=()=>{if(this._isDragging){if(this._isDragging=!1,t.style.cursor="pointer",t.style.transition="",o){this.saveState();const t=t=>{t.stopPropagation(),t.preventDefault()};window.addEventListener("click",t,{capture:!0,once:!0})}window.removeEventListener("mousemove",a),window.removeEventListener("mouseup",r)}};window.addEventListener("mousemove",a),window.addEventListener("mouseup",r)})}render(){const t=this._bgColor?`background: ${this._bgColor};`:"",e=this._textColor?`color: ${this._textColor};`:"";this._shadow.innerHTML=`\n <style>\n ${l}\n button {\n position: fixed;\n \n left: 0;\n top: 0;\n transform: translateZ(0); /* 开启硬件加速 */\n \n width: 48px;\n height: 48px;\n border-radius: 12px;\n background: var(--hs-primary);\n color: white;\n ${t}\n ${e}\n border: none;\n box-shadow: 0 4px 12px rgba(0,0,0,0.15);\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n font-family: var(--hs-font-family);\n z-index: var(--hs-z-index);\n /* 添加平滑过渡动画 */\n transition: width 0.3s cubic-bezier(0.25, 0.8, 0.25, 1), \n left 0.3s cubic-bezier(0.25, 0.8, 0.25, 1), \n top 0.3s cubic-bezier(0.25, 0.8, 0.25, 1), \n border-radius 0.3s,\n background 0.2s, \n box-shadow 0.2s;\n overflow: visible;\n }\n .icon {\n transition: transform 0.2s;\n display: flex;\n }\n button:hover {\n ${this._bgColor?`background: ${this._bgColor}; filter: brightness(1.1);`:"background: var(--hs-primary-hover);"}\n box-shadow: 0 6px 16px rgba(0,0,0,0.2);\n }\n button:hover .icon {\n transform: scale(1.1);\n }\n button:active .icon {\n transform: scale(0.95);\n }\n\n /* 显式收起按钮 */\n .collapse-btn {\n position: absolute;\n top: 0;\n right: 0;\n width: 20px;\n height: 20px;\n background: rgba(0,0,0,0.1);\n border-top-right-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n opacity: 1; \n transition: opacity 0.2s, background 0.2s;\n color: white;\n font-weight: bold;\n z-index: 2;\n }\n .collapse-btn::before {\n content: '—'; \n font-size: 12px;\n color: currentColor;\n }\n button:hover .collapse-btn {\n opacity: 1;\n }\n .collapse-btn:hover {\n background: rgba(0,0,0,0.3);\n }\n\n /* 收起状态样式 */\n button.collapsed {\n width: 24px;\n height: 48px;\n border-radius: 12px 0 0 12px;\n /* 不再强制 left/right,由 JS 控制 left 实现动画 */\n }\n button.collapsed:hover {\n width: 28px; \n }\n \n button.collapsed .icon {\n display: none;\n }\n button.collapsed .collapse-btn {\n position: static;\n width: 100%;\n height: 100%;\n border-radius: 0;\n background: transparent;\n }\n button.collapsed .collapse-btn::before {\n content: '‹'; \n font-size: 20px;\n line-height: 48px;\n }\n </style>\n <button title="Toggle Hyper Scheduler DevTools">\n <div class="collapse-btn" title="Minimize"></div>\n <span class="icon">${d.chart}</span>\n </button>\n `}}customElements.define("hs-floating-trigger",g);class u extends HTMLElement{constructor(){super(),e(this,"_shadow"),e(this,"_fps",0),e(this,"_stats",{active:0,total:0}),e(this,"_theme","auto"),e(this,"_activeTab","tasks"),e(this,"_language","en"),e(this,"_schedulerRunning",!1),e(this,"$fps"),e(this,"$stats"),e(this,"$schedulerStatus"),e(this,"$themeIcon"),e(this,"$dockIcon"),e(this,"$tabs"),e(this,"$searchInput"),e(this,"$title"),e(this,"$langBtn"),this._shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this.cacheDom(),this.addEventListeners(),this.updateView()}set fps(t){if(this._fps=Math.round(t),this.$fps){const t=this._fps<30?"var(--hs-danger)":this._fps<50?"var(--hs-warning)":"var(--hs-success)";this.$fps.innerHTML=`⚡ ${r("stats.fps")}: <span style="color:${t}; font-family:var(--hs-font-monospaced-num);">${this._fps}</span> (${r("stats.mainThread")})`}}set stats(t){this._stats=t,this.$stats&&(this.$stats.innerHTML=`📊 ${r("stats.status")}: <span style="color:var(--hs-success)">🟢 ${r("stats.active")}: ${t.active}</span> <span style="margin-left:12px;color:var(--hs-text-secondary)">⚪ ${r("stats.total")}: ${t.total}</span>`)}set schedulerRunning(t){if(this._schedulerRunning=t,this.$schedulerStatus){const e=r(t?"stats.running":"stats.stopped"),s=t?"var(--hs-success)":"var(--hs-danger)",n=t?"▶️":"⏹️";this.$schedulerStatus.innerHTML=`${n} ${r("stats.scheduler")}: <span style="color:${s}">${e}</span>`}}set theme(t){this._theme=t,this.setAttribute("theme",t),this.updateThemeIcon()}set language(t){this._language=t,this.updateTexts()}set dockPosition(t){var e;this.$dockIcon&&(this.$dockIcon.innerHTML="right"===t?d.dock:d.dockRight,null==(e=this.$dockIcon.parentElement)||e.setAttribute("title",r("header.toggleDock")))}set activeTab(t){this._activeTab=t,this.updateTabs()}cacheDom(){this.$fps=this._shadow.querySelector(".fps"),this.$stats=this._shadow.querySelector(".stats"),this.$schedulerStatus=this._shadow.querySelector(".scheduler-status"),this.$themeIcon=this._shadow.querySelector(".theme-btn span"),this.$dockIcon=this._shadow.querySelector(".dock-btn"),this.$tabs=this._shadow.querySelectorAll(".tab"),this.$searchInput=this._shadow.querySelector(".search-input"),this.$title=this._shadow.querySelector(".title"),this.$langBtn=this._shadow.querySelector(".lang-btn")}addEventListeners(){var t,e,s,n,i;null==(t=this._shadow.querySelector(".dock-btn"))||t.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("dock-toggle"))}),null==(e=this._shadow.querySelector(".theme-btn"))||e.addEventListener("click",()=>{const t="dark"===this._theme?"light":"dark";this.dispatchEvent(new CustomEvent("theme-toggle",{detail:t}))}),null==(s=this._shadow.querySelector(".lang-btn"))||s.addEventListener("click",()=>{const t="en"===this._language?"zh":"en";this.dispatchEvent(new CustomEvent("lang-toggle",{detail:t}))}),null==(n=this._shadow.querySelector(".close-btn"))||n.addEventListener("click",()=>{this.dispatchEvent(new CustomEvent("close"))}),this.$tabs.forEach(t=>{t.addEventListener("click",t=>{const e=t.currentTarget.dataset.tab;this.dispatchEvent(new CustomEvent("tab-change",{detail:e}))})}),null==(i=this.$searchInput)||i.addEventListener("input",t=>{const e=t.target.value;this.dispatchEvent(new CustomEvent("search",{detail:e}))})}updateThemeIcon(){this.$themeIcon&&(this.$themeIcon.innerHTML="dark"===this._theme?d.moon:d.sun)}updateTabs(){this.$tabs.forEach(t=>{t.dataset.tab===this._activeTab?t.classList.add("active"):t.classList.remove("active")})}updateTexts(){this.$title&&(this.$title.innerHTML=`🕒 ${r("header.title")}`),this.$searchInput&&(this.$searchInput.placeholder=r("header.searchPlaceholder")),this.$langBtn&&(this.$langBtn.textContent="en"===this._language?"中":"EN"),this.$tabs.forEach(t=>{const e=t.dataset.tab;"tasks"===e&&(t.innerHTML=`📌 ${r("tabs.tasks")}`),"timeline"===e&&(t.innerHTML=`📈 ${r("tabs.timeline")}`)}),this.stats=this._stats,this.fps=this._fps,this.schedulerRunning=this._schedulerRunning}updateView(){this.updateThemeIcon(),this.updateTabs(),this.updateTexts()}render(){this._shadow.innerHTML=`\n <style>\n ${l}\n :host {\n display: block;\n background: var(--hs-bg);\n border-bottom: 1px solid var(--hs-border);\n padding: 0 16px;\n height: var(--hs-header-height);\n height: auto; \n }\n .top-bar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n height: 40px;\n border-bottom: 1px solid var(--hs-border);\n }\n .title {\n font-weight: 600;\n font-size: 13px;\n color: var(--hs-text);\n display: flex;\n align-items: center;\n gap: 6px;\n }\n .search-box {\n flex: 1;\n max-width: 300px;\n margin: 0px 32px 0 16px;\n }\n .search-input {\n width: 100%;\n background: var(--hs-bg-secondary);\n border: 1px solid var(--hs-border);\n color: var(--hs-text);\n padding: 6px 12px;\n border-radius: 4px;\n font-size: 12px;\n }\n .search-input::placeholder {\n color: var(--hs-text-secondary);\n }\n .controls {\n display: flex;\n align-items: center;\n gap: 4px;\n }\n button {\n background: transparent;\n border: none;\n color: var(--hs-text-secondary);\n cursor: pointer;\n padding: 4px;\n border-radius: 4px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: 12px;\n width: 28px;\n height: 28px;\n }\n .theme-btn span {\n margin-top: 4px;\n }\n button:hover {\n background: var(--hs-bg-secondary);\n color: var(--hs-text);\n }\n button svg {\n width: 16px;\n height: 16px;\n }\n .lang-btn {\n font-weight: 600;\n }\n .stats-bar {\n display: flex;\n justify-content: space-between;\n align-items: center;\n height: 30px;\n font-size: 11px;\n color: var(--hs-text-secondary);\n border-bottom: 1px solid var(--hs-border);\n gap: 16px;\n }\n .stats-left {\n display: flex;\n gap: 16px;\n }\n .tabs-bar {\n display: flex;\n height: 36px;\n gap: 0;\n }\n .tab {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 12px;\n color: var(--hs-text-secondary);\n cursor: pointer;\n border-bottom: 3px solid transparent;\n padding: 0 16px;\n transition: all 0.2s;\n }\n .tab:hover {\n color: var(--hs-text);\n background: var(--hs-bg-secondary);\n }\n .tab.active {\n color: var(--hs-text);\n font-weight: 600;\n border-bottom-color: var(--hs-primary);\n background: var(--hs-bg-secondary);\n }\n </style>\n \n <div class="top-bar">\n <div class="title"></div>\n <div class="search-box">\n <input type="text" class="search-input">\n </div>\n <div class="controls">\n <button class="lang-btn" title="Switch Language">EN</button>\n <button class="dock-btn" title="Toggle Dock">${d.dock}</button>\n <button class="theme-btn" title="Toggle Theme"><span>${d.sun}</span></button>\n <button class="close-btn" title="Close">${d.close}</button>\n </div>\n </div>\n \n <div class="stats-bar">\n <div class="stats-left">\n <div class="scheduler-status"></div>\n <div class="stats"></div>\n </div>\n <div class="fps"></div>\n </div>\n \n <div class="tabs-bar">\n <div class="tab active" data-tab="tasks"></div>\n <div class="tab" data-tab="timeline"></div>\n </div>\n `}}customElements.define("hs-task-header",u);class b extends HTMLElement{constructor(){super(),e(this,"_shadow"),e(this,"_tasks",[]),e(this,"_lastExecutionTimes",new Map),e(this,"_expandedNamespaces",new Set(["default"])),this._shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.render()}set tasks(t){const e=Array.from(t.values());e.forEach(t=>{const e=this._tasks.find(e=>e.id===t.id);e&&t.executionCount>e.executionCount&&this._lastExecutionTimes.set(t.id,Date.now())}),this._tasks=e,this.renderRows()}groupTasksByNamespace(t){const e=new Map;return t.forEach(t=>{const s=t.namespace||"default";e.has(s)||e.set(s,[]),e.get(s).push(t)}),e}filter(t,e){const s=Array.from(e.values());if(t){const e=t.toLowerCase();this._tasks=s.filter(t=>t.id.toLowerCase().includes(e)||t.tags.some(t=>t.toLowerCase().includes(e))||t.namespace&&t.namespace.toLowerCase().includes(e))}else this._tasks=s;this.renderRows()}updateHeaders(){const t=this._shadow.querySelector("thead");t&&(t.innerHTML=`\n <tr>\n <th style="width:40px">#</th>\n <th style="min-width:150px">${r("list.idTags")}</th>\n <th style="width:150px">${r("list.status")}</th>\n <th style="width:70px">${r("list.driver")}</th>\n <th style="width:100px">${r("list.schedule")}</th>\n <th style="width:60px">${r("list.count")}</th>\n <th style="width:100px">${r("list.lastRun")}</th>\n <th style="width:100px">${r("list.actions")}</th>\n </tr>\n `);const e=this._shadow.querySelector(".tip");e&&(e.textContent=r("list.tip")),this.renderRows()}getStatusIcon(t,e){const n=this._lastExecutionTimes.get(e),i=n&&Date.now()-n<1e3;switch(t){case s.TaskStatus.RUNNING:return`<span style="color:var(--hs-primary)">🔵</span> <strong>${r("status.running")}</strong>`;case s.TaskStatus.STOPPED:return`<span style="color:var(--hs-text-secondary)">⚪</span> ${r("status.stopped")}`;case s.TaskStatus.IDLE:return i?`<span class="status-flash" style="color:var(--hs-success)">🟢</span> ${r("status.idle")}`:`<span style="color:var(--hs-success)">🟢</span> ${r("status.idle")}`;case s.TaskStatus.ERROR:return`<span style="color:var(--hs-warning)">🟠</span> ${r("status.error")}`;default:return t}}formatSchedule(t){return"number"==typeof t?`${t}ms`:t&&(t.includes("*")||t.includes(" "))?t.length>15?t.substring(0,12)+"...":t:t||"-"}formatTime(t){if(!t)return"-";const e=new Date(t);return e.toLocaleTimeString("en-US",{hour12:!1,hour:"2-digit",minute:"2-digit",second:"2-digit"})+"."+e.getMilliseconds().toString().padStart(3,"0")}getDriverBadge(t){return"worker"===(t||"worker")?`<span class="driver-badge worker" title="${r("list.driverWorker")}">W</span>`:`<span class="driver-badge main" title="${r("list.driverMain")}">M</span>`}renderTaskRow(t,e,n=!1){const i=this._lastExecutionTimes.get(t.id),o=i&&Date.now()-i<1e3?"recently-executed":"",a=n?"nested-task":"";return`\n <tr data-id="${t.id}" class="${o} ${a}">\n <td class="col-num">\n ${n?"":e+1}\n </td>\n <td class="col-id">\n <div class="task-id">\n ${t.id}\n ${t.namespace&&"default"!==t.namespace&&!n?`<span class="namespace-badge" title="Namespace">${t.namespace}</span>`:""}\n </div>\n <div class="tags">\n ${t.tags&&t.tags.length>0?t.tags.map(t=>`<span class="tag">${t}</span>`).join(""):`<span class="no-tags">${r("list.noTags")}</span>`}\n </div>\n </td>\n <td>${this.getStatusIcon(t.status,t.id)}</td>\n <td>${this.getDriverBadge(t.driver)}</td>\n <td>${this.formatSchedule(t.schedule)}</td>\n <td>${t.executionCount||0}</td>\n <td>${this.formatTime(t.lastRun)}</td>\n <td class="col-actions">\n <div class="action-group">\n <button class="btn-icon" data-action="trigger" title="${r("actions.trigger")}" ${t.status===s.TaskStatus.RUNNING?"disabled":""}>${d.trigger}</button>\n ${t.status===s.TaskStatus.STOPPED||t.status===s.TaskStatus.ERROR?`<button class="btn-icon success" data-action="start" title="${r("actions.start")}">${d.resume}</button>`:`<button class="btn-icon warning" data-action="stop" title="${r("actions.stop")}" ${t.status===s.TaskStatus.RUNNING?"disabled":""}>${d.pause}</button>`}\n <button class="btn-icon danger" data-action="remove" title="${r("actions.remove")}">${d.remove}</button>\n </div>\n </td>\n </tr>\n `}renderRows(){const t=this._shadow.querySelector("tbody");if(!t)return;const e=this.groupTasksByNamespace(this._tasks);let s="",n=0;const i=e.get("default");i&&i.length>0&&(s+=i.map(t=>this.renderTaskRow(t,++n,!1)).join("")),e.delete("default");Array.from(e.keys()).sort((t,e)=>t.localeCompare(e)).forEach(t=>{const i=e.get(t),o=this._expandedNamespaces.has(t);s+=`\n <tr class="namespace-row ${o?"ns-expanded":""}" data-ns="${t}">\n <td colspan="8">\n <span class="ns-toggle">${o?"▼":"▶"}</span>\n <span class="ns-icon">📂</span>\n <span class="ns-name">${t}</span>\n <span class="ns-count">(${i.length})</span>\n </td>\n </tr>\n `,o&&(s+=i.map(t=>this.renderTaskRow(t,++n,!0)).join(""))}),t.innerHTML=s}render(){this._shadow.innerHTML=`\n <style>\n ${l}\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--hs-bg);\n }\n .table-container {\n flex: 1;\n min-height: 0;\n overflow-y: auto;\n overflow-x: auto;\n position: relative;\n }\n table {\n width: 100%;\n border-collapse: collapse;\n font-size: var(--hs-font-size);\n color: var(--hs-text);\n }\n thead {\n position: sticky;\n top: 0;\n z-index: 2;\n background: var(--hs-bg);\n }\n th {\n text-align: left;\n padding: 8px 12px;\n border-bottom: 2px solid var(--hs-border);\n color: var(--hs-text-secondary);\n font-weight: 600;\n background: var(--hs-bg);\n font-size: 11px;\n text-transform: uppercase;\n white-space: nowrap;\n }\n th:last-child {\n position: sticky;\n right: 0;\n background: var(--hs-bg);\n box-shadow: -2px 0 4px rgba(0,0,0,0.1);\n }\n td {\n padding: 8px 12px;\n border-bottom: 1px solid var(--hs-border);\n vertical-align: middle;\n }\n tr:hover {\n background: var(--hs-bg-secondary);\n cursor: pointer;\n }\n tr.recently-executed {\n animation: flash-row 1s ease-out;\n }\n @keyframes flash-row {\n 0% { background: rgba(34, 197, 94, 0.2); }\n 100% { background: transparent; }\n }\n .status-flash {\n animation: flash-icon 1s ease-out;\n }\n @keyframes flash-icon {\n 0%, 50% { opacity: 1; }\n 25%, 75% { opacity: 0.3; }\n }\n .tip {\n padding: 12px;\n text-align: center;\n font-size: 11px;\n color: var(--hs-text-secondary);\n border-top: 1px solid var(--hs-border);\n background: var(--hs-bg);\n }\n .task-id {\n font-weight: 600;\n }\n .namespace-badge {\n display: inline-block;\n background: var(--hs-bg-secondary);\n color: var(--hs-text-secondary);\n border: 1px solid var(--hs-border);\n border-radius: 4px;\n padding: 0 4px;\n font-size: 9px;\n margin-left: 6px;\n font-family: monospace;\n vertical-align: middle;\n }\n .tags {\n display: flex;\n gap: 4px;\n margin-top: 4px;\n }\n .tag {\n background: var(--hs-bg-secondary);\n border: 1px solid var(--hs-border);\n border-radius: 10px;\n padding: 2px 8px;\n font-size: 10px;\n color: var(--hs-text-secondary);\n }\n .no-tags {\n font-size: 10px;\n color: var(--hs-text-secondary);\n font-style: italic;\n }\n .driver-badge {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 22px;\n height: 22px;\n border-radius: 4px;\n font-size: 11px;\n font-weight: 600;\n font-family: monospace;\n }\n .driver-badge.worker {\n background: rgba(34, 197, 94, 0.15);\n color: var(--hs-success);\n border: 1px solid var(--hs-success);\n }\n .driver-badge.main {\n background: rgba(245, 158, 11, 0.15);\n color: var(--hs-warning);\n border: 1px solid var(--hs-warning);\n }\n .col-num {\n width: 40px;\n color: var(--hs-text-secondary);\n font-size: 11px;\n }\n .col-actions {\n width: 100px;\n position: sticky;\n right: 0;\n background: var(--hs-bg);\n box-shadow: -2px 0 4px rgba(0,0,0,0.1);\n }\n .action-group {\n display: flex;\n gap: 4px;\n }\n .btn-icon {\n background: transparent;\n border: 1px solid var(--hs-border);\n color: var(--hs-text-secondary);\n border-radius: 4px;\n width: 24px;\n height: 24px;\n display: flex;\n align-items: center;\n justify-content: center;\n cursor: pointer;\n padding: 0;\n flex-shrink: 0;\n }\n .btn-icon svg {\n width: 14px;\n height: 14px;\n display: block;\n }\n .btn-icon:hover {\n background: var(--hs-primary);\n color: white;\n border-color: var(--hs-primary);\n }\n .btn-trigger:hover {\n background: var(--hs-success);\n border-color: var(--hs-success);\n }\n .btn-pause:hover {\n background: var(--hs-warning);\n border-color: var(--hs-warning);\n }\n .btn-resume:hover {\n background: var(--hs-success);\n border-color: var(--hs-success);\n }\n .btn-remove:hover {\n color: white;\n background: var(--hs-danger);\n border-color: var(--hs-danger);\n }\n .btn-icon:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n }\n .btn-icon:disabled:hover {\n background: transparent;\n color: var(--hs-text-secondary);\n border-color: var(--hs-border);\n }\n /* Namespace Styles */\n .namespace-row {\n background: var(--hs-bg-secondary);\n cursor: pointer;\n font-weight: 600;\n user-select: none;\n }\n .namespace-row:hover {\n background: var(--hs-border);\n }\n .namespace-row td {\n padding: 8px 12px;\n border-bottom: 1px solid var(--hs-border);\n }\n .ns-toggle {\n display: inline-block;\n width: 20px;\n text-align: center;\n font-size: 10px;\n color: var(--hs-text-secondary);\n transition: transform 0.2s;\n }\n .ns-icon {\n margin-right: 4px;\n }\n .ns-count {\n font-weight: normal;\n color: var(--hs-text-secondary);\n font-size: 11px;\n margin-left: 4px;\n }\n .nested-task .col-id {\n padding-left: 32px !important;\n }\n </style>\n <div class="table-container">\n <table>\n <thead>\n <tr>\n <th style="width:40px">#</th>\n <th style="min-width:150px">${r("list.idTags")}</th>\n <th style="width:150px">${r("list.status")}</th>\n <th style="width:70px">${r("list.driver")}</th>\n <th style="width:100px">${r("list.schedule")}</th>\n <th style="width:60px">${r("list.count")}</th>\n <th style="width:100px">${r("list.lastRun")}</th>\n <th style="width:100px">${r("list.actions")}</th>\n </tr>\n </thead>\n <tbody>\n \x3c!-- Rows --\x3e\n </tbody>\n </table>\n </div>\n <div class="tip">\n ${r("list.tip")}\n </div>\n `,this._shadow.addEventListener("click",t=>{const e=t.target,s=e.closest(".namespace-row");if(s){const t=s.dataset.ns;return void(t&&(this._expandedNamespaces.has(t)?this._expandedNamespaces.delete(t):this._expandedNamespaces.add(t),this.renderRows()))}const n=e.closest("button");if(n){const t=n.dataset.action,e=n.closest("tr");if(!t||!e)return;const s=e.dataset.id;return void this.dispatchEvent(new CustomEvent("task-action",{detail:{action:t,id:s},bubbles:!0,composed:!0}))}const i=e.closest("tr");if(i&&!e.closest(".col-actions")&&!i.classList.contains("namespace-row")){const t=i.dataset.id;this.dispatchEvent(new CustomEvent("task-select",{detail:t,bubbles:!0,composed:!0}))}})}}customElements.define("hs-task-list",b);class v extends HTMLElement{constructor(){super(),e(this,"_shadow"),e(this,"_task",null),e(this,"_history",[]),this._shadow=this.attachShadow({mode:"open"})}connectedCallback(){this.render(),this._shadow.addEventListener("click",t=>{t.target.closest(".back-btn")&&this.dispatchEvent(new CustomEvent("back"))})}set task(t){this._task=t,this.renderContent()}set history(t){this._history=t||[],this.renderContent()}updateTexts(){this.renderContent()}renderContent(){const t=this._shadow.querySelector(".content");if(!t)return;if(!this._task)return void(t.innerHTML=`<div class="empty">${r("detail.noTask")}</div>`);const e=this._task,s={id:e.id,schedule:e.schedule,tags:e.tags},n=this._history.length>0?Math.round(this._history.reduce((t,e)=>t+e.duration,0)/this._history.length):0;t.innerHTML=`\n <div class="header">\n <button class="back-btn" title="${r("detail.back")}">${d.back}</button>\n <h2>📂 ${e.id}</h2>\n </div>\n \n <div class="section">\n <div class="config-label">${r("detail.config")}:</div>\n <pre>${JSON.stringify(s,null,2)}</pre>\n </div>\n\n <div class="section">\n <h3>📜 ${r("detail.history")} (${r("detail.lastRuns",{n:this._history.length})}) ${n>0?`- ${r("detail.avgDuration")}: ${n}ms`:""}</h3>\n <table class="history-table">\n <thead>\n <tr>\n <th>#</th>\n <th>${r("detail.startTime")}</th>\n <th>${r("detail.duration")}</th>\n <th>${r("detail.drift")}</th>\n <th>${r("detail.status")}</th>\n </tr>\n </thead>\n <tbody>\n ${0===this._history.length?`<tr><td colspan="5" class="no-data">${r("detail.noHistory")}</td></tr>`:""}\n ${this._history.slice().reverse().map((t,e)=>{const s=t.success?`✅ ${r("detail.success")}`:t.error?`❌ ${r("detail.error")}: ${t.error}`:`⚠️ ${r("detail.failed")}`,n=t.duration>100?"slow":"";return`\n <tr class="${t.success?"success":"error"}">\n <td class="col-num">${this._history.length-e}</td>\n <td>${new Date(t.timestamp).toLocaleTimeString("en-US",{hour12:!1})}</td>\n <td class="${n}">${t.duration}ms</td>\n <td>0ms</td>\n <td class="status-cell">${s}</td>\n </tr>\n `}).join("")}\n </tbody>\n </table>\n </div>\n `}render(){this._shadow.innerHTML=`\n <style>\n ${l}\n :host {\n display: block;\n height: 100%;\n background: var(--hs-bg);\n overflow-y: auto;\n }\n .content {\n padding: 16px;\n }\n .header {\n display: flex;\n align-items: center;\n gap: 16px;\n margin-bottom: 24px;\n padding-bottom: 16px;\n border-bottom: 2px solid var(--hs-border);\n }\n .back-btn {\n background: var(--hs-bg-secondary);\n border: 1px solid var(--hs-border);\n color: var(--hs-text);\n padding: 6px 12px;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n gap: 4px;\n font-size: 12px;\n }\n .back-btn:hover {\n background: var(--hs-primary);\n color: white;\n border-color: var(--hs-primary);\n }\n h2 {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n }\n h3 {\n font-size: 13px;\n color: var(--hs-text);\n margin-bottom: 12px;\n font-weight: 600;\n }\n .section {\n margin-bottom: 32px;\n }\n .config-label {\n font-size: 12px;\n color: var(--hs-text-secondary);\n margin-bottom: 8px;\n }\n pre {\n background: var(--hs-bg-secondary);\n padding: 12px;\n border-radius: 6px;\n border: 1px solid var(--hs-border);\n font-family: 'Monaco', 'Menlo', monospace;\n font-size: 11px;\n overflow-x: auto;\n line-height: 1.5;\n }\n .history-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 11px;\n }\n .history-table th {\n text-align: left;\n padding: 8px;\n border-bottom: 2px solid var(--hs-border);\n color: var(--hs-text-secondary);\n font-weight: 600;\n background: var(--hs-bg-secondary);\n }\n .history-table td {\n padding: 8px;\n border-bottom: 1px solid var(--hs-border);\n }\n .history-table tr.success {\n background: rgba(34, 197, 94, 0.05);\n }\n .history-table tr.error {\n background: rgba(239, 68, 68, 0.05);\n }\n .history-table tr:hover {\n background: var(--hs-bg-secondary);\n }\n .col-num {\n width: 40px;\n color: var(--hs-text-secondary);\n }\n .slow {\n color: var(--hs-warning);\n font-weight: 600;\n }\n .status-cell {\n font-size: 11px;\n }\n .no-data {\n color: var(--hs-text-secondary);\n font-style: italic;\n text-align: center;\n padding: 24px;\n }\n </style>\n <div class="content"></div>\n `}}customElements.define("hs-task-detail",v);class m extends HTMLElement{constructor(){super(),e(this,"_shadow"),e(this,"_tasks",new Map),e(this,"_history",new Map),e(this,"$canvas"),e(this,"ctx"),e(this,"timeRange",6e4),e(this,"zoom",1),this._shadow=this.attachShadow({mode:"open"})}connectedCallback(){if(this.render(),this.$canvas=this._shadow.querySelector("canvas"),!this.$canvas)return void console.error("[Timeline] Canvas not found");if(this.ctx=this.$canvas.getContext("2d"),!this.ctx)return void console.error("[Timeline] Canvas context not available");this.setupZoom(),this.startLoop();const t=this._shadow.querySelector(".canvas-container");if(t){new ResizeObserver(()=>{requestAnimationFrame(()=>this.draw())}).observe(t)}}set data(t){this._tasks=t.tasks,this._history=t.history}set defaultZoom(t){if(t>=.5&&t<=5){this.zoom=t,this.timeRange=6e4/this.zoom;const e=this._shadow.querySelector(".zoom-slider");e&&(e.value=t.toString()),this.updateZoomLabel()}}updateTexts(){this.updateZoomLabel()}updateZoomLabel(){const t=this._shadow.querySelector(".zoom-label");t&&(t.textContent=`${r("timeline.zoom")}: ${this.zoom}x (${Math.round(this.timeRange/1e3)}s)`)}setupZoom(){const t=this._shadow.querySelector(".zoom-slider"),e=this._shadow.querySelector(".zoom-out"),s=this._shadow.querySelector(".zoom-in"),n=t=>{this.zoom=t,this.timeRange=6e4/this.zoom,this.updateZoomLabel()};null==t||t.addEventListener("input",t=>{const e=parseFloat(t.target.value);n(e)}),null==e||e.addEventListener("click",()=>{const e=Math.max(.5,this.zoom-.5);t&&(t.value=e.toString()),n(e)}),null==s||s.addEventListener("click",()=>{const e=Math.min(5,this.zoom+.5);t&&(t.value=e.toString()),n(e)}),this.updateZoomLabel()}startLoop(){const t=()=>{this.isConnected&&(this.draw(),requestAnimationFrame(t))};requestAnimationFrame(t)}draw(){if(!this.ctx||!this.$canvas)return;const t=this._shadow.querySelector(".canvas-container");if(!t)return;const e=window.devicePixelRatio||1,s=t.clientWidth;if(0===s)return;const n=Array.from(this._tasks.keys()),i=t.clientHeight||300,o=40*n.length+60+40,a=Math.max(i,o);this.$canvas.width=s*e,this.$canvas.height=a*e,this.$canvas.style.width=`${s}px`,this.$canvas.style.height=`${a}px`,this.ctx.setTransform(e,0,0,e,0,0);const r=Date.now(),h=r-this.timeRange,l=getComputedStyle(this),d=l.getPropertyValue("--hs-bg").trim()||"#1e1e1e",c=l.getPropertyValue("--hs-text").trim()||"#fff",p=l.getPropertyValue("--hs-text-secondary").trim()||"#888",g=l.getPropertyValue("--hs-border").trim()||"#333",u=l.getPropertyValue("--hs-success").trim()||"#22c55e",b=l.getPropertyValue("--hs-danger").trim()||"#ef4444";this.ctx.fillStyle=d,this.ctx.fillRect(0,0,s,a),this.drawTimeAxis(s,150,h,p,g),n.forEach((t,e)=>{const n=40*e+60;this.drawTaskRow(t,n,s,150,h,r,c,p,g,u,b)}),this.drawLegend(s,a,p,u)}drawTimeAxis(t,e,s,n,i){const o=this.ctx,a=t-e-20;o.fillStyle=n,o.font="10px monospace",o.textAlign="center";for(let r=0;r<=4;r++){const t=e+a/4*r,n=s+this.timeRange/4*r,h=new Date(n).toLocaleTimeString("en-US",{hour:"2-digit",minute:"2-digit",second:"2-digit",hour12:!1});o.fillText(h,t,30),o.strokeStyle=i,o.beginPath(),o.moveTo(t,40),o.lineTo(t,this.$canvas.clientHeight-40),o.stroke()}o.textAlign="left",o.fillText(r("timeline.timeRange",{n:Math.round(this.timeRange/1e3)}),10,15)}drawTaskRow(t,e,s,n,i,o,a,r,h,l,d){const c=this.ctx,p=s-n-20;c.fillStyle=a,c.font="11px sans-serif",c.textAlign="left",c.fillText(t,10,e+15);const g=this._tasks.get(t),u="main"===(null==g?void 0:g.driver)?"M":"W",b="W"===u?"#22c55e":"#f59e0b";c.fillStyle=b,c.font="9px monospace",c.fillText(`[${u}]`,10,e+28),c.strokeStyle=h,c.beginPath(),c.moveTo(0,e+35),c.lineTo(s,e+35),c.stroke();(this._history.get(t)||[]).forEach(t=>{if(t.timestamp<i||t.timestamp>o)return;const s=n+(t.timestamp-i)/this.timeRange*p,a=t.duration;if(a<10)c.fillStyle=t.success?l:d,c.beginPath(),c.arc(s,e+15,3,0,2*Math.PI),c.fill();else{const n=Math.max(2,a/this.timeRange*p);c.fillStyle=t.success?l:d,c.globalAlpha=.7,c.fillRect(s,e+5,n,20),c.globalAlpha=1}})}drawLegend(t,e,s,n){const i=this.ctx,o=e-25;i.font="10px sans-serif",i.textAlign="left",i.fillStyle=s;let a=10;i.fillText(`${r("timeline.legend")}:`,a,o),a+=50,i.fillStyle=n,i.beginPath(),i.arc(a,o-4,3,0,2*Math.PI),i.fill(),i.fillStyle=s,i.fillText(r("timeline.instant"),a+10,o),a+=60,i.fillStyle=n,i.globalAlpha=.7,i.fillRect(a,o-8,15,10),i.globalAlpha=1,i.fillStyle=s,i.fillText(r("timeline.duration"),a+20,o),a+=80,i.fillText(`[W] ${r("timeline.workerDriver")}`,a,o),a+=110,i.fillText(`[M] ${r("timeline.mainDriver")}`,a,o)}render(){this._shadow.innerHTML=`\n <style>\n ${l}\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n background: var(--hs-bg);\n overflow: hidden;\n }\n .controls {\n display: flex;\n justify-content: flex-end;\n align-items: center;\n padding: 12px 16px;\n gap: 8px;\n border-bottom: 1px solid var(--hs-border);\n flex-shrink: 0;\n }\n .zoom-label {\n font-size: 11px;\n color: var(--hs-text-secondary);\n }\n .zoom-btn {\n background: var(--hs-bg-secondary);\n border: 1px solid var(--hs-border);\n color: var(--hs-text);\n width: 24px;\n height: 24px;\n border-radius: 4px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n }\n .zoom-btn:hover {\n background: var(--hs-primary);\n color: white;\n }\n .zoom-slider {\n width: 100px;\n }\n .canvas-container {\n flex: 1;\n overflow: auto;\n position: relative;\n }\n canvas {\n display: block;\n }\n </style>\n <div class="controls">\n <span class="zoom-label">Zoom:</span>\n <button class="zoom-btn zoom-out">-</button>\n <input type="range" class="zoom-slider" min="0.5" max="5" step="0.5" value="1">\n <button class="zoom-btn zoom-in">+</button>\n </div>\n <div class="canvas-container">\n <canvas></canvas>\n </div>\n `}}customElements.define("hs-timeline",m);class y extends HTMLElement{constructor(){super(),e(this,"_shadow"),e(this,"startX",0),e(this,"startY",0),e(this,"startWidth",0),e(this,"startHeight",0),e(this,"panel",null),e(this,"mode","right"),this._shadow=this.attachShadow({mode:"open"})}isMobile(){return window.innerWidth<=480}connectedCallback(){this.render(),this.addEventListeners(),this.panel=this.closest(".panel"),this.panel&&this.panel.classList.contains("dock-bottom")&&(this.mode="bottom")}addEventListeners(){const t=this._shadow.querySelector(".handle"),e=t=>{if(this.panel&&!this.isMobile())if("right"===this.mode){const e=this.startX-t.clientX,s=Math.max(300,Math.min(window.innerWidth-50,this.startWidth+e));this.panel.style.width=`${s}px`,this.dispatchEvent(new CustomEvent("resize",{detail:{width:s},bubbles:!0,composed:!0}))}else{const e=Math.max(200,Math.min(window.innerHeight-50,this.startHeight+(this.startY-t.clientY)));this.panel.style.height=`${e}px`,this.dispatchEvent(new CustomEvent("resize",{detail:{height:e},bubbles:!0,composed:!0}))}},s=()=>{document.removeEventListener("mousemove",e),document.removeEventListener("mouseup",s),document.body.style.userSelect="",document.body.style.cursor=""};t.addEventListener("mousedown",t=>{this.isMobile()||(this.startX=t.clientX,this.startY=t.clientY,this.panel&&(this.panel.classList.contains("dock-bottom")?(this.mode="bottom",this.startHeight=this.panel.offsetHeight):(this.mode="right",this.startWidth=this.panel.offsetWidth)),document.addEventListener("mousemove",e),document.addEventListener("mouseup",s),document.body.style.userSelect="none",document.body.style.cursor="right"===this.mode?"col-resize":"row-resize")})}render(){this._shadow.innerHTML=`\n <style>\n ${l}\n :host {\n display: block;\n z-index: 100;\n }\n .handle {\n background: transparent;\n transition: background 0.2s;\n }\n .handle:hover {\n background: var(--hs-primary);\n }\n \n /* Right Dock Mode (Vertical Handle on Left) */\n :host-context(.dock-right) .handle {\n width: 4px;\n height: 100%;\n cursor: col-resize;\n position: absolute;\n left: 0;\n top: 0;\n }\n\n /* Bottom Dock Mode (Horizontal Handle on Top) */\n :host-context(.dock-bottom) .handle {\n width: 100%;\n height: 4px;\n cursor: row-resize;\n position: absolute;\n top: 0;\n left: 0;\n }\n \n /* 移动端隐藏拖拽手柄 */\n @media (max-width: 480px) {\n .handle {\n display: none;\n }\n }\n </style>\n <div class="handle"></div>\n `}}customElements.define("hs-resizer",y);class x extends HTMLElement{constructor(){super(),e(this,"_shadow"),e(this,"store"),e(this,"scheduler"),e(this,"rAFId"),e(this,"lastTime",0),e(this,"$panel"),e(this,"$header"),e(this,"$taskList"),e(this,"$taskDetail"),e(this,"$timeline"),e(this,"$trigger"),e(this,"$overlay"),this._shadow=this.attachShadow({mode:"open"}),this.store=new h}connectedCallback(){const t=this.getAttribute("language");"en"!==t&&"zh"!==t||this.store.setLanguageSync(t),this.render(),this.cacheDom(),this.bindStore();const e=this.getAttribute("dock");console.log("[DevTools] dock attribute:",e),"bottom"===e&&this.store.setDockPosition("bottom");const s=this.getAttribute("theme");"light"!==s&&"dark"!==s&&"auto"!==s||this.store.setTheme(s),"en"!==t&&"zh"!==t||this.store.setLanguage(t);const n=this.getAttribute("trigger-bg"),i=this.getAttribute("trigger-color"),o=this.getAttribute("trigger-position");console.log("[DevTools] trigger attrs:",{triggerBg:n,triggerColor:i,triggerPosition:o}),n&&this.$trigger.setAttribute("bg-color",n),i&&this.$trigger.setAttribute("text-color",i),o&&this.$trigger.setAttribute("position",o);const a=this.getAttribute("default-zoom");if(a){const t=parseFloat(a);!isNaN(t)&&t>=.5&&t<=5&&(this.$timeline.defaultZoom=t)}this.addEventListeners(),this.startLoop()}disconnectedCallback(){this.rAFId&&cancelAnimationFrame(this.rAFId)}setScheduler(t){this.scheduler=t,this.store.setScheduler(t);this.scheduler.getTasks().forEach(t=>this.store.updateTask(t));const e=this.scheduler.isRunning();this.store.setSchedulerRunning(e);const n=()=>{var t;((null==(t=this.scheduler)?void 0:t.getTasks())||[]).forEach(t=>this.store.updateTask(t))};this.scheduler.on(s.SchedulerEvents.TASK_REGISTERED,n),this.scheduler.on(s.SchedulerEvents.TASK_UPDATED,t=>{console.log("[DevTools] task_updated event:",t),n()}),this.scheduler.on(s.SchedulerEvents.TASK_STARTED,n),this.scheduler.on(s.SchedulerEvents.TASK_REMOVED,n),this.scheduler.on(s.SchedulerEvents.TASK_STOPPED,t=>{console.log("[DevTools] task_stopped event:",t),n()}),this.scheduler.on(s.SchedulerEvents.SCHEDULER_STARTED,()=>{console.log("[DevTools] scheduler_started event"),this.store.setSchedulerRunning(!0),n()}),this.scheduler.on(s.SchedulerEvents.SCHEDULER_STOPPED,()=>{console.log("[DevTools] scheduler_stopped event"),this.store.setSchedulerRunning(!1),n()}),this.scheduler.on(s.SchedulerEvents.TASK_COMPLETED,t=>{var e;n(),t&&t.taskId&&this.store.addHistory(t.taskId,{timestamp:(null==(e=t.task)?void 0:e.lastRun)||Date.now(),duration:t.duration||0,success:!0,error:null})}),this.scheduler.on(s.SchedulerEvents.TASK_FAILED,t=>{var e;n(),t&&t.taskId&&this.store.addHistory(t.taskId,{timestamp:(null==(e=t.task)?void 0:e.lastRun)||Date.now(),duration:t.duration||0,success:!1,error:t.error||"Unknown error"})}),setInterval(()=>{this.store.getState().isOpen&&n()},500)}cacheDom(){this.$panel=this._shadow.querySelector(".panel"),this.$header=this._shadow.querySelector("hs-task-header"),this.$taskList=this._shadow.querySelector("hs-task-list"),this.$taskDetail=this._shadow.querySelector("hs-task-detail"),this.$timeline=this._shadow.querySelector("hs-timeline"),this.$trigger=this._shadow.querySelector("hs-floating-trigger"),this.$overlay=this._shadow.querySelector(".overlay")}bindStore(){try{const t=localStorage.getItem("hs-panel-size");t&&this.store.setPanelSize(JSON.parse(t))}catch(t){}this.store.subscribe("isOpen",t=>{const e=this.store.getState().dockPosition,s=this.store.getState().panelSize;t?(this.$panel.classList.add("open"),this.$trigger.style.display="none",this.$overlay.style.display="block","right"===e?this.$panel.style.right="0":this.$panel.style.bottom="0"):(this.$panel.classList.remove("open"),this.$trigger.style.display="block",this.$overlay.style.display="none","right"===e?this.$panel.style.right=`-${s.width}px`:this.$panel.style.bottom=`-${s.height}px`)}),this.store.subscribe("theme",t=>{const e="auto"===t?"light":t;this.setAttribute("theme",e),this.$header.setAttribute("theme",e),this.$taskList.setAttribute("theme",e),this.$taskDetail.setAttribute("theme",e),this.$timeline.setAttribute("theme",e),this.$header.theme=t}),this.store.subscribe("tasks",t=>{this.$taskList.tasks=t,this.$timeline.data={tasks:t,history:this.store.getState().history};let e=0;t.forEach(t=>{"idle"!==t.status&&"running"!==t.status||e++}),this.$header.stats={active:e,total:t.size};const s=this.store.getState().selectedTaskId;s&&t.has(s)&&(this.$taskDetail.task=t.get(s)||null)}),this.store.subscribe("history",t=>{this.$timeline.data={tasks:this.store.getState().tasks,history:t};const e=this.store.getState().selectedTaskId;e&&(this.$taskDetail.history=t.get(e)||[])}),this.store.subscribe("selectedTaskId",t=>{if("tasks"===this.store.getState().activeTab)if(t){this.$taskList.style.display="none",this.$taskDetail.style.display="block";const e=this.store.getState().tasks.get(t),s=this.store.getState().history.get(t);this.$taskDetail.task=e||null,this.$taskDetail.history=s||[]}else this.$taskList.style.display="block",this.$taskDetail.style.display="none"}),this.store.subscribe("activeTab",t=>{this.$header.activeTab=t,"tasks"===t?(this.$taskList.style.display="block",this.$timeline.style.display="none",this.store.getState().selectedTaskId?(this.$taskList.style.display="none",this.$taskDetail.style.display="block"):(this.$taskList.style.display="block",this.$taskDetail.style.display="none")):(this.$taskList.style.display="none",this.$taskDetail.style.display="none",this.$timeline.style.display="block")}),this.store.subscribe("dockPosition",t=>{this.$header.dockPosition=t;const e=this.store.getState().panelSize,s=this.store.getState().isOpen,n=window.innerWidth<=480;if("right"===t){this.$panel.classList.add("dock-right"),this.$panel.classList.remove("dock-bottom");const t=n?window.innerWidth:e.width;this.$panel.style.width=n?"100vw":`${t}px`,this.$panel.style.height="100vh",this.$panel.style.bottom="",this.$panel.style.right=s?"0":`-${t}px`}else{this.$panel.classList.add("dock-bottom"),this.$panel.classList.remove("dock-right"),this.$panel.style.width="100%";const t=n?"50vh":`${e.height}px`;this.$panel.style.height=t,this.$panel.style.right="",this.$panel.style.bottom=s?"0":n?"-50vh":`-${e.height}px`}}),this.store.subscribe("panelSize",t=>{const e=this.store.getState().dockPosition;"right"===e&&t.width?(this.$panel.style.width=`${t.width}px`,this.$panel.style.right=this.store.getState().isOpen?"0":`-${t.width}px`):"bottom"===e&&t.height&&(this.$panel.style.height=`${t.height}px`,this.$panel.style.bottom=this.store.getState().isOpen?"0":`-${t.height}px`)}),this.store.subscribe("language",t=>{var e,s,n,i;this.$header.language=t,this.$taskList.updateHeaders(),null==(s=(e=this.$taskDetail).updateTexts)||s.call(e),null==(i=(n=this.$timeline).updateTexts)||i.call(n)}),this.store.subscribe("filterText",t=>{const e=this.store.getState().tasks;this.$taskList.filter(t,e)}),this.store.subscribe("schedulerRunning",t=>{this.$header.schedulerRunning=t})}addEventListeners(){this.$trigger.addEventListener("toggle",()=>{this.store.toggle()}),this.$header.addEventListener("close",t=>{t.stopPropagation(),this.store.toggle()}),this.$header.addEventListener("dock-toggle",()=>{const t=this.store.getState().dockPosition;this.store.setDockPosition("right"===t?"bottom":"right")}),this.$header.addEventListener("theme-toggle",t=>{const e=t.detail;this.store.setTheme(e)}),this.$header.addEventListener("lang-toggle",t=>{const e=t.detail;this.store.setLanguage(e)}),this.$header.addEventListener("tab-change",t=>{const e=t.detail;this.store.setTab(e)}),this.$header.addEventListener("search",t=>{const e=t.detail;this.store.setFilterText(e)}),this.$overlay.addEventListener("click",()=>{this.store.toggle()}),this.$taskList.addEventListener("task-select",t=>{const e=t.detail;this.store.selectTask(e)}),this.$taskDetail.addEventListener("back",()=>{this.store.selectTask(null)}),this.$taskList.addEventListener("task-action",t=>{const{action:e,id:s}=t.detail;switch(console.log("[DevTools] task-action:",e,s),e){case"trigger":this.store.triggerTask(s);break;case"stop":this.store.stopTask(s);break;case"start":this.store.startTask(s);break;case"remove":confirm(`Remove task "${s}"?`)&&this.store.removeTask(s)}})}startLoop(){const t=e=>{const s=e-this.lastTime;this.lastTime=e;const n=1e3/s;this.$header&&(this.$header.fps=n),this.rAFId=requestAnimationFrame(t)};this.rAFId=requestAnimationFrame(t)}render(){this._shadow.innerHTML=`\n <style>\n ${l}\n :host {\n font-family: var(--hs-font-family);\n font-size: var(--hs-font-size);\n color: var(--hs-text);\n line-height: var(--hs-line-height);\n }\n .overlay {\n position: fixed;\n top: 0;\n left: 0;\n width: 100vw;\n height: 100vh;\n background: rgba(0, 0, 0, 0.5);\n z-index: calc(var(--hs-z-index) - 1); /* 确保在面板之下,但在应用之上 */\n display: none; /* 默认隐藏 */\n }\n .panel {\n position: fixed;\n background: var(--hs-bg);\n box-shadow: var(--hs-shadow);\n z-index: var(--hs-z-index);\n transition: all 0.3s ease;\n display: flex;\n flex-direction: column;\n border-left: 1px solid var(--hs-border);\n }\n /* Default Right Dock */\n .panel.dock-right {\n top: 0;\n right: -500px;\n width: 500px;\n height: 100vh;\n border-left: 1px solid var(--hs-border);\n border-top: none;\n }\n \n /* Bottom Dock */\n .panel.dock-bottom {\n bottom: -50vh;\n left: 0;\n width: 100%;\n height: 50vh;\n max-height: 50vh;\n border-top: 1px solid var(--hs-border);\n border-left: none;\n }\n\n .content {\n flex: 1;\n overflow: hidden;\n position: relative;\n display: flex;\n flex-direction: column;\n }\n .content > * {\n flex: 1;\n min-height: 0;\n }\n \n /* Mobile - 固定尺寸,禁用拖拽 */\n @media (max-width: 480px) {\n .panel.dock-right {\n width: 100vw !important;\n right: -100vw;\n }\n .panel.dock-right.open {\n right: 0;\n }\n .panel.dock-bottom {\n height: 50vh !important;\n max-height: 50vh !important;\n bottom: -50vh;\n }\n .panel.dock-bottom.open {\n bottom: 0;\n }\n }\n </style>\n \n <div class="overlay"></div>\n <hs-floating-trigger></hs-floating-trigger>\n \n <div class="panel dock-right">\n <hs-resizer></hs-resizer>\n <hs-task-header></hs-task-header>\n <div class="content">\n <hs-task-list></hs-task-list>\n <hs-task-detail style="display:none"></hs-task-detail>\n <hs-timeline style="display:none"></hs-timeline>\n </div>\n </div>\n `}}customElements.define("hs-devtools",x),exports.DevTools=x;
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var t=Object.defineProperty,e=(e,s,i)=>((e,s,i)=>s in e?t(e,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[s]=i)(e,"symbol"!=typeof s?s+"":s,i);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s={IDLE:"idle",RUNNING:"running",STOPPED:"stopped",ERROR:"error"},i={TASK_REGISTERED:"task_registered",TASK_STARTED:"task_started",TASK_COMPLETED:"task_completed",TASK_FAILED:"task_failed",TASK_STOPPED:"task_stopped",TASK_REMOVED:"task_removed",TASK_UPDATED:"task_updated",SCHEDULER_STARTED:"scheduler_started",SCHEDULER_STOPPED:"scheduler_stopped"};class r{constructor(){e(this,"tasks"),e(this,"namespaceIndex"),this.tasks=new Map,this.namespaceIndex=new Map}addTask(t){var e,s;if(this.tasks.has(t.id))throw new Error(`Task with ID "${t.id}" already exists.`);this.tasks.set(t.id,t);const i=(null==(e=t.options)?void 0:e.namespace)||"default";this.namespaceIndex.has(i)||this.namespaceIndex.set(i,new Set),null==(s=this.namespaceIndex.get(i))||s.add(t.id)}getTask(t){return this.tasks.get(t)}deleteTask(t){var e,s,i;const r=this.tasks.get(t);if(!r)return!1;const n=(null==(e=r.options)?void 0:e.namespace)||"default";return null==(s=this.namespaceIndex.get(n))||s.delete(t),0===(null==(i=this.namespaceIndex.get(n))?void 0:i.size)&&this.namespaceIndex.delete(n),this.tasks.delete(t)}getAllTasks(){return Array.from(this.tasks.values())}getTasksByNamespace(t){const e=this.namespaceIndex.get(t);return e?Array.from(e).map(t=>this.tasks.get(t)).filter(Boolean):[]}clear(){this.tasks.clear(),this.namespaceIndex.clear()}}function n(t,e,s){const i=new Set;if("*"===t){for(let t=e;t<=s;t++)i.add(t);return Array.from(i).sort((t,e)=>t-e)}const r=t.split(",");for(const n of r)if(n.includes("/")){const[t,r]=n.split("/"),o=parseInt(r,10);if("*"===t)for(let n=e;n<=s;n+=o)i.add(n);else if(t.includes("-")){const[r,n]=t.split("-").map(Number);if(r<e||n>s)throw new Error(`Value out of range: ${r}-${n} (expected ${e}-${s})`);for(let t=r;t<=n;t+=o)i.add(t)}else{const r=parseInt(t,10);if(r<e||r>s)throw new Error(`Value out of range: ${r} (expected ${e}-${s})`);for(let t=r;t<=s;t+=o)i.add(t)}}else if(n.includes("-")){const[t,r]=n.split("-").map(Number);if(t<e||r>s)throw new Error(`Value out of range: ${t}-${r} (expected ${e}-${s})`);for(let e=t;e<=r;e++)i.add(e)}else{const t=parseInt(n,10);if(t<e||t>s)throw new Error(`Value out of range: ${t} (expected ${e}-${s})`);i.add(t)}return Array.from(i).sort((t,e)=>t-e)}function o(t){const e=t.trim().split(/\s+/);let s,i,r,o,a,l;if(5===e.length)s=[0],[i,r,o,a,l]=[n(e[0],0,59),n(e[1],0,23),n(e[2],1,31),n(e[3],1,12),n(e[4],0,6)];else{if(6!==e.length)throw new Error(`Invalid cron expression: expected 5 or 6 fields, got ${e.length}`);[s,i,r,o,a,l]=[n(e[0],0,59),n(e[1],0,59),n(e[2],0,23),n(e[3],1,31),n(e[4],1,12),n(e[5],0,6)]}return{second:s,minute:i,hour:r,dayOfMonth:o,month:a,dayOfWeek:l}}function a(t,e){const s=t.getSeconds(),i=t.getMinutes(),r=t.getHours(),n=t.getDate(),o=t.getMonth()+1,a=t.getDay();return e.second.includes(s)&&e.minute.includes(i)&&e.hour.includes(r)&&e.month.includes(o)&&(e.dayOfMonth.includes(n)||e.dayOfWeek.includes(a))}function l(t){const e=t.match(/^(\d+)(s|m|h|d)$/);if(e){const t=parseInt(e[1],10);let s=1e3;switch(e[2]){case"s":s=1e3;break;case"m":s=6e4;break;case"h":s=36e5;break;case"d":s=864e5}return{type:"interval",value:t*s}}try{return function(t){try{o(t)}catch(e){throw new Error(`Invalid cron expression: ${t}`)}}(t),{type:"cron",value:t}}catch(s){throw new Error(`无效的调度格式: "${t}". 必须是有效的 Cron 表达式或间隔字符串 (例如 "10s")。`)}}function c(t,e){let s;if(s="string"==typeof t?l(t):t,"interval"===s.type){const t=s.value,i=(null==e?void 0:e.lastRun)||Date.now();return new Date(i+t)}{const t=s.value;try{return function(t){var e,s,i;const r=o(t);let n=new Date((new Date).getTime()+1e3);n.setMilliseconds(0);let l=0;for(;l<126144e3;){if(a(n,r))return n;const t=n.getSeconds(),o=n.getMinutes(),c=n.getHours();if(!r.second.includes(t)){const s=null!=(e=r.second.find(e=>e>t))?e:r.second[0];s>t?n.setSeconds(s):n.setMinutes(o+1,s),n.setMilliseconds(0),l++;continue}if(!r.minute.includes(o)){const t=null!=(s=r.minute.find(t=>t>o))?s:r.minute[0];t>o?n.setMinutes(t,r.second[0]):n.setHours(c+1,t,r.second[0]),n.setMilliseconds(0),l++;continue}if(!r.hour.includes(c)){const t=null!=(i=r.hour.find(t=>t>c))?i:r.hour[0];t>c||n.setDate(n.getDate()+1),n.setHours(t,r.minute[0],r.second[0]),n.setMilliseconds(0),l++;continue}n=new Date(n.getTime()+1e3),l++}throw new Error(`Could not find next run time for cron expression: ${t}`)}(t,null==e||e.timezone)}catch(i){throw new Error(`无法计算下一次 Cron 运行时间: ${t}`)}}}class u{static getDelay(t,e){if(!e)return-1;const{maxAttempts:s,initialDelay:i,factor:r=2}=e;return t>=s?-1:i*Math.pow(r,t)}}let d=class{constructor(t,s={},i){e(this,"registry"),e(this,"config"),e(this,"defaultTimerStrategy"),e(this,"timerStrategyFactory"),e(this,"taskTimerStrategies"),e(this,"running"),e(this,"timers"),e(this,"listeners"),e(this,"eventListeners"),this.registry=new r,this.defaultTimerStrategy=t,this.timerStrategyFactory=i,this.taskTimerStrategies=new Map,this.config={debug:!1,maxHistory:50,...s},this.running=!1,this.timers=new Map,this.listeners=[],this.eventListeners=new Map,this.config.plugins&&Array.isArray(this.config.plugins)&&this.config.plugins.forEach(t=>{try{this.log(`Initializing plugin: ${t.name}`),t.init(this)}catch(e){console.warn(`[HyperScheduler] Failed to initialize plugin ${t.name}:`,e)}})}subscribe(t){return this.listeners.push(t),()=>{this.listeners=this.listeners.filter(e=>e!==t)}}on(t,e){return this.eventListeners.has(t)||this.eventListeners.set(t,new Set),this.eventListeners.get(t).add(e),()=>{var s;null==(s=this.eventListeners.get(t))||s.delete(e)}}emit(t,e){const s=this.eventListeners.get(t);s&&s.forEach(t=>t(e))}getTimerStrategy(t){var e;const s=null==(e=t.options)?void 0:e.driver,i=this.config.driver,r=s||i;if(!r||!this.timerStrategyFactory)return this.defaultTimerStrategy;const n=`${t.id}_${r}`;if(this.taskTimerStrategies.has(n))return this.taskTimerStrategies.get(n);const o=this.timerStrategyFactory(r);return this.taskTimerStrategies.set(n,o),o}notify(){if(this.listeners.length>0){const t=this.registry.getAllTasks();this.listeners.forEach(e=>e(t))}}createTask(t){var e;!function(t){if(!t||"string"!=typeof t||""===t.trim())throw new Error("Task ID must be a non-empty string.")}(t.id),l(t.schedule);const r={...t,tags:t.tags||[],status:s.STOPPED,history:[],executionCount:0};this.registry.addTask(r),this.log(`Task created: ${r.id}`),this.emit(i.TASK_REGISTERED,{taskId:r.id,task:r}),this.notify(),this.running&&(r.status=s.IDLE,(null==(e=r.options)?void 0:e.runImmediately)&&this.triggerTask(r.id),this.scheduleTask(r))}deleteTask(t){this.stopTask(t);const e=this.registry.deleteTask(t);return e&&(this.log(`Task deleted: ${t}`),this.emit(i.TASK_REMOVED,{taskId:t}),this.notify()),e}startTask(t){const e=this.registry.getTask(t);if(!e)throw new Error(`Task not found: ${t}`);if(e.status===s.RUNNING)return;const r=this.timers.get(t);r&&(this.getTimerStrategy(e).cancel(r),this.timers.delete(t)),e.status=s.IDLE,this.log(`Starting task: ${t}`),this.emit(i.TASK_STARTED,{taskId:t,task:e}),this.notify(),this.scheduleTaskForce(e)}scheduleTaskForce(t){var e;try{const s=c(t.schedule,{timezone:(null==(e=t.options)?void 0:e.timezone)||this.config.timezone,lastRun:t.lastRun});t.nextRun=s.getTime();const i=Date.now(),r=Math.max(0,s.getTime()-i);this.log(`Scheduling task ${t.id} for ${s.toISOString()} (in ${r}ms)`);const n=this.getTimerStrategy(t).schedule(()=>{this.executeTaskIndividual(t)},r);this.timers.set(t.id,n)}catch(i){this.log(`Error scheduling task ${t.id}: ${i}`),t.status=s.ERROR,this.notify()}}async executeTaskIndividual(t,e=0){var r,n;if(this.timers.delete(t.id),t.status===s.STOPPED)return;t.status=s.RUNNING,t.lastRun=Date.now(),t.executionCount=(t.executionCount||0)+1;const o=Date.now();this.log(`Executing task: ${t.id} (Attempt ${e})`),this.emit(i.TASK_STARTED,{taskId:t.id,task:t}),this.notify();try{await t.handler();const e=Date.now()-o;this.recordHistory(t,{timestamp:o,duration:e,success:!0}),t.status=s.IDLE,this.log(`Task execution success: ${t.id}`),this.emit(i.TASK_COMPLETED,{taskId:t.id,task:t,duration:e}),this.notify(),this.scheduleTaskForce(t)}catch(a){const c=Date.now()-o;if(this.recordHistory(t,{timestamp:o,duration:c,success:!1,error:a.message}),this.log(`Task execution failed: ${t.id} - ${a.message}`),this.emit(i.TASK_FAILED,{taskId:t.id,task:t,error:a.message,duration:c}),null==(r=t.options)?void 0:r.onError)try{t.options.onError(a,t.id)}catch(l){this.log(`onError callback failed: ${l}`)}const d=u.getDelay(e,null==(n=t.options)?void 0:n.retry);if(d>=0){this.log(`Retrying task ${t.id} in ${d}ms (Attempt ${e+1})`);const i=this.getTimerStrategy(t).schedule(()=>{this.executeTaskIndividual(t,e+1)},d);this.timers.set(t.id,i),t.status=s.ERROR,this.notify()}else t.status=s.ERROR,this.notify(),this.scheduleTaskForce(t)}}stopTask(t){const e=this.registry.getTask(t),r=this.timers.get(t);r&&e?(this.getTimerStrategy(e).cancel(r),this.timers.delete(t)):r&&(this.defaultTimerStrategy.cancel(r),this.timers.delete(t)),e&&(e.status=s.STOPPED,this.log(`Task stopped: ${t}`),this.emit(i.TASK_STOPPED,{taskId:t,task:e}),this.notify())}getTask(t){return this.registry.getTask(t)}getAllTasks(t){return t?this.registry.getTasksByNamespace(t):this.registry.getAllTasks()}isRunning(){return this.running}getTaskDriver(t){var e;const s=this.registry.getTask(t);return s?(null==(e=s.options)?void 0:e.driver)||this.config.driver||"worker":this.config.driver||"worker"}getGlobalDriver(){return this.config.driver||"worker"}async triggerTask(t){const e=this.getTask(t);if(!e)return;if(e.status===s.RUNNING)return;const r=e.status;e.status=s.RUNNING,e.lastRun=Date.now(),e.executionCount=(e.executionCount||0)+1;const n=Date.now();this.log(`Triggering task: ${e.id}`),this.emit(i.TASK_STARTED,{taskId:e.id,task:e}),this.notify();try{await e.handler();const t=Date.now()-n;this.recordHistory(e,{timestamp:n,duration:t,success:!0}),e.status=r,this.log(`Task trigger success: ${e.id}`),this.emit(i.TASK_COMPLETED,{taskId:e.id,task:e,duration:t}),this.notify()}catch(o){const t=Date.now()-n;this.recordHistory(e,{timestamp:n,duration:t,success:!1,error:o.message}),this.log(`Task trigger failed: ${e.id} - ${o.message}`),this.emit(i.TASK_FAILED,{taskId:e.id,task:e,error:o.message,duration:t}),e.status=r,this.notify()}}start(t){if(!t&&this.running)return;this.log(t?`Scheduler starting for scope: ${t}`:"Scheduler started"),this.emit(i.SCHEDULER_STARTED,{running:!0,scope:t});(t?this.registry.getTasksByNamespace(t):this.registry.getAllTasks()).forEach(t=>{var e;t.status===s.STOPPED&&(t.status=s.IDLE,this.emit(i.TASK_UPDATED,{taskId:t.id,task:t})),t.status!==s.RUNNING&&((null==(e=t.options)?void 0:e.runImmediately)&&this.triggerTask(t.id),this.scheduleTask(t))}),t||(this.running=!0),this.notify()}stop(t){if(!t&&!this.running)return;this.log(t?`Scheduler stopping for scope: ${t}`:"Scheduler stopped"),this.emit(i.SCHEDULER_STOPPED,{running:!1,scope:t});(t?this.registry.getTasksByNamespace(t):this.registry.getAllTasks()).forEach(t=>{const e=this.timers.get(t.id);e&&(this.getTimerStrategy(t).cancel(e),this.timers.delete(t.id)),t.status!==s.STOPPED&&(t.status=s.STOPPED,this.emit(i.TASK_UPDATED,{taskId:t.id,task:t}))}),t||(this.running=!1),this.notify()}scheduleTask(t){var e;try{const s=c(t.schedule,{timezone:(null==(e=t.options)?void 0:e.timezone)||this.config.timezone,lastRun:t.lastRun});t.nextRun=s.getTime();const i=Date.now(),r=Math.max(0,s.getTime()-i);this.log(`Scheduling task ${t.id} for ${s.toISOString()} (in ${r}ms)`);const n=this.getTimerStrategy(t).schedule(()=>{this.executeTask(t)},r);this.timers.set(t.id,n)}catch(i){this.log(`Error scheduling task ${t.id}: ${i}`),t.status=s.ERROR}}async executeTask(t,e=0,r=!1){var n,o;if(this.timers.delete(t.id),!r&&t.status===s.STOPPED)return;t.status=s.RUNNING,t.lastRun=Date.now(),t.executionCount=(t.executionCount||0)+1;const a=Date.now();this.log(`Executing task: ${t.id} (Attempt ${e})`),this.emit(i.TASK_STARTED,{taskId:t.id,task:t}),this.notify();try{await t.handler();const e=Date.now()-a;this.recordHistory(t,{timestamp:a,duration:e,success:!0}),t.status=s.IDLE,this.log(`Task execution success: ${t.id}`),this.emit(i.TASK_COMPLETED,{taskId:t.id,task:t,duration:e}),this.notify(),this.scheduleTask(t)}catch(l){const r=Date.now()-a;if(this.recordHistory(t,{timestamp:a,duration:r,success:!1,error:l.message}),this.log(`Task execution failed: ${t.id} - ${l.message}`),this.emit(i.TASK_FAILED,{taskId:t.id,task:t,error:l.message,duration:r}),null==(n=t.options)?void 0:n.onError)try{t.options.onError(l,t.id)}catch(c){this.log(`onError callback failed: ${c}`)}const d=u.getDelay(e,null==(o=t.options)?void 0:o.retry);if(d>=0){this.log(`Retrying task ${t.id} in ${d}ms (Attempt ${e+1})`);const i=this.getTimerStrategy(t).schedule(()=>{this.executeTask(t,e+1)},d);this.timers.set(t.id,i),t.status=s.ERROR,this.notify()}else t.status=s.ERROR,this.notify(),this.scheduleTask(t)}}recordHistory(t,e){t.history.unshift(e),this.config.maxHistory&&t.history.length>this.config.maxHistory&&t.history.pop()}log(t){this.config.debug&&console.log(`[HyperScheduler] ${t}`)}};class h{schedule(t,e){return setTimeout(t,e)}cancel(t){clearTimeout(t)}}const g="IWZ1bmN0aW9uKCl7InVzZSBzdHJpY3QiO2NvbnN0IGU9bmV3IE1hcDtzZWxmLm9ubWVzc2FnZT1zPT57Y29uc3R7aWQ6dCxkZWxheTpjLHR5cGU6bH09cy5kYXRhO2lmKCJzY2hlZHVsZSI9PT1sKXtjb25zdCBzPXNlbGYuc2V0VGltZW91dCgoKT0+e3NlbGYucG9zdE1lc3NhZ2Uoe2lkOnQsdHlwZToidGljayJ9KSxlLmRlbGV0ZSh0KX0sYyk7ZS5zZXQodCxzKX1lbHNlIGlmKCJjYW5jZWwiPT09bCl7Y29uc3Qgcz1lLmdldCh0KTt2b2lkIDAhPT1zJiYoc2VsZi5jbGVhclRpbWVvdXQocyksZS5kZWxldGUodCkpfX19KCk7Cg==",m="undefined"!=typeof self&&self.Blob&&new Blob([(k=g,Uint8Array.from(atob(k),t=>t.charCodeAt(0)))],{type:"text/javascript;charset=utf-8"});var k;function f(t){let e;try{if(e=m&&(self.URL||self.webkitURL).createObjectURL(m),!e)throw"";const s=new Worker(e,{name:null==t?void 0:t.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),s}catch(s){return new Worker("data:text/javascript;base64,"+g,{name:null==t?void 0:t.name})}finally{e&&(self.URL||self.webkitURL).revokeObjectURL(e)}}class T{constructor(){e(this,"worker"),e(this,"callbacks"),e(this,"nextId"),this.worker=void 0!==f?new f:{postMessage:()=>{},onmessage:null,terminate:()=>{},addEventListener:()=>{},removeEventListener:()=>{},dispatchEvent:()=>!1},this.callbacks=new Map,this.nextId=1,this.worker.onmessage=t=>{const{id:e,type:s}=t.data;if("tick"===s){const t=this.callbacks.get(e);t&&(t(),this.callbacks.delete(e))}}}schedule(t,e){const s=this.nextId++;return this.callbacks.set(s,t),this.worker.postMessage({id:s,delay:e,type:"schedule"}),s}cancel(t){this.worker.postMessage({id:t,type:"cancel"}),this.callbacks.delete(t)}}class p{schedule(t,e){return window.setTimeout(t,e)}cancel(t){window.clearTimeout(t)}}const y="undefined"!=typeof window&&void 0!==window.document;let E=null,S=null;exports.CoreScheduler=d,exports.DevTools=class{constructor(t={}){e(this,"name","DevTools"),e(this,"options"),this.options=t}init(t){"undefined"!=typeof window&&void 0!==window.document&&this.mount(t)}async mount(t){try{await Promise.resolve().then(()=>require("./devtools-xPwLHcqi.cjs")),await customElements.whenDefined("hs-devtools"),this.setupElement(t)}catch(e){console.error("[DevTools] Failed to mount:",e)}}setupElement(t){try{let e=document.querySelector("hs-devtools");e&&e.remove(),e=document.createElement("hs-devtools");const i=this.options;console.log("[DevTools Plugin] options:",JSON.stringify(i)),i.theme&&e.setAttribute("theme",i.theme),i.dockPosition&&e.setAttribute("dock",i.dockPosition),i.language&&e.setAttribute("language",i.language),i.defaultZoom&&e.setAttribute("default-zoom",i.defaultZoom.toString()),i.trigger&&(i.trigger.backgroundColor&&e.setAttribute("trigger-bg",i.trigger.backgroundColor),i.trigger.textColor&&e.setAttribute("trigger-color",i.trigger.textColor),i.trigger.position&&e.setAttribute("trigger-position",i.trigger.position)),console.log("[DevTools Plugin] attributes set:",e.getAttribute("dock"),e.getAttribute("trigger-position")),document.body.appendChild(e),"function"==typeof e.setScheduler?e.setScheduler({getTasks:()=>t.getAllTasks().map(e=>{var i;return{id:e.id,status:e.status,lastRun:e.lastRun||null,nextRun:e.nextRun||null,executionCount:e.executionCount||0,schedule:e.schedule,tags:e.tags||[],error:e.status===s.ERROR?"Execution failed":null,driver:t.getTaskDriver(e.id),namespace:(null==(i=e.options)?void 0:i.namespace)||"default"}}),on:(e,s)=>t.on(e,s),isRunning:()=>t.isRunning(),trigger:e=>t.triggerTask(e),pause:e=>t.stopTask(e),resume:e=>t.startTask(e),remove:e=>t.deleteTask(e)}):console.warn("[DevTools] hs-devtools element does not have setScheduler method.")}catch(e){console.error("[DevTools] Failed to setup element:",e)}}},exports.Scheduler=class extends d{constructor(t){super(function(t){if(y)return"main"===((null==t?void 0:t.driver)||"worker")?(S||(S=new p),S):(E||(E=new T),E);return new h}(t),t,function(){if(y)return t=>"main"===t?(S||(S=new p),S):(E||(E=new T),E)}())}},exports.SchedulerEvents=i,exports.TaskStatus=s;
1
+ "use strict";var t=Object.defineProperty,e=(e,s,i)=>((e,s,i)=>s in e?t(e,s,{enumerable:!0,configurable:!0,writable:!0,value:i}):e[s]=i)(e,"symbol"!=typeof s?s+"":s,i);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const s={IDLE:"idle",RUNNING:"running",STOPPED:"stopped",ERROR:"error"},i={TASK_REGISTERED:"task_registered",TASK_STARTED:"task_started",TASK_COMPLETED:"task_completed",TASK_FAILED:"task_failed",TASK_STOPPED:"task_stopped",TASK_REMOVED:"task_removed",TASK_UPDATED:"task_updated",SCHEDULER_STARTED:"scheduler_started",SCHEDULER_STOPPED:"scheduler_stopped"};class r{constructor(){e(this,"tasks"),e(this,"namespaceIndex"),this.tasks=new Map,this.namespaceIndex=new Map}addTask(t){var e,s;if(this.tasks.has(t.id))throw new Error(`Task with ID "${t.id}" already exists.`);this.tasks.set(t.id,t);const i=(null==(e=t.options)?void 0:e.namespace)||"default";this.namespaceIndex.has(i)||this.namespaceIndex.set(i,new Set),null==(s=this.namespaceIndex.get(i))||s.add(t.id)}getTask(t){return this.tasks.get(t)}deleteTask(t){var e,s,i;const r=this.tasks.get(t);if(!r)return!1;const n=(null==(e=r.options)?void 0:e.namespace)||"default";return null==(s=this.namespaceIndex.get(n))||s.delete(t),0===(null==(i=this.namespaceIndex.get(n))?void 0:i.size)&&this.namespaceIndex.delete(n),this.tasks.delete(t)}getAllTasks(){return Array.from(this.tasks.values())}getTasksByNamespace(t){const e=this.namespaceIndex.get(t);return e?Array.from(e).map(t=>this.tasks.get(t)).filter(Boolean):[]}clear(){this.tasks.clear(),this.namespaceIndex.clear()}}function n(t,e,s){const i=new Set;if("*"===t){for(let t=e;t<=s;t++)i.add(t);return Array.from(i).sort((t,e)=>t-e)}const r=t.split(",");for(const n of r)if(n.includes("/")){const[t,r]=n.split("/"),o=parseInt(r,10);if("*"===t)for(let n=e;n<=s;n+=o)i.add(n);else if(t.includes("-")){const[r,n]=t.split("-").map(Number);if(r<e||n>s)throw new Error(`Value out of range: ${r}-${n} (expected ${e}-${s})`);for(let t=r;t<=n;t+=o)i.add(t)}else{const r=parseInt(t,10);if(r<e||r>s)throw new Error(`Value out of range: ${r} (expected ${e}-${s})`);for(let t=r;t<=s;t+=o)i.add(t)}}else if(n.includes("-")){const[t,r]=n.split("-").map(Number);if(t<e||r>s)throw new Error(`Value out of range: ${t}-${r} (expected ${e}-${s})`);for(let e=t;e<=r;e++)i.add(e)}else{const t=parseInt(n,10);if(t<e||t>s)throw new Error(`Value out of range: ${t} (expected ${e}-${s})`);i.add(t)}return Array.from(i).sort((t,e)=>t-e)}function o(t){const e=t.trim().split(/\s+/);let s,i,r,o,a,l;if(5===e.length)s=[0],[i,r,o,a,l]=[n(e[0],0,59),n(e[1],0,23),n(e[2],1,31),n(e[3],1,12),n(e[4],0,6)];else{if(6!==e.length)throw new Error(`Invalid cron expression: expected 5 or 6 fields, got ${e.length}`);[s,i,r,o,a,l]=[n(e[0],0,59),n(e[1],0,59),n(e[2],0,23),n(e[3],1,31),n(e[4],1,12),n(e[5],0,6)]}return{second:s,minute:i,hour:r,dayOfMonth:o,month:a,dayOfWeek:l}}function a(t,e){const s=t.getSeconds(),i=t.getMinutes(),r=t.getHours(),n=t.getDate(),o=t.getMonth()+1,a=t.getDay();return e.second.includes(s)&&e.minute.includes(i)&&e.hour.includes(r)&&e.month.includes(o)&&(e.dayOfMonth.includes(n)||e.dayOfWeek.includes(a))}function l(t){const e=t.match(/^(\d+)(s|m|h|d)$/);if(e){const t=parseInt(e[1],10);let s=1e3;switch(e[2]){case"s":s=1e3;break;case"m":s=6e4;break;case"h":s=36e5;break;case"d":s=864e5}return{type:"interval",value:t*s}}try{return function(t){try{o(t)}catch(e){throw new Error(`Invalid cron expression: ${t}`)}}(t),{type:"cron",value:t}}catch(s){throw new Error(`无效的调度格式: "${t}". 必须是有效的 Cron 表达式或间隔字符串 (例如 "10s")。`)}}function c(t,e){let s;if(s="string"==typeof t?l(t):t,"interval"===s.type){const t=s.value,i=(null==e?void 0:e.lastRun)||Date.now();return new Date(i+t)}{const t=s.value;try{return function(t){var e,s,i;const r=o(t);let n=new Date((new Date).getTime()+1e3);n.setMilliseconds(0);let l=0;for(;l<126144e3;){if(a(n,r))return n;const t=n.getSeconds(),o=n.getMinutes(),c=n.getHours();if(!r.second.includes(t)){const s=null!=(e=r.second.find(e=>e>t))?e:r.second[0];s>t?n.setSeconds(s):n.setMinutes(o+1,s),n.setMilliseconds(0),l++;continue}if(!r.minute.includes(o)){const t=null!=(s=r.minute.find(t=>t>o))?s:r.minute[0];t>o?n.setMinutes(t,r.second[0]):n.setHours(c+1,t,r.second[0]),n.setMilliseconds(0),l++;continue}if(!r.hour.includes(c)){const t=null!=(i=r.hour.find(t=>t>c))?i:r.hour[0];t>c||n.setDate(n.getDate()+1),n.setHours(t,r.minute[0],r.second[0]),n.setMilliseconds(0),l++;continue}n=new Date(n.getTime()+1e3),l++}throw new Error(`Could not find next run time for cron expression: ${t}`)}(t,null==e||e.timezone)}catch(i){throw new Error(`无法计算下一次 Cron 运行时间: ${t}`)}}}class u{static getDelay(t,e){if(!e)return-1;const{maxAttempts:s,initialDelay:i,factor:r=2}=e;return t>=s?-1:i*Math.pow(r,t)}}let d=class{constructor(t,s={},i){e(this,"registry"),e(this,"config"),e(this,"defaultTimerStrategy"),e(this,"timerStrategyFactory"),e(this,"taskTimerStrategies"),e(this,"running"),e(this,"timers"),e(this,"listeners"),e(this,"eventListeners"),this.registry=new r,this.defaultTimerStrategy=t,this.timerStrategyFactory=i,this.taskTimerStrategies=new Map,this.config={debug:!1,maxHistory:50,...s},this.running=!1,this.timers=new Map,this.listeners=[],this.eventListeners=new Map,this.config.plugins&&Array.isArray(this.config.plugins)&&this.config.plugins.forEach(t=>{try{this.log(`Initializing plugin: ${t.name}`),t.init(this)}catch(e){console.warn(`[HyperScheduler] Failed to initialize plugin ${t.name}:`,e)}})}subscribe(t){return this.listeners.push(t),()=>{this.listeners=this.listeners.filter(e=>e!==t)}}on(t,e){return this.eventListeners.has(t)||this.eventListeners.set(t,new Set),this.eventListeners.get(t).add(e),()=>{var s;null==(s=this.eventListeners.get(t))||s.delete(e)}}emit(t,e){const s=this.eventListeners.get(t);s&&s.forEach(t=>t(e))}getTimerStrategy(t){var e;const s=null==(e=t.options)?void 0:e.driver,i=this.config.driver,r=s||i;if(!r||!this.timerStrategyFactory)return this.defaultTimerStrategy;const n=`${t.id}_${r}`;if(this.taskTimerStrategies.has(n))return this.taskTimerStrategies.get(n);const o=this.timerStrategyFactory(r);return this.taskTimerStrategies.set(n,o),o}notify(){if(this.listeners.length>0){const t=this.registry.getAllTasks();this.listeners.forEach(e=>e(t))}}createTask(t){var e;!function(t){if(!t||"string"!=typeof t||""===t.trim())throw new Error("Task ID must be a non-empty string.")}(t.id),l(t.schedule);const r={...t,tags:t.tags||[],status:s.STOPPED,history:[],executionCount:0};this.registry.addTask(r),this.log(`Task created: ${r.id}`),this.emit(i.TASK_REGISTERED,{taskId:r.id,task:r}),this.notify(),this.running&&(r.status=s.IDLE,(null==(e=r.options)?void 0:e.runImmediately)&&this.triggerTask(r.id),this.scheduleTask(r))}deleteTask(t){this.stopTask(t);const e=this.registry.deleteTask(t);return e&&(this.log(`Task deleted: ${t}`),this.emit(i.TASK_REMOVED,{taskId:t}),this.notify()),e}startTask(t){const e=this.registry.getTask(t);if(!e)throw new Error(`Task not found: ${t}`);if(e.status===s.RUNNING)return;const r=this.timers.get(t);r&&(this.getTimerStrategy(e).cancel(r),this.timers.delete(t)),e.status=s.IDLE,this.log(`Starting task: ${t}`),this.emit(i.TASK_STARTED,{taskId:t,task:e}),this.notify(),this.scheduleTaskForce(e)}scheduleTaskForce(t){var e;try{const s=c(t.schedule,{timezone:(null==(e=t.options)?void 0:e.timezone)||this.config.timezone,lastRun:t.lastRun});t.nextRun=s.getTime();const i=Date.now(),r=Math.max(0,s.getTime()-i);this.log(`Scheduling task ${t.id} for ${s.toISOString()} (in ${r}ms)`);const n=this.getTimerStrategy(t).schedule(()=>{this.executeTaskIndividual(t)},r);this.timers.set(t.id,n)}catch(i){this.log(`Error scheduling task ${t.id}: ${i}`),t.status=s.ERROR,this.notify()}}async executeTaskIndividual(t,e=0){var r,n;if(this.timers.delete(t.id),t.status===s.STOPPED)return;t.status=s.RUNNING,t.lastRun=Date.now(),t.executionCount=(t.executionCount||0)+1;const o=Date.now();this.log(`Executing task: ${t.id} (Attempt ${e})`),this.emit(i.TASK_STARTED,{taskId:t.id,task:t}),this.notify();try{await t.handler();const e=Date.now()-o;this.recordHistory(t,{timestamp:o,duration:e,success:!0}),t.status=s.IDLE,this.log(`Task execution success: ${t.id}`),this.emit(i.TASK_COMPLETED,{taskId:t.id,task:t,duration:e}),this.notify(),this.scheduleTaskForce(t)}catch(a){const c=Date.now()-o;if(this.recordHistory(t,{timestamp:o,duration:c,success:!1,error:a.message}),this.log(`Task execution failed: ${t.id} - ${a.message}`),this.emit(i.TASK_FAILED,{taskId:t.id,task:t,error:a.message,duration:c}),null==(r=t.options)?void 0:r.onError)try{t.options.onError(a,t.id)}catch(l){this.log(`onError callback failed: ${l}`)}const d=u.getDelay(e,null==(n=t.options)?void 0:n.retry);if(d>=0){this.log(`Retrying task ${t.id} in ${d}ms (Attempt ${e+1})`);const i=this.getTimerStrategy(t).schedule(()=>{this.executeTaskIndividual(t,e+1)},d);this.timers.set(t.id,i),t.status=s.ERROR,this.notify()}else t.status=s.ERROR,this.notify(),this.scheduleTaskForce(t)}}stopTask(t){const e=this.registry.getTask(t),r=this.timers.get(t);r&&e?(this.getTimerStrategy(e).cancel(r),this.timers.delete(t)):r&&(this.defaultTimerStrategy.cancel(r),this.timers.delete(t)),e&&(e.status=s.STOPPED,this.log(`Task stopped: ${t}`),this.emit(i.TASK_STOPPED,{taskId:t,task:e}),this.notify())}getTask(t){return this.registry.getTask(t)}getAllTasks(t){return t?this.registry.getTasksByNamespace(t):this.registry.getAllTasks()}isRunning(){return this.running}getTaskDriver(t){var e;const s=this.registry.getTask(t);return s?(null==(e=s.options)?void 0:e.driver)||this.config.driver||"worker":this.config.driver||"worker"}getGlobalDriver(){return this.config.driver||"worker"}async triggerTask(t){const e=this.getTask(t);if(!e)return;if(e.status===s.RUNNING)return;const r=e.status;e.status=s.RUNNING,e.lastRun=Date.now(),e.executionCount=(e.executionCount||0)+1;const n=Date.now();this.log(`Triggering task: ${e.id}`),this.emit(i.TASK_STARTED,{taskId:e.id,task:e}),this.notify();try{await e.handler();const t=Date.now()-n;this.recordHistory(e,{timestamp:n,duration:t,success:!0}),e.status=r,this.log(`Task trigger success: ${e.id}`),this.emit(i.TASK_COMPLETED,{taskId:e.id,task:e,duration:t}),this.notify()}catch(o){const t=Date.now()-n;this.recordHistory(e,{timestamp:n,duration:t,success:!1,error:o.message}),this.log(`Task trigger failed: ${e.id} - ${o.message}`),this.emit(i.TASK_FAILED,{taskId:e.id,task:e,error:o.message,duration:t}),e.status=r,this.notify()}}start(t){if(!t&&this.running)return;this.log(t?`Scheduler starting for scope: ${t}`:"Scheduler started"),this.emit(i.SCHEDULER_STARTED,{running:!0,scope:t});(t?this.registry.getTasksByNamespace(t):this.registry.getAllTasks()).forEach(t=>{var e;t.status===s.STOPPED&&(t.status=s.IDLE,this.emit(i.TASK_UPDATED,{taskId:t.id,task:t})),t.status!==s.RUNNING&&((null==(e=t.options)?void 0:e.runImmediately)&&this.triggerTask(t.id),this.scheduleTask(t))}),t||(this.running=!0),this.notify()}stop(t){if(!t&&!this.running)return;this.log(t?`Scheduler stopping for scope: ${t}`:"Scheduler stopped"),this.emit(i.SCHEDULER_STOPPED,{running:!1,scope:t});(t?this.registry.getTasksByNamespace(t):this.registry.getAllTasks()).forEach(t=>{const e=this.timers.get(t.id);e&&(this.getTimerStrategy(t).cancel(e),this.timers.delete(t.id)),t.status!==s.STOPPED&&(t.status=s.STOPPED,this.emit(i.TASK_UPDATED,{taskId:t.id,task:t}))}),t||(this.running=!1),this.notify()}scheduleTask(t){var e;try{const s=c(t.schedule,{timezone:(null==(e=t.options)?void 0:e.timezone)||this.config.timezone,lastRun:t.lastRun});t.nextRun=s.getTime();const i=Date.now(),r=Math.max(0,s.getTime()-i);this.log(`Scheduling task ${t.id} for ${s.toISOString()} (in ${r}ms)`);const n=this.getTimerStrategy(t).schedule(()=>{this.executeTask(t)},r);this.timers.set(t.id,n)}catch(i){this.log(`Error scheduling task ${t.id}: ${i}`),t.status=s.ERROR}}async executeTask(t,e=0,r=!1){var n,o;if(this.timers.delete(t.id),!r&&t.status===s.STOPPED)return;t.status=s.RUNNING,t.lastRun=Date.now(),t.executionCount=(t.executionCount||0)+1;const a=Date.now();this.log(`Executing task: ${t.id} (Attempt ${e})`),this.emit(i.TASK_STARTED,{taskId:t.id,task:t}),this.notify();try{await t.handler();const e=Date.now()-a;this.recordHistory(t,{timestamp:a,duration:e,success:!0}),t.status=s.IDLE,this.log(`Task execution success: ${t.id}`),this.emit(i.TASK_COMPLETED,{taskId:t.id,task:t,duration:e}),this.notify(),this.scheduleTask(t)}catch(l){const r=Date.now()-a;if(this.recordHistory(t,{timestamp:a,duration:r,success:!1,error:l.message}),this.log(`Task execution failed: ${t.id} - ${l.message}`),this.emit(i.TASK_FAILED,{taskId:t.id,task:t,error:l.message,duration:r}),null==(n=t.options)?void 0:n.onError)try{t.options.onError(l,t.id)}catch(c){this.log(`onError callback failed: ${c}`)}const d=u.getDelay(e,null==(o=t.options)?void 0:o.retry);if(d>=0){this.log(`Retrying task ${t.id} in ${d}ms (Attempt ${e+1})`);const i=this.getTimerStrategy(t).schedule(()=>{this.executeTask(t,e+1)},d);this.timers.set(t.id,i),t.status=s.ERROR,this.notify()}else t.status=s.ERROR,this.notify(),this.scheduleTask(t)}}recordHistory(t,e){t.history.unshift(e),this.config.maxHistory&&t.history.length>this.config.maxHistory&&t.history.pop()}log(t){this.config.debug&&console.log(`[HyperScheduler] ${t}`)}};class h{schedule(t,e){return setTimeout(t,e)}cancel(t){clearTimeout(t)}}const g="IWZ1bmN0aW9uKCl7InVzZSBzdHJpY3QiO2NvbnN0IGU9bmV3IE1hcDtzZWxmLm9ubWVzc2FnZT1zPT57Y29uc3R7aWQ6dCxkZWxheTpjLHR5cGU6bH09cy5kYXRhO2lmKCJzY2hlZHVsZSI9PT1sKXtjb25zdCBzPXNlbGYuc2V0VGltZW91dCgoKT0+e3NlbGYucG9zdE1lc3NhZ2Uoe2lkOnQsdHlwZToidGljayJ9KSxlLmRlbGV0ZSh0KX0sYyk7ZS5zZXQodCxzKX1lbHNlIGlmKCJjYW5jZWwiPT09bCl7Y29uc3Qgcz1lLmdldCh0KTt2b2lkIDAhPT1zJiYoc2VsZi5jbGVhclRpbWVvdXQocyksZS5kZWxldGUodCkpfX19KCk7Cg==",m="undefined"!=typeof self&&self.Blob&&new Blob([(k=g,Uint8Array.from(atob(k),t=>t.charCodeAt(0)))],{type:"text/javascript;charset=utf-8"});var k;function f(t){let e;try{if(e=m&&(self.URL||self.webkitURL).createObjectURL(m),!e)throw"";const s=new Worker(e,{name:null==t?void 0:t.name});return s.addEventListener("error",()=>{(self.URL||self.webkitURL).revokeObjectURL(e)}),s}catch(s){return new Worker("data:text/javascript;base64,"+g,{name:null==t?void 0:t.name})}finally{e&&(self.URL||self.webkitURL).revokeObjectURL(e)}}class T{constructor(){e(this,"worker"),e(this,"callbacks"),e(this,"nextId"),this.worker=void 0!==f?new f:{postMessage:()=>{},onmessage:null,terminate:()=>{},addEventListener:()=>{},removeEventListener:()=>{},dispatchEvent:()=>!1},this.callbacks=new Map,this.nextId=1,this.worker.onmessage=t=>{const{id:e,type:s}=t.data;if("tick"===s){const t=this.callbacks.get(e);t&&(t(),this.callbacks.delete(e))}}}schedule(t,e){const s=this.nextId++;return this.callbacks.set(s,t),this.worker.postMessage({id:s,delay:e,type:"schedule"}),s}cancel(t){this.worker.postMessage({id:t,type:"cancel"}),this.callbacks.delete(t)}}class p{schedule(t,e){return window.setTimeout(t,e)}cancel(t){window.clearTimeout(t)}}const y="undefined"!=typeof window&&void 0!==window.document;let E=null,S=null;exports.CoreScheduler=d,exports.DevTools=class{constructor(t={}){e(this,"name","DevTools"),e(this,"options"),this.options=t}init(t){"undefined"!=typeof window&&void 0!==window.document&&this.mount(t)}async mount(t){try{await Promise.resolve().then(()=>require("./devtools-CRTqUH_8.cjs")),await customElements.whenDefined("hs-devtools"),this.setupElement(t)}catch(e){console.error("[DevTools] Failed to mount:",e)}}setupElement(t){try{let e=document.querySelector("hs-devtools");e&&e.remove(),e=document.createElement("hs-devtools");const i=this.options;console.log("[DevTools Plugin] options:",JSON.stringify(i)),i.theme&&e.setAttribute("theme",i.theme),i.dockPosition&&e.setAttribute("dock",i.dockPosition),i.language&&e.setAttribute("language",i.language),i.defaultZoom&&e.setAttribute("default-zoom",i.defaultZoom.toString()),i.trigger&&(i.trigger.backgroundColor&&e.setAttribute("trigger-bg",i.trigger.backgroundColor),i.trigger.textColor&&e.setAttribute("trigger-color",i.trigger.textColor),i.trigger.position&&e.setAttribute("trigger-position",i.trigger.position)),console.log("[DevTools Plugin] attributes set:",e.getAttribute("dock"),e.getAttribute("trigger-position")),document.body.appendChild(e),"function"==typeof e.setScheduler?e.setScheduler({getTasks:()=>t.getAllTasks().map(e=>{var i;return{id:e.id,status:e.status,lastRun:e.lastRun||null,nextRun:e.nextRun||null,executionCount:e.executionCount||0,schedule:e.schedule,tags:e.tags||[],error:e.status===s.ERROR?"Execution failed":null,driver:t.getTaskDriver(e.id),namespace:(null==(i=e.options)?void 0:i.namespace)||"default"}}),on:(e,s)=>t.on(e,s),isRunning:()=>t.isRunning(),trigger:e=>t.triggerTask(e),pause:e=>t.stopTask(e),resume:e=>t.startTask(e),remove:e=>t.deleteTask(e)}):console.warn("[DevTools] hs-devtools element does not have setScheduler method.")}catch(e){console.error("[DevTools] Failed to setup element:",e)}}},exports.Scheduler=class extends d{constructor(t){super(function(t){if(y)return"main"===((null==t?void 0:t.driver)||"worker")?(S||(S=new p),S):(E||(E=new T),E);return new h}(t),t,function(){if(y)return t=>"main"===t?(S||(S=new p),S):(E||(E=new T),E)}())}},exports.SchedulerEvents=i,exports.TaskStatus=s;
package/dist/index.js CHANGED
@@ -936,7 +936,7 @@ class DevTools {
936
936
  }
937
937
  async mount(scheduler) {
938
938
  try {
939
- await import("./devtools-_ah1nNTk.js");
939
+ await import("./devtools-B029_YOS.js");
940
940
  await customElements.whenDefined("hs-devtools");
941
941
  this.setupElement(scheduler);
942
942
  } catch (e) {