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: