diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..affe8fb
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,93 @@
+name: build
+
+on:
+ workflow_dispatch:
+ push:
+ branches:
+ - main
+ - patch-1
+ paths:
+ - ui/**/*
+ - .github/**/*
+
+# schedule:
+## https://help.github.com/en/actions/automating-your-workflow-with-github-actions/events-that-trigger-workflows#scheduled-events-schedule
+## ┌───────────── minute (0 - 59)
+## │ ┌───────────── hour (0 - 23)
+## │ │ ┌───────────── day of the month (1 - 31)
+## │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
+## │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
+## │ │ │ │ │
+## │ │ │ │ │
+## │ │ │ │ │
+## * * * * *
+# - cron: '* * 1 * *'
+# - cron: '* * 15 * *'
+
+jobs:
+ main-action:
+ runs-on: ubuntu-latest
+ if: "!contains(github.event.head_commit.message, '[skip ci]')"
+
+ strategy:
+ matrix:
+ node-version: [ 22 ]
+
+ steps:
+ -
+ uses: actions/checkout@main
+ with:
+ fetch-depth: 2
+ token: ${{ secrets.GITHUB_TOKEN }}
+ -
+ name: Set up Node.js ${{ matrix.node-version }}
+ uses: actions/setup-node@main
+ with:
+ node-version: ${{ matrix.node-version }}
+ -
+ name: get yarn cache dir
+ id: yarn-cache
+ run: echo "::set-output name=dir::$(yarn cache dir)"
+ -
+ name: set cache id
+ id: id-cache
+ run: echo "::set-output name=id::${GITHUB_SHA}"
+ -
+ name: echo var
+ run: |
+ echo ${{ steps.yarn-cache.outputs.dir }}
+ echo ${{ steps.id-cache.outputs.id }}
+ echo ${GITHUB_SHA}
+ -
+ name: yarn cache
+ uses: bluelovers/github-actions-cache@2020011001
+ with:
+ path: ${{ steps.yarn-cache.outputs.dir }}
+ key: ${{ runner.os }}-yarn-${{ steps.id-cache.outputs.id }}
+ restore-keys: |
+ ${{ runner.os }}-yarn-
+ -
+ name: setup git config
+ run: |
+ git config --local user.email "action@github.com"
+ git config --local user.name "GitHub Action"
+ -
+ name: install deps
+ run: |
+ cd ./ui
+ yarn install --frozen-lockfile
+ yarn run ci:install
+ -
+ name: run script
+ if: success()
+ # env:
+ run: |
+ cd ./ui
+ yarn run ci:build
+ -
+ name: Push changes
+ if: success()
+ uses: ad-m/github-push-action@master
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ branch: ${{ github.ref }}
diff --git a/agent_scheduler/shared_opts_backup.py b/agent_scheduler/shared_opts_backup.py
new file mode 100644
index 0000000..eafd908
--- /dev/null
+++ b/agent_scheduler/shared_opts_backup.py
@@ -0,0 +1,118 @@
+from pathlib import Path, PurePath
+import gradio as gr
+from typing import Union
+
+
+def simplify_path(input_path: Union[PurePath, str]) -> Path:
+ # 如果输入是字符串,将其转换为 Path 对象
+ if isinstance(input_path, str):
+ input_path = Path(input_path)
+
+ parts = []
+ for part in input_path.parts:
+ if part == '..':
+ if parts and parts[-1] != '..' and parts[-1] != '/' and parts[-1] != input_path.root:
+ parts.pop()
+ else:
+ parts.append(part)
+ elif part != '.' and part != '':
+ parts.append(part)
+
+ # 如果路径是绝对路径,保留根路径
+ if input_path.is_absolute():
+ simplified_path = Path(input_path.root, *parts)
+ else:
+ simplified_path = Path(*parts)
+
+ return simplified_path
+
+class SharedOptsBackup:
+ """
+ A class used to backup and restore shared options.
+
+ Attributes
+ ----------
+ shared_opts : dict
+ The shared options to be backed up and restored.
+ backup : dict
+ A dictionary to store the backup of shared options.
+
+ Methods
+ -------
+ set_shared_opts_core(key: str, value)
+ Sets a shared option and backs it up only if it is not already backed up.
+
+ set_shared_opts(**kwargs)
+ Sets multiple shared options and backs them up.
+
+ restore_shared_opts()
+ Restores the shared options from the backup.
+ """
+
+ def __init__(self, shared_opts):
+ """
+ Constructs all the necessary attributes for the SharedOptsBackup object.
+
+ Parameters
+ ----------
+ shared_opts : dict
+ The shared options to be backed up and restored.
+ """
+ self.shared_opts = shared_opts
+ self.backup = {}
+
+ # gr.Info(f"[AgentScheduler] backup shared opts")
+
+ def set_shared_opts_core(self, key: str, value):
+ """
+ Sets a shared option and backs it up only if it is not already backed up.
+
+ Parameters
+ ----------
+ key : str
+ The key of the shared option to be set.
+ value : any
+ The value to be set for the shared option.
+ """
+ if not self.is_backup_exists(key):
+ old = getattr(self.shared_opts, key, None)
+ self.backup[key] = old
+ print(f"[AgentScheduler] [backup] {key}: {old}")
+
+ if isinstance(value, (Path, PurePath)):
+ if key != "control_net_detectedmap_dir":
+ value = simplify_path(value)
+
+ value = str(value.as_posix())
+
+ self.shared_opts.set(key, value)
+ if self.backup[key] != value:
+ print(f"\33[32m[AgentScheduler] [change] {key}: {value}\33[0m")
+
+ def set_shared_opts(self, **kwargs):
+ """
+ Sets multiple shared options and backs them up.
+
+ Parameters
+ ----------
+ kwargs : dict
+ The key-value pairs of shared options to be set.
+ """
+ for attr, value in kwargs.items():
+ self.set_shared_opts_core(attr, value)
+
+ def is_backup_exists(self, key: str):
+ return key in self.backup
+
+ def get_backup_value(self, key: str):
+ return self.backup.get(key) if self.is_backup_exists(key) else getattr(self.shared_opts, key, None)
+
+ def restore_shared_opts(self):
+ """
+ Restores the shared options from the backup.
+ """
+ for attr, value in self.backup.items():
+ self.shared_opts.set(attr, value)
+ print(f"\33[32m[AgentScheduler] [restore] {attr}: {value}\33[0m")
+
+ # gr.Info(f"[AgentScheduler] restore shared opts")
diff --git a/agent_scheduler/task_runner.py b/agent_scheduler/task_runner.py
index 9b58136..770c51c 100644
--- a/agent_scheduler/task_runner.py
+++ b/agent_scheduler/task_runner.py
@@ -22,6 +22,7 @@
StableDiffusionTxt2ImgProcessingAPI,
StableDiffusionImg2ImgProcessingAPI,
)
+from modules.devices import torch_gc
from .db import TaskStatus, Task, task_manager
from .helpers import (
@@ -43,7 +44,8 @@
map_ui_task_args_list_to_named_args,
map_named_args_to_ui_task_args_list,
)
-
+from .shared_opts_backup import SharedOptsBackup
+from pathlib import Path
class OutOfMemoryError(Exception):
def __init__(self, message="CUDA out of memory") -> None:
@@ -67,13 +69,15 @@ class ParsedTaskArgs(BaseModel):
class TaskRunner:
instance = None
- def __init__(self, UiControlNetUnit=None):
+ def __init__(self, UiControlNetUnit=None, block: gr.Blocks=None):
self.UiControlNetUnit = UiControlNetUnit
self.__total_pending_tasks: int = 0
self.__current_thread: threading.Thread = None
self.__api = Api(FastAPI(), queue_lock)
+ self.__block = block
+
self.__saved_images_path: List[str] = []
script_callbacks.on_image_saved(self.__on_image_saved)
@@ -332,6 +336,7 @@ def execute_task(self, task: Task, get_next_task: Callable[[], Task]):
if progress.current_task is None:
task_id = task.id
is_img2img = task.type == "img2img"
+ # gr.Error(f"[AgentScheduler] Executing task {task_id}")
log.info(f"[AgentScheduler] Executing task {task_id}")
task_args = self.parse_task_args(task)
@@ -345,20 +350,88 @@ def execute_task(self, task: Task, get_next_task: Callable[[], Task]):
self.__saved_images_path = []
self.__run_callbacks("task_started", task_id, **task_meta)
- # enable image saving
- samples_save = shared.opts.samples_save
- shared.opts.samples_save = True
+ shared_opts_backup = SharedOptsBackup(shared.opts)
+
+ shared_opts_backup.set_shared_opts(samples_save=True, grid_save=True)
+
+ def change_output_dir():
+ if is_img2img:
+ key_samples = "outdir_img2img_samples"
+ key_grids = "outdir_img2img_grids"
+ else:
+ key_samples = "outdir_txt2img_samples"
+ key_grids = "outdir_txt2img_grids"
+
+ outdir_path_samples_old = Path(shared_opts_backup.get_backup_value(key_samples))
+
+ outdir_path_root_top = outdir_path_samples_old.joinpath('..')
+ outdir_path_root = outdir_path_root_top.joinpath('agent-scheduler')
+
+ outdir_path_root_task = outdir_path_root
+
+ save_to_dirs = False
+ if save_to_dirs:
+ directories_filename_pattern_new = "[datetime<%Y-%m-%d_%H-%M-%S>]_" + str(task_id)
+
+ shared_opts_backup.set_shared_opts_core("directories_filename_pattern",
+ directories_filename_pattern_new)
+ else:
+ outdir_label = time.strftime("%Y-%m-%d/%H-%M-%S") + '_' + str(task_id)
+
+ outdir_path_root_task = outdir_path_root.joinpath(outdir_label)
+
+ outdir_path_samples_new = outdir_path_root_task.joinpath(outdir_path_samples_old.name)
+
+ def _output_to_root_task(key: str):
+ name = Path(shared_opts_backup.get_backup_value(key)).name
+ shared_opts_backup.set_shared_opts_core(key, outdir_path_root_task.joinpath(name))
+
+ shared_opts_backup.set_shared_opts_core(key_samples, outdir_path_samples_new)
+
+ _output_to_root_task(key_grids)
+ _output_to_root_task("outdir_init_images")
+ _output_to_root_task("ad_save_images_dir")
+
+ shared_opts_backup.set_shared_opts_core("grid_only_if_multiple", True)
+ shared_opts_backup.set_shared_opts_core("grid_prevent_empty_spots", True)
+
+ shared_opts_backup.set_shared_opts_core("save_to_dirs", save_to_dirs)
+ shared_opts_backup.set_shared_opts_core("grid_save_to_dirs", save_to_dirs)
+
+ control_net_detectedmap_dir = Path("..").joinpath("detected_maps")
+
+ shared_opts_backup.set_shared_opts_core("control_net_detectedmap_dir", control_net_detectedmap_dir)
+ shared_opts_backup.set_shared_opts_core("control_net_detectmap_autosaving", True)
+
+ shared_opts_backup.set_shared_opts_core("save_mask", True)
+ shared_opts_backup.set_shared_opts_core("save_mask_composite", True)
+
+ shared_opts_backup.set_shared_opts_core("dp_write_prompts_to_file", False)
+
+ shared_opts_backup.set_shared_opts_core("enable_pnginfo", True)
+ shared_opts_backup.set_shared_opts_core("save_txt", True)
+
+ shared_opts_backup.set_shared_opts_core("save_images_before_highres_fix", True)
+
+ shared_opts_backup.set_shared_opts_core("save_init_img", is_img2img)
+
+ if is_img2img:
+ shared_opts_backup.set_shared_opts_core("ad_save_previews", True)
+ shared_opts_backup.set_shared_opts_core("ad_save_images_before", True)
+
+ change_output_dir()
res = self.__execute_task(task_id, is_img2img, task_args)
- # disable image saving
- shared.opts.samples_save = samples_save
+ shared_opts_backup.restore_shared_opts()
if not res or isinstance(res, Exception):
if isinstance(res, OutOfMemoryError):
+ gr.Error(f"[AgentScheduler] Task {task_id} failed: CUDA OOM. Queue will be paused.")
log.error(f"[AgentScheduler] Task {task_id} failed: CUDA OOM. Queue will be paused.")
shared.opts.queue_paused = True
else:
+ gr.Error(f"[AgentScheduler] Task {task_id} failed: {res}")
log.error(f"[AgentScheduler] Task {task_id} failed: {res}")
log.debug(traceback.format_exc())
@@ -401,6 +474,7 @@ def execute_task(self, task: Task, get_next_task: Callable[[], Task]):
result=result,
**task_meta,
)
+ # gr.Info(f"[AgentScheduler] Task {task_id} finished")
self.__saved_images_path = []
else:
@@ -416,10 +490,12 @@ def execute_task(self, task: Task, get_next_task: Callable[[], Task]):
def execute_pending_tasks_threading(self):
if self.paused:
+ gr.Warning("[AgentScheduler] Runner is paused")
log.info("[AgentScheduler] Runner is paused")
return
if self.is_executing_task:
+ # gr.Warning("[AgentScheduler] Runner already started")
log.info("[AgentScheduler] Runner already started")
return
@@ -465,6 +541,8 @@ def __execute_ui_task(self, task_id: str, is_img2img: bool, *args):
res = OutOfMemoryError()
else:
res = result[1]
+
+
except Exception as e:
res = e
finally:
@@ -581,6 +659,26 @@ def __on_completed(self):
elif action == "Stop webui":
log.info("[AgentScheduler] Stopping webui...")
_exit(0)
+ elif action == "Restart webui":
+ log.info("[AgentScheduler] Restarting webui...")
+ with self.__block:
+ gr.HTML("""
+
+ """)
+ shared.state.request_restart()
if command:
subprocess.Popen(command)
@@ -616,16 +714,25 @@ def on_task_cleared(self, callback: Callable):
self.script_callbacks["task_cleared"].append(callback)
def __run_callbacks(self, name: str, *args, **kwargs):
+ # print(f"[AgentScheduler] __run_callbacks {name}...")
+
for callback in self.script_callbacks[name]:
callback(*args, **kwargs)
+ if name == "task_finished" or name == "task_started":
+ print(f"[AgentScheduler] {name} torch_gc...")
+ try:
+ torch_gc()
+ except Exception as e:
+ print(e)
+
def get_instance(block) -> TaskRunner:
if TaskRunner.instance is None:
if block is not None:
txt2img_submit_button = get_component_by_elem_id(block, "txt2img_generate")
UiControlNetUnit = detect_control_net(block, txt2img_submit_button)
- TaskRunner(UiControlNetUnit)
+ TaskRunner(UiControlNetUnit, block)
else:
TaskRunner()
diff --git a/javascript/agent-scheduler.iife.js b/javascript/agent-scheduler.iife.js
index 9135cc6..b516914 100644
--- a/javascript/agent-scheduler.iife.js
+++ b/javascript/agent-scheduler.iife.js
@@ -1,31 +1,25 @@
-(function(){"use strict";/**
- * @ag-grid-community/all-modules - Advanced Data Grid / Data Table supporting Javascript / Typescript / React / Angular / Vue * @version v31.1.1
- * @link https://www.ag-grid.com/
- * @license MIT
- */function ct(n){return n==null||n===""?null:n}function P(n,t){return t===void 0&&(t=!1),n!=null&&(n!==""||t)}function H(n){return!P(n)}function Ge(n){return n==null||n.length===0}function zr(n){return n!=null&&typeof n.toString=="function"?n.toString():null}function Mt(n){if(n!==void 0){if(n===null||n==="")return null;if(typeof n=="number")return isNaN(n)?void 0:n;var t=parseInt(n,10);return isNaN(t)?void 0:t}}function xo(n){if(n!==void 0)return n===null||n===""?!1:typeof n=="boolean"?n:/true/i.test(n)}function yc(n){if(!(n==null||n===""))return n}function Yi(n,t){var e=n?JSON.stringify(n):null,r=t?JSON.stringify(t):null;return e===r}function mc(n,t,e){e===void 0&&(e=!1);var r=n==null,o=t==null;if(n&&n.toNumber&&(n=n.toNumber()),t&&t.toNumber&&(t=t.toNumber()),r&&o)return 0;if(r)return-1;if(o)return 1;function i(s,a){return s>a?1:s=n.length&&(n=void 0),{value:n&&n[r++],done:!n}}};throw new TypeError(t?"Object is not iterable.":"Symbol.iterator is not defined.")},Ec=function(n,t){var e=typeof Symbol=="function"&&n[Symbol.iterator];if(!e)return n;var r=e.call(n),o,i=[],s;try{for(;(t===void 0||t-- >0)&&!(o=r.next()).done;)i.push(o.value)}catch(a){s={error:a}}finally{try{o&&!o.done&&(e=r.return)&&e.call(r)}finally{if(s)throw s.error}}return i};function ye(n,t){var e,r;if(n!=null){if(Array.isArray(n)){for(var o=0;o=0)){var i=e[o],s=Go(i)&&i.constructor===Object;s?r[o]=No(i):r[o]=i}}),r}}function It(n){if(!n)return[];var t=Object;if(typeof t.values=="function")return t.values(n);var e=[];for(var r in n)n.hasOwnProperty(r)&&n.propertyIsEnumerable(r)&&e.push(n[r]);return e}function Ve(n,t,e,r){e===void 0&&(e=!0),r===void 0&&(r=!1),P(t)&&ye(t,function(o,i){var s=n[o];if(s!==i){if(r){var a=s==null&&i!=null;if(a){var l=typeof i=="object"&&i.constructor===Object,u=l;u&&(s={},n[o]=s)}}Go(i)&&Go(s)&&!Array.isArray(s)?Ve(s,i,e,r):(e||i!==void 0)&&(n[o]=i)}})}function wr(n,t,e){if(!(!t||!n)){if(!e)return n[t];for(var r=t.split("."),o=n,i=0;ie in t?Ar(t,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):t[e]=i,N=(t,e)=>{for(var i in e||(e={}))Dl.call(e,i)&&Tl(t,i,e[i]);if(Co)for(var i of Co(e))bl.call(e,i)&&Tl(t,i,e[i]);return t},Z=(t,e)=>Gh(t,Oh(e)),Vh=(t,e)=>{var i={};for(var s in t)Dl.call(t,s)&&e.indexOf(s)<0&&(i[s]=t[s]);if(t!=null&&Co)for(var s of Co(t))e.indexOf(s)<0&&bl.call(t,s)&&(i[s]=t[s]);return i},ge=(t,e)=>{for(var i in e)Ar(t,i,{get:e[i],enumerable:!0})},d=(t,e,i,s)=>{for(var o=s>1?void 0:s?_h(e,i):e,r=t.length-1,n;r>=0;r--)(n=t[r])&&(o=(s?n(e,i,o):n(o))||o);return s&&o&&Ar(e,i,o),o},tt=(t,e)=>(i,s)=>e(i,s,t),Al={};ge(Al,{attrToBoolean:()=>vo,attrToNumber:()=>Nt,attrToString:()=>Hh,defaultComparator:()=>kh,exists:()=>D,jsonEquals:()=>Pr,makeNull:()=>ht,missing:()=>G,missingOrEmpty:()=>Ue,toStringOrNull:()=>Cs,values:()=>Yt});function ht(t){return t==null||t===""?null:t}function D(t,e=!1){return t!=null&&(t!==""||e)}function G(t){return!D(t)}function Ue(t){return t==null||t.length===0}function Cs(t){return t!=null&&typeof t.toString=="function"?t.toString():null}function Nt(t){if(t===void 0)return;if(t===null||t==="")return null;if(typeof t=="number")return isNaN(t)?void 0:t;const e=parseInt(t,10);return isNaN(e)?void 0:e}function vo(t){if(t!==void 0)return t===null||t===""?!1:typeof t=="boolean"?t:/true/i.test(t)}function Hh(t){if(!(t==null||t===""))return t}function Pr(t,e){const i=t?JSON.stringify(t):null,s=e?JSON.stringify(e):null;return i===s}function kh(t,e,i=!1){const s=t==null,o=e==null;if(t&&t.toNumber&&(t=t.toNumber()),e&&e.toNumber&&(e=e.toNumber()),s&&o)return 0;if(s)return-1;if(o)return 1;function r(n,l){return n>l?1:ne.push(i)),e}return Object.values(t)}var Bh=class{constructor(){this.existingKeys={}}addExistingKeys(t){for(let e=0;eFr,deepCloneDefinition:()=>wo,getAllValuesInObject:()=>xt,getValueUsingField:()=>Ii,isNonNullObject:()=>So,iterateObject:()=>ve,mergeDeep:()=>Pe,removeAllReferences:()=>Fl});function ve(t,e){if(t!=null){if(Array.isArray(t)){for(let i=0;i{if(e&&e.indexOf(o)>=0)return;const r=i[o];So(r)&&r.constructor===Object?s[o]=wo(r):s[o]=r}),s}function xt(t){if(!t)return[];const e=Object;if(typeof e.values=="function")return e.values(t);const i=[];for(const s in t)t.hasOwnProperty(s)&&t.propertyIsEnumerable(s)&&i.push(t[s]);return i}function Pe(t,e,i=!0,s=!1){D(e)&&ve(e,(o,r)=>{let n=t[o];n!==r&&(s&&n==null&&r!=null&&typeof r=="object"&&r.constructor===Object&&(n={},t[o]=n),So(r)&&So(n)&&!Array.isArray(n)?Pe(n,r,i,s):(i||r!==void 0)&&(t[o]=r))})}function Ii(t,e,i){if(!e||!t)return;if(!i)return t[e];const s=e.split(".");let o=t;for(let r=0;r{typeof t[n]=="object"&&!e.includes(n)&&(t[n]=void 0)});const s=Object.getPrototypeOf(t),o={},r=n=>`AG Grid: Grid API function ${n}() cannot be called as the grid has been destroyed.
It is recommended to remove local references to the grid api. Alternatively, check gridApi.isDestroyed() to avoid calling methods against a destroyed grid.
- To run logic when the grid is about to be destroyed use the gridPreDestroy event. See: `).concat(e)};Object.getOwnPropertyNames(r).forEach(function(s){var a=r[s];if(typeof a=="function"&&!t.includes(s)){var l=function(){console.warn(i(s))};o[s]={value:l,writable:!0}}}),Object.defineProperties(n,o)}function Go(n){return typeof n=="object"&&n!==null}var _c=Object.freeze({__proto__:null,iterateObject:ye,cloneObject:qi,deepCloneDefinition:No,getAllValuesInObject:It,mergeDeep:Ve,getValueUsingField:wr,removeAllReferences:ca,isNonNullObject:Go}),pa={};function er(n,t){pa[t]||(n(),pa[t]=!0)}function V(n){er(function(){return console.warn("AG Grid: "+n)},n)}function pt(n){er(function(){return console.error("AG Grid: "+n)},n)}function Vo(n){if(n.name)return n.name;var t=/function\s+([^\(]+)/.exec(n.toString());return t&&t.length===2?t[1].trim():null}function Ho(n){return!!(n&&n.constructor&&n.call&&n.apply)}function da(n){ha(n,400)}var Qi=[],Xi=!1;function Ji(n){Qi.push(n),!Xi&&(Xi=!0,window.setTimeout(function(){var t=Qi.slice();Qi.length=0,Xi=!1,t.forEach(function(e){return e()})},0))}function ha(n,t){t===void 0&&(t=0),n.length>0&&window.setTimeout(function(){return n.forEach(function(e){return e()})},t)}function He(n,t){var e;return function(){for(var r=[],o=0;oe;(n()||l)&&(t(),s=!0,i!=null&&(window.clearInterval(i),i=null),l&&r&&console.warn(r))};a(),s||(i=window.setInterval(a,10))}function Rc(){for(var n=[],t=0;t0)&&!(o=r.next()).done;)i.push(o.value)}catch(a){s={error:a}}finally{try{o&&!o.done&&(e=r.return)&&e.call(r)}finally{if(s)throw s.error}}return i},fa=function(n,t,e){if(e||arguments.length===2)for(var r=0,o=t.length,i;r{if(typeof s[n]=="function"&&!e.includes(n)){const a=()=>{console.warn(r(n))};o[n]={value:a,writable:!0}}}),Object.defineProperties(t,o)}function So(t){return typeof t=="object"&&t!==null}var Ll={};ge(Ll,{compose:()=>Wh,debounce:()=>Ee,doOnce:()=>Mi,errorOnce:()=>ut,executeAfter:()=>Nl,executeInAWhile:()=>Ml,executeNextVMTurn:()=>Mr,getFunctionName:()=>Eo,isFunction:()=>yo,noop:()=>Uh,throttle:()=>Nr,waitUntil:()=>xr,warnOnce:()=>x});var Il={};function Mi(t,e){Il[e]||(t(),Il[e]=!0)}function x(t){Mi(()=>console.warn("AG Grid: "+t),t)}function ut(t){Mi(()=>console.error("AG Grid: "+t),t)}function Eo(t){if(t.name)return t.name;const e=/function\s+([^\(]+)/.exec(t.toString());return e&&e.length===2?e[1].trim():null}function yo(t){return!!(t&&t.constructor&&t.call&&t.apply)}function Ml(t){Nl(t,400)}var Lr=[],Ir=!1;function Mr(t){Lr.push(t),!Ir&&(Ir=!0,window.setTimeout(()=>{const e=Lr.slice();Lr.length=0,Ir=!1,e.forEach(i=>i())},0))}function Nl(t,e=0){t.length>0&&window.setTimeout(()=>t.forEach(i=>i()),e)}function Ee(t,e){let i;return function(...s){const o=this;window.clearTimeout(i),i=window.setTimeout(function(){t.apply(o,s)},e)}}function Nr(t,e){let i=0;return function(...s){const o=this,r=new Date().getTime();r-i{const a=new Date().getTime()-o>i;(t()||a)&&(e(),n=!0,r!=null&&(window.clearInterval(r),r=null),a&&s&&console.warn(s))};l(),n||(r=window.setInterval(l,10))}function Wh(...t){return e=>t.reduce((i,s)=>s(i),e)}var Uh=()=>{},xl=(t=>(t.CommunityCoreModule="@ag-grid-community/core",t.InfiniteRowModelModule="@ag-grid-community/infinite-row-model",t.ClientSideRowModelModule="@ag-grid-community/client-side-row-model",t.CsvExportModule="@ag-grid-community/csv-export",t.EnterpriseCoreModule="@ag-grid-enterprise/core",t.RowGroupingModule="@ag-grid-enterprise/row-grouping",t.ColumnsToolPanelModule="@ag-grid-enterprise/column-tool-panel",t.FiltersToolPanelModule="@ag-grid-enterprise/filter-tool-panel",t.MenuModule="@ag-grid-enterprise/menu",t.SetFilterModule="@ag-grid-enterprise/set-filter",t.MultiFilterModule="@ag-grid-enterprise/multi-filter",t.StatusBarModule="@ag-grid-enterprise/status-bar",t.SideBarModule="@ag-grid-enterprise/side-bar",t.RangeSelectionModule="@ag-grid-enterprise/range-selection",t.MasterDetailModule="@ag-grid-enterprise/master-detail",t.RichSelectModule="@ag-grid-enterprise/rich-select",t.GridChartsModule="@ag-grid-enterprise/charts",t.ViewportRowModelModule="@ag-grid-enterprise/viewport-row-model",t.ServerSideRowModelModule="@ag-grid-enterprise/server-side-row-model",t.ExcelExportModule="@ag-grid-enterprise/excel-export",t.ClipboardModule="@ag-grid-enterprise/clipboard",t.SparklinesModule="@ag-grid-enterprise/sparklines",t.AdvancedFilterModule="@ag-grid-enterprise/advanced-filter",t.AngularModule="@ag-grid-community/angular",t.ReactModule="@ag-grid-community/react",t.VueModule="@ag-grid-community/vue",t))(xl||{}),Ro=class Q{static register(e){Q.__register(e,!0,void 0)}static registerModules(e){Q.__registerModules(e,!0,void 0)}static __register(e,i,s){Q.runVersionChecks(e),s!==void 0?(Q.areGridScopedModules=!0,Q.gridModulesMap[s]===void 0&&(Q.gridModulesMap[s]={}),Q.gridModulesMap[s][e.moduleName]=e):Q.globalModulesMap[e.moduleName]=e,Q.setModuleBased(i)}static __unRegisterGridModules(e){delete Q.gridModulesMap[e]}static __registerModules(e,i,s){Q.setModuleBased(i),e&&e.forEach(o=>Q.__register(o,i,s))}static isValidModuleVersion(e){const[i,s]=e.version.split(".")||[],[o,r]=Q.currentModuleVersion.split(".")||[];return i===o&&s===r}static runVersionChecks(e){if(Q.currentModuleVersion||(Q.currentModuleVersion=e.version),e.version?Q.isValidModuleVersion(e)||console.error(`AG Grid: You are using incompatible versions of AG Grid modules. Major and minor versions should always match across modules. '${e.moduleName}' is version ${e.version} but the other modules are version ${this.currentModuleVersion}. Please update all modules to the same version.`):console.error(`AG Grid: You are using incompatible versions of AG Grid modules. Major and minor versions should always match across modules. '${e.moduleName}' is incompatible. Please update all modules to the same version.`),e.validate){const i=e.validate();i.isValid||console.error(`AG Grid: ${i.message}`)}}static setModuleBased(e){Q.moduleBased===void 0?Q.moduleBased=e:Q.moduleBased!==e&&Mi(()=>{console.warn("AG Grid: You are mixing modules (i.e. @ag-grid-community/core) and packages (ag-grid-community) - you can only use one or the other of these mechanisms."),console.warn("Please see https://www.ag-grid.com/javascript-grid/modules/ for more information.")},"ModulePackageCheck")}static __setIsBundled(){Q.isBundled=!0}static __assertRegistered(e,i,s){var o;if(this.__isRegistered(e,s))return!0;const r=i+e;let n;if(Q.isBundled)n=`AG Grid: unable to use ${i} as 'ag-grid-enterprise' has not been loaded. Check you are using the Enterprise bundle: