From 69c99dd13a1dad4b8c336e7adf6fe9c73209ce22 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Tue, 15 Oct 2024 18:15:33 -0400 Subject: [PATCH 01/34] Add button to mute audio when media is playing in webview (#1036) ![image](https://github.com/user-attachments/assets/202636dc-aab5-4164-9729-fecd0cc804ae) Also fixes atom usage for the url bar so it will properly update when any upstream atom states change --- frontend/app/block/block.less | 9 ---- frontend/app/view/webview/webview.less | 13 ++++++ frontend/app/view/webview/webview.tsx | 60 ++++++++++++++++++++++---- 3 files changed, 64 insertions(+), 18 deletions(-) diff --git a/frontend/app/block/block.less b/frontend/app/block/block.less index 967098c69..75c44a1fd 100644 --- a/frontend/app/block/block.less +++ b/frontend/app/block/block.less @@ -221,15 +221,6 @@ font-size: 11px; } } - - .block-frame-div-url, - .block-frame-div-search { - background: rgba(255, 255, 255, 0.1); - - input { - opacity: 1; - } - } } .block-frame-end-icons { diff --git a/frontend/app/view/webview/webview.less b/frontend/app/view/webview/webview.less index 2d42f320e..ed104a478 100644 --- a/frontend/app/view/webview/webview.less +++ b/frontend/app/view/webview/webview.less @@ -15,3 +15,16 @@ transform: translate3d(0, 0, 0); will-change: transform; } + +.block-frame-div-url { + background: rgba(255, 255, 255, 0.1); + + input { + opacity: 1; + } + + .iconbutton { + width: fit-content !important; + margin-right: 5px; + } +} diff --git a/frontend/app/view/webview/webview.tsx b/frontend/app/view/webview/webview.tsx index ceb2f5455..ed3cb33e2 100644 --- a/frontend/app/view/webview/webview.tsx +++ b/frontend/app/view/webview/webview.tsx @@ -46,6 +46,8 @@ export class WebViewModel implements ViewModel { urlInputRef: React.RefObject; nodeModel: NodeModel; endIconButtons?: Atom; + mediaPlaying: PrimitiveAtom; + mediaMuted: PrimitiveAtom; constructor(blockId: string, nodeModel: NodeModel) { this.nodeModel = nodeModel; @@ -70,12 +72,18 @@ export class WebViewModel implements ViewModel { this.urlInputRef = React.createRef(); this.webviewRef = React.createRef(); + this.mediaPlaying = atom(false); + this.mediaMuted = atom(false); + this.viewText = atom((get) => { - let url = get(this.blockAtom)?.meta?.url || get(this.homepageUrl); + const homepageUrl = get(this.homepageUrl); + const metaUrl = get(this.blockAtom)?.meta?.url; const currUrl = get(this.url); - if (currUrl !== undefined) { - url = currUrl; - } + const urlWrapperClassName = get(this.urlWrapperClassName); + const refreshIcon = get(this.refreshIcon); + const mediaPlaying = get(this.mediaPlaying); + const mediaMuted = get(this.mediaMuted); + const url = currUrl ?? metaUrl ?? homepageUrl; return [ { elemtype: "iconbutton", @@ -97,7 +105,7 @@ export class WebViewModel implements ViewModel { }, { elemtype: "div", - className: clsx("block-frame-div-url", get(this.urlWrapperClassName)), + className: clsx("block-frame-div-url", urlWrapperClassName), onMouseOver: this.handleUrlWrapperMouseOver.bind(this), onMouseOut: this.handleUrlWrapperMouseOut.bind(this), children: [ @@ -111,26 +119,31 @@ export class WebViewModel implements ViewModel { onFocus: this.handleFocus.bind(this), onBlur: this.handleBlur.bind(this), }, + mediaPlaying && { + elemtype: "iconbutton", + icon: mediaMuted ? "volume-slash" : "volume", + click: this.handleMuteChange.bind(this), + }, { elemtype: "iconbutton", - icon: get(this.refreshIcon), + icon: refreshIcon, click: this.handleRefresh.bind(this), }, - ], + ].filter((v) => v), }, ] as HeaderElem[]; }); this.endIconButtons = atom((get) => { + const url = get(this.url); return [ { elemtype: "iconbutton", icon: "arrow-up-right-from-square", title: "Open in External Browser", click: () => { - const url = this.getUrl(); if (url != null && url != "") { - return getApi().openExternal(this.getUrl()); + return getApi().openExternal(url); } }, }, @@ -180,6 +193,25 @@ export class WebViewModel implements ViewModel { this.loadUrl(globalStore.get(this.homepageUrl), "home"); } + setMediaPlaying(isPlaying: boolean) { + console.log("setMediaPlaying", isPlaying); + globalStore.set(this.mediaPlaying, isPlaying); + } + + handleMuteChange(e: React.ChangeEvent) { + if (e) { + e.preventDefault(); + e.stopPropagation(); + } + try { + const newMutedVal = !this.webviewRef.current?.isAudioMuted(); + globalStore.set(this.mediaMuted, newMutedVal); + this.webviewRef.current?.setAudioMuted(newMutedVal); + } catch (e) { + console.error("Failed to change mute value", e); + } + } + handleUrlWrapperMouseOver(e: React.MouseEvent) { const urlInputFocused = globalStore.get(this.urlInputFocused); if (e.type === "mouseover" && !urlInputFocused) { @@ -536,6 +568,12 @@ const WebView = memo(({ model }: WebViewProps) => { setDomReady(true); setBgColor(); }; + const handleMediaPlaying = () => { + model.setMediaPlaying(true); + }; + const handleMediaPaused = () => { + model.setMediaPlaying(false); + }; webview.addEventListener("did-navigate-in-page", navigateListener); webview.addEventListener("did-navigate", navigateListener); @@ -546,6 +584,8 @@ const WebView = memo(({ model }: WebViewProps) => { webview.addEventListener("focus", webviewFocus); webview.addEventListener("blur", webviewBlur); webview.addEventListener("dom-ready", handleDomReady); + webview.addEventListener("media-started-playing", handleMediaPlaying); + webview.addEventListener("media-paused", handleMediaPaused); // Clean up event listeners on component unmount return () => { @@ -558,6 +598,8 @@ const WebView = memo(({ model }: WebViewProps) => { webview.removeEventListener("focus", webviewFocus); webview.removeEventListener("blur", webviewBlur); webview.removeEventListener("dom-ready", handleDomReady); + webview.removeEventListener("media-started-playing", handleMediaPlaying); + webview.removeEventListener("media-paused", handleMediaPaused); }; }, []); From 0b3888d90096629586a865b59952cc27bb6f1408 Mon Sep 17 00:00:00 2001 From: Sylvie Crowe <107814465+oneirocosm@users.noreply.github.com> Date: Wed, 16 Oct 2024 09:24:22 -0700 Subject: [PATCH 02/34] Quicklook only for local files on mac (#1039) bug fix so quicklook does attempt to launch for remote directory previews --- frontend/app/view/preview/directorypreview.tsx | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/frontend/app/view/preview/directorypreview.tsx b/frontend/app/view/preview/directorypreview.tsx index 59586c7a2..011cbfc52 100644 --- a/frontend/app/view/preview/directorypreview.tsx +++ b/frontend/app/view/preview/directorypreview.tsx @@ -534,6 +534,7 @@ function DirectoryPreview({ model }: DirectoryPreviewProps) { const [selectedPath, setSelectedPath] = useState(""); const [refreshVersion, setRefreshVersion] = useAtom(model.refreshVersion); const conn = useAtomValue(model.connection); + const blockData = useAtomValue(model.blockAtom); useEffect(() => { model.refreshCallback = () => { @@ -593,7 +594,12 @@ function DirectoryPreview({ model }: DirectoryPreviewProps) { setSearchText((current) => current.slice(0, -1)); return true; } - if (checkKeyPressed(waveEvent, "Space") && searchText == "" && PLATFORM == "darwin") { + if ( + checkKeyPressed(waveEvent, "Space") && + searchText == "" && + PLATFORM == "darwin" && + !blockData?.meta?.connection + ) { getApi().onQuicklook(selectedPath); console.log(selectedPath); return true; From fe70efab8d05cfb57e18843b98d6c40fa2c09336 Mon Sep 17 00:00:00 2001 From: Mike Sawka Date: Wed, 16 Oct 2024 09:57:27 -0700 Subject: [PATCH 03/34] fix bg image css processing (#1044) --- frontend/app/app.tsx | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/frontend/app/app.tsx b/frontend/app/app.tsx index 627e4a20b..f54f41642 100644 --- a/frontend/app/app.tsx +++ b/frontend/app/app.tsx @@ -159,29 +159,46 @@ function processBackgroundUrls(cssText: string): string { if (cssText.endsWith(";")) { cssText = cssText.slice(0, -1); } - const attrRe = /^background(-image):\s*/; + const attrRe = /^background(-image)?\s*:\s*/i; cssText = cssText.replace(attrRe, ""); const ast = csstree.parse("background: " + cssText, { context: "declaration", }); - let hasJSUrl = false; + let hasUnsafeUrl = false; csstree.walk(ast, { visit: "Url", enter(node) { const originalUrl = node.value.trim(); - if (originalUrl.startsWith("javascript:")) { - hasJSUrl = true; + if ( + originalUrl.startsWith("http:") || + originalUrl.startsWith("https:") || + originalUrl.startsWith("data:") + ) { return; } - if (originalUrl.startsWith("data:")) { + // allow file:/// urls (if they are absolute) + if (originalUrl.startsWith("file://")) { + const path = originalUrl.slice(7); + if (!path.startsWith("/")) { + console.log(`Invalid background, contains a non-absolute file URL: ${originalUrl}`); + hasUnsafeUrl = true; + return; + } + const newUrl = encodeFileURL(path); + node.value = newUrl; return; } - const newUrl = encodeFileURL(originalUrl); - node.value = newUrl; + // allow absolute paths + if (originalUrl.startsWith("/") || originalUrl.startsWith("~/")) { + const newUrl = encodeFileURL(originalUrl); + node.value = newUrl; + return; + } + hasUnsafeUrl = true; + console.log(`Invalid background, contains an unsafe URL scheme: ${originalUrl}`); }, }); - if (hasJSUrl) { - console.log("invalid background, contains a 'javascript' protocol url which is not allowed"); + if (hasUnsafeUrl) { return null; } const rtnStyle = csstree.generate(ast); From 924d1495a38ad5cadc2c5dd1eb8d0f8f84d36209 Mon Sep 17 00:00:00 2001 From: Mike Sawka Date: Wed, 16 Oct 2024 11:04:22 -0700 Subject: [PATCH 04/34] add new generic open clipboard url (#1045) --- frontend/app/app.tsx | 51 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 44 insertions(+), 7 deletions(-) diff --git a/frontend/app/app.tsx b/frontend/app/app.tsx index f54f41642..15e5da4d6 100644 --- a/frontend/app/app.tsx +++ b/frontend/app/app.tsx @@ -4,7 +4,16 @@ import { useWaveObjectValue } from "@/app/store/wos"; import { Workspace } from "@/app/workspace/workspace"; import { ContextMenuModel } from "@/store/contextmenu"; -import { PLATFORM, WOS, atoms, getApi, globalStore, removeFlashError, useSettingsPrefixAtom } from "@/store/global"; +import { + PLATFORM, + WOS, + atoms, + createBlock, + getApi, + globalStore, + removeFlashError, + useSettingsPrefixAtom, +} from "@/store/global"; import { appHandleKeyDown } from "@/store/keymodel"; import { getWebServerEndpoint } from "@/util/endpoints"; import { getElemAsStr } from "@/util/focusutil"; @@ -36,7 +45,7 @@ const App = () => { ); }; -function isContentEditableBeingEdited() { +function isContentEditableBeingEdited(): boolean { const activeElement = document.activeElement; return ( activeElement && @@ -45,17 +54,17 @@ function isContentEditableBeingEdited() { ); } -function canEnablePaste() { +function canEnablePaste(): boolean { const activeElement = document.activeElement; return activeElement.tagName === "INPUT" || activeElement.tagName === "TEXTAREA" || isContentEditableBeingEdited(); } -function canEnableCopy() { +function canEnableCopy(): boolean { const sel = window.getSelection(); return !util.isBlank(sel?.toString()); } -function canEnableCut() { +function canEnableCut(): boolean { const sel = window.getSelection(); if (document.activeElement?.classList.contains("xterm-helper-textarea")) { return false; @@ -63,12 +72,26 @@ function canEnableCut() { return !util.isBlank(sel?.toString()) && canEnablePaste(); } -function handleContextMenu(e: React.MouseEvent) { +async function getClipboardURL(): Promise { + try { + const clipboardText = await navigator.clipboard.readText(); + if (clipboardText == null) { + return null; + } + const url = new URL(clipboardText); + return url; + } catch (e) { + return null; + } +} + +async function handleContextMenu(e: React.MouseEvent) { e.preventDefault(); const canPaste = canEnablePaste(); const canCopy = canEnableCopy(); const canCut = canEnableCut(); - if (!canPaste && !canCopy && !canCut) { + const clipboardURL = await getClipboardURL(); + if (!canPaste && !canCopy && !canCut && !clipboardURL) { return; } let menu: ContextMenuItem[] = []; @@ -81,6 +104,20 @@ function handleContextMenu(e: React.MouseEvent) { if (canPaste) { menu.push({ label: "Paste", role: "paste" }); } + if (clipboardURL) { + menu.push({ type: "separator" }); + menu.push({ + label: "Open Clipboard URL (" + clipboardURL.hostname + ")", + click: () => { + createBlock({ + meta: { + view: "web", + url: clipboardURL.toString(), + }, + }); + }, + }); + } ContextMenuModel.showContextMenu(menu, e); } From a90e747f926f2b18b1e525a34f6b3b74aa2d59b3 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 17 Oct 2024 12:53:49 -0400 Subject: [PATCH 05/34] Fix runaway name appending on the default AI preset (#1051) Shallow copy the presets when updating `display:name` so that the appending of the model name for the default preset doesn't accumulate every time the tab refreshes. closes #1040 --- frontend/app/view/waveai/waveai.tsx | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/frontend/app/view/waveai/waveai.tsx b/frontend/app/view/waveai/waveai.tsx index 0c170d645..db6bb67ef 100644 --- a/frontend/app/view/waveai/waveai.tsx +++ b/frontend/app/view/waveai/waveai.tsx @@ -81,12 +81,12 @@ export class WaveAiModel implements ViewModel { .filter(([k]) => k.startsWith("ai@")) .map(([k, v]) => { const aiPresetKeys = Object.keys(v).filter((k) => k.startsWith("ai:")); - console.log(aiPresetKeys); - v["display:name"] = + const newV = { ...v }; + newV["display:name"] = aiPresetKeys.length == 1 && aiPresetKeys.includes("ai:*") - ? `${v["display:name"] ?? "Default"} (${settings["ai:model"]})` - : v["display:name"]; - return [k, v]; + ? `${newV["display:name"] ?? "Default"} (${settings["ai:model"]})` + : newV["display:name"]; + return [k, newV]; }) ); }); @@ -109,7 +109,7 @@ export class WaveAiModel implements ViewModel { messages.pop(); set(this.messagesAtom, [...messages]); }); - this.simulateAssistantResponseAtom = atom(null, async (get, set, userMessage: ChatMessageType) => { + this.simulateAssistantResponseAtom = atom(null, async (_, set, userMessage: ChatMessageType) => { // unused at the moment. can replace the temp() function in the future const typingMessage: ChatMessageType = { id: crypto.randomUUID(), @@ -213,7 +213,7 @@ export class WaveAiModel implements ViewModel { } async fetchAiData(): Promise> { - const { data, fileInfo } = await fetchWaveFile(this.blockId, "aidata"); + const { data } = await fetchWaveFile(this.blockId, "aidata"); if (!data) { return []; } @@ -318,7 +318,6 @@ export class WaveAiModel implements ViewModel { content: errMsg, }; updatedHist.push(errorPrompt); - console.log(updatedHist); await BlockService.SaveWaveAiData(blockId, updatedHist); } setLocked(false); From 46684a344077b6f84b6679da1b321df49e430999 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 09:55:32 -0700 Subject: [PATCH 06/34] Bump electron from 32.1.2 to 32.2.0 in the electron group (#1018) Bumps the electron group with 1 update: [electron](https://github.com/electron/electron). Updates `electron` from 32.1.2 to 32.2.0
Release notes

Sourced from electron's releases.

electron v32.2.0

Release Notes for v32.2.0

Fixes

  • Fixed a crash when calling focus on a WebView's webContents. #43934 (Also in 31, 33)
  • Fixed a potential issue accessing a child window document when overriding browserWindow creation via setWindowOpenHandler. #43877 (Also in 31, 33)
  • Fixed an issue where an exception could be thrown on BrowserView after its owner BrowserWindow was closed. #44001 (Also in 31, 33)
  • Fixed closing a window with more than one attached sheet on macOS. #43954 (Also in 31, 33)
  • Fixed potential use-after-free during view removal on macOS. #43923 (Also in 31, 33)

Other Changes

  • Ensured that the sender-id hint is set when creating desktop notifications on DBus. #43950 (Also in 31, 33)
  • Updated Chromium to 128.0.6613.178. #44086
  • Updated Node.js to v20.18.0. #44116
Commits
  • da32971 chore: bump node to v20.18.0 (32-x-y) (#44116)
  • 27c38bd build: add import/order eslint rule (#44107)
  • bf8de29 fix: remove use of deprecated API base::Hash() (#44102)
  • 058a616 perf: use ArrayBuffer::Data() instead of GetBackingStore()->Data() (32-x-y) (...
  • bd8b9da fix: -Wunsafe-buffer-usage warnings in WebFrameRenderer::ExecuteJavaScript() ...
  • a635dac chore: bump chromium to 128.0.6613.178 (32-x-y) (#44086)
  • 653b928 build: fix relative file read during npm publish (#44092)
  • 98b1d30 build: cleanup release scripts, separate cli entrypoints from logic (#44081)
  • 2f519a8 build: update some build dependencies (#44070)
  • 2e84985 build: convert all release scripts to typescript (#44060)
  • Additional commits viewable in compare view

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=electron&package-manager=npm_and_yarn&previous-version=32.1.2&new-version=32.2.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/package.json b/package.json index 0d50a9345..1eaded3c8 100644 --- a/package.json +++ b/package.json @@ -55,7 +55,7 @@ "@types/ws": "^8", "@vitejs/plugin-react-swc": "^3.7.1", "@vitest/coverage-istanbul": "^2.1.2", - "electron": "^32.1.2", + "electron": "^32.2.0", "electron-builder": "^25.1.7", "electron-vite": "^2.3.0", "eslint": "^9.12.0", diff --git a/yarn.lock b/yarn.lock index 1eb60f941..c6fda30e3 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5226,16 +5226,16 @@ __metadata: languageName: node linkType: hard -"electron@npm:^32.1.2": - version: 32.1.2 - resolution: "electron@npm:32.1.2" +"electron@npm:^32.2.0": + version: 32.2.0 + resolution: "electron@npm:32.2.0" dependencies: "@electron/get": "npm:^2.0.0" "@types/node": "npm:^20.9.0" extract-zip: "npm:^2.0.1" bin: electron: cli.js - checksum: 10c0/9e453e046e024b1454fb212e977d622feba3b6d24ff922a360c06177ec8bcbe58e729e105260285e79c0a203dfcb42d3d795844030bba8681016ab50b7d4bb87 + checksum: 10c0/28d988a9d05c89e93d70cc790bd53ecc97135cc3fa9efe3617f10b87cdf85ada468d383afd7858bcf8f064aa189ea7f8987e32c7ebaac70bda64e8f9f85621e8 languageName: node linkType: hard @@ -11683,7 +11683,7 @@ __metadata: css-tree: "npm:^3.0.0" dayjs: "npm:^1.11.13" debug: "npm:^4.3.7" - electron: "npm:^32.1.2" + electron: "npm:^32.2.0" electron-builder: "npm:^25.1.7" electron-updater: "npm:6.3.9" electron-vite: "npm:^2.3.0" From 594bc6839a3a10873ae682af55abc10c1cfb5097 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 09:55:52 -0700 Subject: [PATCH 07/34] Bump github.com/sashabaranov/go-openai from 1.31.0 to 1.32.0 (#1019) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/sashabaranov/go-openai](https://github.com/sashabaranov/go-openai) from 1.31.0 to 1.32.0.
Release notes

Sourced from github.com/sashabaranov/go-openai's releases.

v1.32.0

What's Changed

New Contributors

Full Changelog: https://github.com/sashabaranov/go-openai/compare/v1.31.0...v1.32.0

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/sashabaranov/go-openai&package-manager=go_modules&previous-version=1.31.0&new-version=1.32.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 9f4774c85..d1e5b4466 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/kevinburke/ssh_config v1.2.0 github.com/mattn/go-sqlite3 v1.14.24 github.com/mitchellh/mapstructure v1.5.0 - github.com/sashabaranov/go-openai v1.31.0 + github.com/sashabaranov/go-openai v1.32.0 github.com/sawka/txwrap v0.2.0 github.com/shirou/gopsutil/v4 v4.24.9 github.com/skeema/knownhosts v1.3.0 diff --git a/go.sum b/go.sum index 732c02c94..ae94a83f4 100644 --- a/go.sum +++ b/go.sum @@ -56,8 +56,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sashabaranov/go-openai v1.31.0 h1:rGe77x7zUeCjtS2IS7NCY6Tp4bQviXNMhkQM6hz/UC4= -github.com/sashabaranov/go-openai v1.31.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= +github.com/sashabaranov/go-openai v1.32.0 h1:Yk3iE9moX3RBXxrof3OBtUBrE7qZR0zF9ebsoO4zVzI= +github.com/sashabaranov/go-openai v1.32.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/sawka/txwrap v0.2.0 h1:V3LfvKVLULxcYSxdMguLwFyQFMEU9nFDJopg0ZkL+94= github.com/sawka/txwrap v0.2.0/go.mod h1:wwQ2SQiN4U+6DU/iVPhbvr7OzXAtgZlQCIGuvOswEfA= github.com/shirou/gopsutil/v4 v4.24.9 h1:KIV+/HaHD5ka5f570RZq+2SaeFsb/pq+fp2DGNWYoOI= From 88445b2f1ddc9393a495a2535e94314d483001eb Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 17 Oct 2024 13:17:47 -0400 Subject: [PATCH 08/34] Add expect-error to two emain event handlers (#1052) There were two type errors after the most recent electron upgrade, but they're both benign (event handler parameter mismatch) so I am adding ts-expect-error to both instances. --- emain/emain.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/emain/emain.ts b/emain/emain.ts index e23c7f05c..de447b415 100644 --- a/emain/emain.ts +++ b/emain/emain.ts @@ -471,10 +471,12 @@ function createBrowserWindow(clientId: string, waveWindow: WaveWindow, fullConfi } }); win.on( + // @ts-expect-error "resize", debounce(400, (e) => mainResizeHandler(e, waveWindow.oid, win)) ); win.on( + // @ts-expect-error "move", debounce(400, (e) => mainResizeHandler(e, waveWindow.oid, win)) ); From 7628e667ca2cc4879e60e08b05e462ef04876bb6 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 17 Oct 2024 14:14:59 -0400 Subject: [PATCH 09/34] Separate AppBackground into its own file (#1053) Setup for command palette. I'm moving AppBackground to its own file and simplifying the imports --- frontend/app/app-bg.tsx | 123 ++++++++++++++++++++++++++++++ frontend/app/app.tsx | 164 +++++----------------------------------- 2 files changed, 141 insertions(+), 146 deletions(-) create mode 100644 frontend/app/app-bg.tsx diff --git a/frontend/app/app-bg.tsx b/frontend/app/app-bg.tsx new file mode 100644 index 000000000..5cc4a929f --- /dev/null +++ b/frontend/app/app-bg.tsx @@ -0,0 +1,123 @@ +import { getWebServerEndpoint } from "@/util/endpoints"; +import * as util from "@/util/util"; +import useResizeObserver from "@react-hook/resize-observer"; +import { generate as generateCSS, parse as parseCSS, walk as walkCSS } from "css-tree"; +import { useAtomValue } from "jotai"; +import { CSSProperties, useCallback, useLayoutEffect, useRef } from "react"; +import { debounce } from "throttle-debounce"; +import { atoms, getApi, PLATFORM, WOS } from "./store/global"; +import { useWaveObjectValue } from "./store/wos"; + +function encodeFileURL(file: string) { + const webEndpoint = getWebServerEndpoint(); + return webEndpoint + `/wave/stream-file?path=${encodeURIComponent(file)}&no404=1`; +} + +function processBackgroundUrls(cssText: string): string { + if (util.isBlank(cssText)) { + return null; + } + cssText = cssText.trim(); + if (cssText.endsWith(";")) { + cssText = cssText.slice(0, -1); + } + const attrRe = /^background(-image)?\s*:\s*/i; + cssText = cssText.replace(attrRe, ""); + const ast = parseCSS("background: " + cssText, { + context: "declaration", + }); + let hasUnsafeUrl = false; + walkCSS(ast, { + visit: "Url", + enter(node) { + const originalUrl = node.value.trim(); + if ( + originalUrl.startsWith("http:") || + originalUrl.startsWith("https:") || + originalUrl.startsWith("data:") + ) { + return; + } + // allow file:/// urls (if they are absolute) + if (originalUrl.startsWith("file://")) { + const path = originalUrl.slice(7); + if (!path.startsWith("/")) { + console.log(`Invalid background, contains a non-absolute file URL: ${originalUrl}`); + hasUnsafeUrl = true; + return; + } + const newUrl = encodeFileURL(path); + node.value = newUrl; + return; + } + // allow absolute paths + if (originalUrl.startsWith("/") || originalUrl.startsWith("~/")) { + const newUrl = encodeFileURL(originalUrl); + node.value = newUrl; + return; + } + hasUnsafeUrl = true; + console.log(`Invalid background, contains an unsafe URL scheme: ${originalUrl}`); + }, + }); + if (hasUnsafeUrl) { + return null; + } + const rtnStyle = generateCSS(ast); + if (rtnStyle == null) { + return null; + } + return rtnStyle.replace(/^background:\s*/, ""); +} + +export function AppBackground() { + const bgRef = useRef(null); + const tabId = useAtomValue(atoms.activeTabId); + const [tabData] = useWaveObjectValue(WOS.makeORef("tab", tabId)); + const bgAttr = tabData?.meta?.bg; + const style: CSSProperties = {}; + if (!util.isBlank(bgAttr)) { + try { + const processedBg = processBackgroundUrls(bgAttr); + if (!util.isBlank(processedBg)) { + const opacity = util.boundNumber(tabData?.meta?.["bg:opacity"], 0, 1) ?? 0.5; + style.opacity = opacity; + style.background = processedBg; + const blendMode = tabData?.meta?.["bg:blendmode"]; + if (!util.isBlank(blendMode)) { + style.backgroundBlendMode = blendMode; + } + } + } catch (e) { + console.error("error processing background", e); + } + } + const getAvgColor = useCallback( + debounce(30, () => { + if ( + bgRef.current && + PLATFORM !== "darwin" && + bgRef.current && + "windowControlsOverlay" in window.navigator + ) { + const titlebarRect: Dimensions = (window.navigator.windowControlsOverlay as any).getTitlebarAreaRect(); + const bgRect = bgRef.current.getBoundingClientRect(); + if (titlebarRect && bgRect) { + const windowControlsLeft = titlebarRect.width - titlebarRect.height; + const windowControlsRect: Dimensions = { + top: titlebarRect.top, + left: windowControlsLeft, + height: titlebarRect.height, + width: bgRect.width - bgRect.left - windowControlsLeft, + }; + getApi().updateWindowControlsOverlay(windowControlsRect); + } + } + }), + [bgRef, style] + ); + useLayoutEffect(getAvgColor, [getAvgColor]); + useResizeObserver(bgRef, getAvgColor); + + return
; +} diff --git a/frontend/app/app.tsx b/frontend/app/app.tsx index 15e5da4d6..02ce0da0d 100644 --- a/frontend/app/app.tsx +++ b/frontend/app/app.tsx @@ -1,35 +1,22 @@ // Copyright 2024, Command Line Inc. // SPDX-License-Identifier: Apache-2.0 -import { useWaveObjectValue } from "@/app/store/wos"; import { Workspace } from "@/app/workspace/workspace"; import { ContextMenuModel } from "@/store/contextmenu"; -import { - PLATFORM, - WOS, - atoms, - createBlock, - getApi, - globalStore, - removeFlashError, - useSettingsPrefixAtom, -} from "@/store/global"; +import { PLATFORM, atoms, createBlock, globalStore, removeFlashError, useSettingsPrefixAtom } from "@/store/global"; import { appHandleKeyDown } from "@/store/keymodel"; -import { getWebServerEndpoint } from "@/util/endpoints"; import { getElemAsStr } from "@/util/focusutil"; import * as keyutil from "@/util/keyutil"; import * as util from "@/util/util"; -import useResizeObserver from "@react-hook/resize-observer"; import clsx from "clsx"; import Color from "color"; -import * as csstree from "css-tree"; import debug from "debug"; -import * as jotai from "jotai"; +import { Provider, useAtomValue } from "jotai"; import "overlayscrollbars/overlayscrollbars.css"; -import * as React from "react"; +import { Fragment, useEffect, useState } from "react"; import { DndProvider } from "react-dnd"; import { HTML5Backend } from "react-dnd-html5-backend"; -import { debounce } from "throttle-debounce"; +import { AppBackground } from "./app-bg"; import "./app.less"; import { CenteredDiv } from "./element/quickelems"; @@ -37,7 +24,6 @@ const dlog = debug("wave:app"); const focusLog = debug("wave:focus"); const App = () => { - let Provider = jotai.Provider; return ( @@ -123,8 +109,8 @@ async function handleContextMenu(e: React.MouseEvent) { function AppSettingsUpdater() { const windowSettingsAtom = useSettingsPrefixAtom("window"); - const windowSettings = jotai.useAtomValue(windowSettingsAtom); - React.useEffect(() => { + const windowSettings = useAtomValue(windowSettingsAtom); + useEffect(() => { const isTransparentOrBlur = (windowSettings?.["window:transparent"] || windowSettings?.["window:blur"]) ?? false; const opacity = util.boundNumber(windowSettings?.["window:opacity"] ?? 0.8, 0, 1); @@ -163,7 +149,7 @@ function AppFocusHandler() { return null; // for debugging - React.useEffect(() => { + useEffect(() => { document.addEventListener("focusin", appFocusIn); document.addEventListener("focusout", appFocusOut); document.addEventListener("selectionchange", appSelectionChange); @@ -183,122 +169,8 @@ function AppFocusHandler() { return null; } -function encodeFileURL(file: string) { - const webEndpoint = getWebServerEndpoint(); - return webEndpoint + `/wave/stream-file?path=${encodeURIComponent(file)}&no404=1`; -} - -function processBackgroundUrls(cssText: string): string { - if (util.isBlank(cssText)) { - return null; - } - cssText = cssText.trim(); - if (cssText.endsWith(";")) { - cssText = cssText.slice(0, -1); - } - const attrRe = /^background(-image)?\s*:\s*/i; - cssText = cssText.replace(attrRe, ""); - const ast = csstree.parse("background: " + cssText, { - context: "declaration", - }); - let hasUnsafeUrl = false; - csstree.walk(ast, { - visit: "Url", - enter(node) { - const originalUrl = node.value.trim(); - if ( - originalUrl.startsWith("http:") || - originalUrl.startsWith("https:") || - originalUrl.startsWith("data:") - ) { - return; - } - // allow file:/// urls (if they are absolute) - if (originalUrl.startsWith("file://")) { - const path = originalUrl.slice(7); - if (!path.startsWith("/")) { - console.log(`Invalid background, contains a non-absolute file URL: ${originalUrl}`); - hasUnsafeUrl = true; - return; - } - const newUrl = encodeFileURL(path); - node.value = newUrl; - return; - } - // allow absolute paths - if (originalUrl.startsWith("/") || originalUrl.startsWith("~/")) { - const newUrl = encodeFileURL(originalUrl); - node.value = newUrl; - return; - } - hasUnsafeUrl = true; - console.log(`Invalid background, contains an unsafe URL scheme: ${originalUrl}`); - }, - }); - if (hasUnsafeUrl) { - return null; - } - const rtnStyle = csstree.generate(ast); - if (rtnStyle == null) { - return null; - } - return rtnStyle.replace(/^background:\s*/, ""); -} - -function AppBackground() { - const bgRef = React.useRef(null); - const tabId = jotai.useAtomValue(atoms.activeTabId); - const [tabData] = useWaveObjectValue(WOS.makeORef("tab", tabId)); - const bgAttr = tabData?.meta?.bg; - const style: React.CSSProperties = {}; - if (!util.isBlank(bgAttr)) { - try { - const processedBg = processBackgroundUrls(bgAttr); - if (!util.isBlank(processedBg)) { - const opacity = util.boundNumber(tabData?.meta?.["bg:opacity"], 0, 1) ?? 0.5; - style.opacity = opacity; - style.background = processedBg; - const blendMode = tabData?.meta?.["bg:blendmode"]; - if (!util.isBlank(blendMode)) { - style.backgroundBlendMode = blendMode; - } - } - } catch (e) { - console.error("error processing background", e); - } - } - const getAvgColor = React.useCallback( - debounce(30, () => { - if ( - bgRef.current && - PLATFORM !== "darwin" && - bgRef.current && - "windowControlsOverlay" in window.navigator - ) { - const titlebarRect: Dimensions = (window.navigator.windowControlsOverlay as any).getTitlebarAreaRect(); - const bgRect = bgRef.current.getBoundingClientRect(); - if (titlebarRect && bgRect) { - const windowControlsLeft = titlebarRect.width - titlebarRect.height; - const windowControlsRect: Dimensions = { - top: titlebarRect.top, - left: windowControlsLeft, - height: titlebarRect.height, - width: bgRect.width - bgRect.left - windowControlsLeft, - }; - getApi().updateWindowControlsOverlay(windowControlsRect); - } - } - }), - [bgRef, style] - ); - React.useLayoutEffect(getAvgColor, [getAvgColor]); - useResizeObserver(bgRef, getAvgColor); - - return
; -} - const AppKeyHandlers = () => { - React.useEffect(() => { + useEffect(() => { const staticKeyDownHandler = keyutil.keydownWrapper(appHandleKeyDown); document.addEventListener("keydown", staticKeyDownHandler); @@ -310,11 +182,11 @@ const AppKeyHandlers = () => { }; const FlashError = () => { - const flashErrors = jotai.useAtomValue(atoms.flashErrors); - const [hoveredId, setHoveredId] = React.useState(null); - const [ticker, setTicker] = React.useState(0); + const flashErrors = useAtomValue(atoms.flashErrors); + const [hoveredId, setHoveredId] = useState(null); + const [ticker, setTicker] = useState(0); - React.useEffect(() => { + useEffect(() => { if (flashErrors.length == 0 || hoveredId != null) { return; } @@ -351,10 +223,10 @@ const FlashError = () => { function convertNewlinesToBreaks(text) { return text.split("\n").map((part, index) => ( - + {part}
-
+ )); } @@ -382,10 +254,10 @@ const FlashError = () => { }; const AppInner = () => { - const prefersReducedMotion = jotai.useAtomValue(atoms.prefersReducedMotionAtom); - const client = jotai.useAtomValue(atoms.client); - const windowData = jotai.useAtomValue(atoms.waveWindow); - const isFullScreen = jotai.useAtomValue(atoms.isFullScreen); + const prefersReducedMotion = useAtomValue(atoms.prefersReducedMotionAtom); + const client = useAtomValue(atoms.client); + const windowData = useAtomValue(atoms.waveWindow); + const isFullScreen = useAtomValue(atoms.isFullScreen); if (client == null || windowData == null) { return ( From fae06600cc572761df6d6b0e607461ecc2ad7311 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 17 Oct 2024 14:27:15 -0700 Subject: [PATCH 10/34] Fix Windows packaging when signing isn't provided, update app icon on Windows (#1055) This adds a new app icon for windows that is less Mac-like and it also fixes a bug in the electron-builder.config.cjs file which would cause the packaging step to crash if it was missing the signing env vars, rather than just not signing the package. ![image](https://github.com/user-attachments/assets/fe433ae5-0b88-49a9-91b6-d1083460b7b2) --- assets/appicon-windows.png | Bin 0 -> 35274 bytes assets/appicon-windows.svg | 20 ++++++++++++++++++++ build/appicon.png | Bin 85828 -> 0 bytes build/{icons.icns => icon.icns} | Bin build/icon.ico | Bin 18212 -> 301768 bytes electron-builder.config.cjs | 15 ++++++++------- 6 files changed, 28 insertions(+), 7 deletions(-) create mode 100644 assets/appicon-windows.png create mode 100644 assets/appicon-windows.svg delete mode 100644 build/appicon.png rename build/{icons.icns => icon.icns} (100%) diff --git a/assets/appicon-windows.png b/assets/appicon-windows.png new file mode 100644 index 0000000000000000000000000000000000000000..e2a8ed41240419bfd247fbba8eac7240bd5d395c GIT binary patch literal 35274 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 literal 0 HcmV?d00001 diff --git a/assets/appicon-windows.svg b/assets/appicon-windows.svg new file mode 100644 index 000000000..6fbf2443c --- /dev/null +++ b/assets/appicon-windows.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/build/appicon.png b/build/appicon.png deleted file mode 100644 index a10809fb055de22040dc22929e2492dcfc18782d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 85828 zcmeFYbyOV9x;KhD1a}=Y1a~JSg9mpA?g0jO_rX25yF+k?gy2qa_XKyBJIUT>+qvIe z-@5k4S#Ph^tGlbK>ZwQS_sH~wDauQtqY$G&K|!HQO97Rkpb$uYpGXLh7KB<SRdiW@8O<6mS!!|Iqphlq(WtEsi=Z@D#FDbE0Bu{~s+73H*LxXXxN)s_JfMDon3z>S*iiU~KxYYXAF$?;T7H zolH$cIM_Hinc3Ny+4zN6|Krs^G$-`;7vgSC(k3GOhCG~xyvDrDrbc``%v{Etyv+PO z-0aM}CLDYmMr>w$9EQgKnCovt{@Y9vMv#fPIk-7^xcS++*m?Q6`Plw3=FiLjHbm9d z+1TPYTOtru{(V9JZ2M>T|Am_WU0nY)!M}_3|0PA+{mWMRt>r&^^tXN?FChBm{5SnV z+62U$oh)n}L~JaLEljPgO(~rWK|;Sf|JRHEVDA69DMC=<-|X-oD|9oo`)?Kq=`8Ta zT5KIuZEdYZ-W!5k424+#v-$sOk^jJ)KN5z3&c9eL>pwtCWMFR!1`1kwR2nFz>Xvc1 zz>W^ZhSpt^B>KyLKuPTj*7ms2ADr_uXoUUS&CEGB94^%U?%z%6dmwhm9A)x1IoAyQP0R*y=znJG2K-&z;yizzp(6e+ zcKn6EJu`jzoA@>VngHs*$pHB;LI1Xr|L<+(FG2s=jeiOHj~Mf>%YJn3hIAir1=+E|FP`<-vYiB_r#BTT6iv+N@!pN`EN^WsY}}TrZFm&fD`{&5&2-qRHQaaJc(3lclUYN`cmH+N zMQj=brvCHL#YH3;`R8$%$2V_a_RoXhdk?~Y4TW6W7%+HJ{yBI-+`gvgpMytO!UNI& zIo8ZYiS*w|$G6X*|9vfWO;RM<)Ae-jm%c*UDGQ?0IM|~jBZqCf(LsNkf1!cK;Gn+| zS4s;G2uIyrBJ)dgWi$9YJSzUr)co<@v*#^4*dEC*=EB!=F_z7)DJ#E@`L1RASErJH zuRl3Et*I3na^r&MA-MTKls${tZD{bbZF!9`hpJ0=)g0$cw`m+gkht+`p)&mPGU}Z# z^asiM_fE?BvvJ1>He@UGZF3f9gAEN4ty9MZ^dfqs${ajjH<5Ah^B=DeMQ;L$NyxV@ zzK?&4!O5DnfDp2A_#=z5s8_GJ??EDx zl$-AB!%5ksC2X8^R@qC`|JB5Kp9S8NcM z{PN!z_0;ZAq3p*292G<2jEGWtr8I} zrqZeul7xh0yyaD4Na}RJ@nmbgVFAbxsI6Z{yAOjm4HO&E$ZO@jkB_G*NMxT%OE7LQ zwzLVCp)KSt6IKdWz8pWH$eiKLPhqf9LrUCbRmX(0WJD^lVZbh~!wnNozxf$`E%-?$ zROW0yO+y7=W$ZKIE8wG`W^&aQ@C5n3>Lf6xV{$e$dAu6bv$S=F!fh#I}&0Cwyl1b zO;-DZVU#fbwwa) zf#%QV8yp?^Zae)_kcHjB`e!lkiur7xJihbg)Q%l*b#1q`u?N2MbFAnrk+c;@#2#us zBtwWKQ!h#vAzRDgn$3u+^=07c@MAOQx!+g*Ky;EKn-Zco(WCKPI=KsQj{bMukCeM8 zqc}`ZX75KN(!|&@t#fjrQ^*zRjfhL|OR7opGkz$NeVw=s2~#0A{F2;vr>-0JXE!r7)*8gGAotVCFi!Q09>i5yE)Dc!*~JelUw8(i|}?iXAZsS51`GF8*X$ z7Ty~vFn|?$$8@)gZL?4-{t)kNf4W8J^S(X2LF?zduFvU29%0YUF%hEBr1 zpoOs;ps}ZU&uKEYqEctf^Lgvi_vT)*A!3)(g7O=h`HxmaTYc@?nbkyOzLNJk!@Wq^ zO~6u{nO)DO&T%T(Ot!q8LNN_SL?x(g8>~ahTTUKupk_>fD%!yz`Mm8)XHpvpU;_|R z$w|NrlBwRJJVat#>>kB8BQ%pOH}A zW9m9p^(%-4U8|q|nuA!-Xbt*tMN2|*Q)dQq`=bij6il_wR$By;%ZvX6$deG$eal=h zttO?O@Ch%R8>=F|9!(R!H-7*10}lNaV!TWuYi}J>AX6S@oPt4tfb9C?lmDEw4BuYS zzTldL*|!3?V3SQP(FcZ5ScIDJbY0 z7Aa8RZH*u@MqEL0m8ki8*iBFC*m0>M1%e9pALs9q+e=M&RVnS<}dgaGl$ z*V@Am%~!S{PcT>^&QwS}nav|V6Rk8%I`< z?_KK=H-sSXK zd<~&Jb&s+%FXqU*A8)1~W-vShFJ|gm%zMY34w^$kK)fAbUX=3+CskI^{G^@4yuwM(mqZ)*f{kuFUD%} z9_xZ7m_{(=7rj|chI@FMx9MPv037%qE^{x-6ZR7Qp5!Twg(N?t*9uvQ%86EUHNw@Z zxesLFPr02Al5I_|%4WQ(o*YjpGKqfM(~8}1-+Z_kMwf%f9!duwqj<%1~g!wT#;VO!by_gsoaO+ z6&E;!#d{q@?IwF2t6vH-mE(_xRZ4W3Ke|rdtQEIpXO+{ZWrJ&-&_D>}#h(NMAi-1S z@Xn9Y-w5Nd4E}7Zl~qCdG4*)9mipWPb|g@(U!9pb5rrh6nN!Upc|!Qz1(q|Mbk+q_ zY&2{2$Jbm1?O=PJxK571XQ2d)a$bFlq&!}Zf#R{ z1K;}rbcE~LZ79J{@5Vzn4`hsarH?v=sXfPPu+I$wk6*4HPz5Dji@d&k5rvrNgbXSaitph3 z^m_CHR^oa=Q}g+G#hhz$?LDc@ZgA4OE$-Mi@X=Bimq9_& z-=hW)Bg+HO`R47^;7E!*hRc=`cNL`0wThG)LJijmdpZ@{(Y)S>^}pL!2ij7-zVdw- zzey%0nVi5BT6q81jpF7&)YGs3Qu#Zw8!lQ&hwBX(pIOE3y~rWTIJoqnMIfQG8FJ;% zVlEp9yh!3mMBcJeGvUY4QVIGA-3p@(ABuEM9Ub%|wP2Dcoa){CFhXT-`=6!RFJpu` zeMeDgB2MvR;`&jnoiP^6t0fD?G4?74s94Zl3#wNFkVw2rnI+%E%uKx!8T8V3G?+2% zI7Qa)s>-4=*JbOyqWLf%)vEUR#h+ugT=ns#}O>$)MK)YJv;qUTf(DEMDbIYb}!>pupU>8&gfk+wLjF>|e2rK7TkP7wDt zKDyJ2UsB6M7sIVUXR>QsEL{&WALTU4UsJHsWPE4?9d+!zo%&`Za|eC?NlmNEPG`EY zAOyh6;>+{APv5}O#YAdVd!Y)Xj{wyM~LATitAMXGN*<*q3ja} z@R^htbPDPS0yAPfC5ShIF8zlspewdB?%P^L3TMT2E?IlcLN`#~#jL>HS7Q zS2h!p*vwr^De_|SYU<^P&S2~3qsOu8t@95MoD^@}^~8r>zcQc1m|mwLvP0! z7Se0tlK>^CrD9Y2NaO*{`gRI%sEo9sl$0`9G6m;q7J7hRS7W8NHSK=G3{j%njLi8? zF6m=?hh%+jN0n0ks>(+}=0H-^vv&aDH@BZqDzPGQd*?$sI|_9plrGk=oxM-}UtxM) zcOS11OyEPXci2rJxI@d5t|4d&KUh0ebo@(G!%NzBCf-s(w1@h5@Fa>Xh zrIo&}CBpLP>dnv7<7a33M^`1$5cR763C%US^nvYYLg~6#7;~?zX1X+Ia)h;s!_;9& zC_y;O^28(sDW7!-P{g$HK46x7L@D*?Ol7?|992m=fbvUZNVnG-92z|7LT+ZyVFw_@ zUPHGj8{Jqr&K@zMO?wPK%m@hZ%#Wwe9=6E!mZ?|_4xc_=WGPvixin~we)20&WmrW{ zla0+AN`rUV7&2dfv?6yI2;hLHJdX#ni`?XJP#I$N8L-c|y?11Fm8M5xn ze`)~9c-q3!e`+n@kZv8HdkkpYIH22dsI3i|S7b0JR%7+t1`>mt$t_F4ZGd;!ui4Ph zLh^V6^rXF|*`s6F4hG`C)uWeIZXGzkStNgiUCg%x?L`-n6%HcmI2px}yWK-G^FK49 z${$4(#hBTg_JhpK)?|NI4;E$$*n{5tz;bd2f^Aj(Pcc-~=tMLkQS}rX~`z`wA z+w->@zlw@w*SjIRG|3E6Fy584&08XNHObX+OapF;r6bIHL`D<93L+Y!Lk7}N6`>X( z>n4jfEi1_RCn_Q{#7$MFdS||RUOgHWoGiDuURzDDByBm9b*;bl`Kd|2$7jyVom+fm zV0ib1%ckr3*X_9{sUJjFvi-%lzkTf!CL3%mnHv%_D^szeP73niJKBnUAg5!E|>g2yvCF9Y`pLm_YaH-%zA z+(c#xY%DY>E}TQO@A3uS;e1*uiYMi=X%VlQa(the?B`;>)`cRueC)P@ETc&tXRsq! zXAUMi-U(IfuEX&>4PE8rp@L5Jn6E$V{v&$Zgj}4h41lqm%aj7BeRWu{KOJ^H9VFoo z%0cCWIh34ySAr+55hVYb?>)9TQf8`%)#_;ig*zj;C(P*niwHXJ$VO{Ic9_Po-wYzT zq4)3}?0WVp{5VMX=D`@^aCS!^bs`8#02*WTvn$=4zK_r_S44mX-?vI)HNjONj+Uqn zN3~~pt8?Z!_%o|wu-#4#R>99~QSUf~?q87)^?*~mGpUYo@3jJ`b2`2!+JZn!rpleI!8r+gdnXZPYFR#@^(uGpk$j@Hi z80LSXlf3hEhmq3-GT||awZgxP!y9G9-dCRp-lWN8$uYLbDL(31YkLAxWblm+jwM#9 ztOPTAM`SZ%)MQ{Md_|4Q21Pz!KNlE+U`dv;!7)#1oYW&D))~Kp3K!FqP&dI%*@eg| zQ_<#%A_?vT!YOL7O}9rczyLwZ!~NaWN7m{NgKG~u8l!Eh=JQPS?nOUm6mq(}WMDCP zs%mvHN|3jDC)>l>gH=rnCq^_{UpL%o61|5f3Cd0SgjBm|18&>m#x3Xj1zTyBrIW zIgpV2gj#BrguVJ^v)>=l&(i(;-Rl@e8aQB{3|`&^-CmdfrLP@PA?o5bhfJ~+QDNyT zEHOO^%QBusbCx1MfYf;?zCVG#Z|r3OHbz0=)KBMp;a_2?y6x9QMoZ(?5j{A8?U%)@ znbi#t+F`=asr{(^>90m`&x*Sd2W6$@uiTQA(md8|wTTMru6@O-Hv?2##gbmb;Lsr! zU?~MMzQ&tTAVa`_MWnq(g z=&py8I%95-ZNZHq>-!swv*nI)cax!!L&i_sVDq6MDE(yhf(nd&5FnnkNFq0C%P@q+g9w>SXp&Vw6%kdj%ZC;6o zxnkLe_A(ln@syCv%yqEDm|X7;Z`v$CNvVDhF@rgwaYO92?44AW86IqmHuop6z59h; zeO%-Yx4scNIS2C3Qc%sZ`khuvVs%NENRWUv(VP9^GZjSi&4+#wDnLFTEl)$q_)l`^j|k9Ni81e6>Rk+gKQrd*A7MJdWc0=N@&QY`*!I! zQ!7u$Px6)@ASgDR*hU0N*FI}^`FMYE`lak*y%bmFVXBr#Y=d@&(~XFXA3qbpszCn+ z5ns<&KAn@KXnO>q%vUaBLD3t``+0$FCL*#-C+Etv{j_;%ozxx$y;#Y5;oo((|Lu;Nk4Tpm#9Y zFWV=Auh2*kcKVa-hd3bqyx(CR1clAhvwu=i`bOMRDSrQm=3b-QySw6Wkw<2s$qQf4 zWme#YwgO@o4mJM!`Z$OrWv}cl1JKQFqAGT^i2bqSwqJxpVf5lQPn0j~1FjVpmmW0` z`&Ms`dz-s;tE#09yKmzb=^;jQy1{Q`5KKvsy35B76_dP z%jj<;HCS@!TBrkTklWt`Fk?4Fjz^Mr0o&J6B@ju*=ExCAN}jpxYjW=~lX>Rt#>`FR z!eR@`pet~IUL)w&g{KDBA8|3&$9L>5=sRr_4{I^c&nMDr;n(S@x^Zy+JB+F%nN9=6y? zv9{`XzeuCpeNOF0n>ZITQ>0{|l8`oL>-AFlO%YEahhQfOeq+~uzpzK z(<5fSY!X@&7`lZkX7GJF)z9f6iYZkj&Q-lN^4foI4iAJBKZG95ry(}q(a??6>p6Lp z?^@6?eUIY*IqdQq*!R618M2rnN*v90p<0muD}UX_*Q}o-As3Ej-+qMNlAH56z$Eo>IKJOAnT>t|t{ex#L_ATg^3SC>2W!1f)vuahfHWdsXju4L_MT0SZpr z1Fo&Eeyza9ygMwGQkfUHwGr<39z4ejPYUfK_PtZ-oiv?j?qK(Lb;IF$_YvO}v=`%x z;VWTg#{a_41&PRtk)h6f4L16MgSCSBBf#^xn}OYke!*{f%2G|N*n_|qdS(Lic7_U0 zH5-ql)+zUxwsJKa%W{J(*M?q+21su3n-p=K_&uwenu{$oHqx#Y1Bm!=TrFq;sYKoH zeXlUza(G<+Aj4Du;6n|j}f4#WE{< z-?U4pyoAG($q71P zI&2wrx4p~&XZxiI=765O1_2=duXw^ zaYZ(AxQP3+^Tp$!f@?&U#_eJQde^y|&Azf^AuFq|eFqv4@q+(f9jE z74ZwjpHH4vJe^3*-TTi@INuCw3`R4r8R;}KCCocy+`hw>B35Jx`Y7|BEdtp_g;;(% zBmNo=2~kFeiLdYylR>zU*=7(qIE1GmCsy&D6pFnpYANjN!dt)+jl6Zntxp{DQtQaH zsF|57ZKZl$_)b#c8a;hu`^DIZ;NpVos%!R5p5$jRIFS|Ax=#}WRgi=pp^udJm}{@e zf5H9@N043w=597W3QyvPGK2RbVFBn*3Q32YMFHqY*AyiVT#uqq!Nx30nT_y(@Eo8N&P0<^9;SG97!pc1C48~SR-a6 zJ&=3D5LEIt@rM}9&o+#3&&Lolm}_WH(ls-X4X81p`zHN?%2g27iFj7ardY7+;+a{P zZ~6IZDG<51jcD#l?&Unwt&w{;Xj;-jag7UI(9yazF$1Q(tX01&UoGq;V5@5+*j zyJ>|6a@?{(xOzKl(@ff%9z}RtM2gA| zcb?*<>(zYVgDhb+p9|(;th-z9NOY+AVed#^Uly`?^wjO6iXNu*>F#GUSnHi1QO|of zxt6IwlirCmbja#MzWayRoeh3hi`qPUe~eEleCjjW5RgC(2n%03$Gxw&qUeXcYk5Q>p#}e4_1(F@WCJvID~txm=pPfh*0P-7aIpBzajh}2;-hsnScswr5DPA@#hV+J@}Z)=}z7pXfSmcy$o2hPm)bHc_fW_YykAdYa;)x%lA^nWN zIlQh1`=QSo;~3g3mG8q(kY7uitICW`TPc4lS-_Ee^AY{Ve&fM2(=z_E+MXVU^)D)7 z;kfDLDbgQf)eUNG6c?~{>(#!YiiQ4QGBV^dhwSMSJafBG7bWnIxaO`;lfuO>2VpMN<=^(k`?Gwsdl0esUn*{Yp}=}A=J%*!ydZo4 zO9~YDsDC0Z^p9C#MQtJAii*!rBY&abO?JSOlNCw08!u`zE=I$EWrb=Zb@4yJI2DdQ zLKL*TMRv71`ISq}$KBv*Jluz(n+A?_@h}MkOX;E3kZmzAm4VOrsIq}QAuhUyJUn*_7DE)wwE7vMaP9| z-CrK>6jfkjge5k7003$|m-n+!YfFt!jtD34q%m_=iZ!`TeYn=K7w=gxC!5sqqBw81 zcR;5JeEsZ#XryqWeoJ#gm;GsiK2y_Ec>>Yk4DU1vX&?}A;5bUCues9vHS-nGvLAb9 z$z9S9lbL0#xCP+>fX&h;{t8{z{b{9yJB7lA4bh6T&X+a~B<)Os z#eblBg^5Kp{H0rgjkrd9CIV*MWOuV2am#fyB^t+w(B6uh7hRev%6eiT#3-HXix@RY zI8F8GK**+fn2+djbGjCt&r`}b6*D35L!H<_n2qzeYgb_<4yCnKVD>ZDcWy8^4RNK#jF^|AWHKjei%{MY-SE zZp&VP1Uq;@Q%&)iC}Jcr z%5GOf;0=JofiKIcoDXmFs3emf@J))E1PGL9`+R#c3WwT;k1$Kb<-fAy|57A|PIGa$ zOE<2zqXG=lqi!3?LE&_z?oKtlZDZGQUGO(mXnPPnNjo0@*f@SY>(zXG>G(>7K+nz` zQRApjN9Tf3;hc^LvC}u~B%wICLHIui@vx-dgbQgd%S}LY8k5eWMDBEx=?ZV4InPd8b6r>b?^!0}ZzkO8-?hd~1fZ=0JcD~T#5PocQ9)qp5`&39)|g3mKdWBrVo zR9Hln97$t-5IZ;3TK5Qm_ry0Tnj2|m3-l&_R2Z=)*EEnQvilUP=Zn`UjjH!$^Ywi( z8Jk#`w{@&BL6L&<;dXqUEllM&UXg%L_=Toer^-%w8Kv--65+{ilXlc>v^&vW>`bQ~W!xJcPY z`}E5@CKTVg;dKOG_>#~Z$fiR>-vSN%iEMeAw=NI0>h@StYCW$@Q|XHiQ>GkkrY8;d zz_Op9a98T_0O9j>+Uz zYVTt9ZbrD-dwhfC;v*;f`}2;JG-d$6JWxx7(ZaxATsZuFWDCfr%lHLdh|7JoSKr&` zc9opC)-a@U)smPN zVhsi&eHYzE?Hf*8&bfDpY;7nh$`h+hAJfHvz>v_Zr_e2KzLV}l_5MZ|^_Yj4KsmXX zD($hl_AiB;>E9bidU?hHk%4^xKq=E=!vM5iyMvlA79fveN96Uq{}6 zByKWaf(-yTbPi)f>G>A;^nImZ^`WGBBya@575O20n>k@&#W_;XwapKVDsU5NM%ia? z#I!wVEbVfwoJSQx1=+5B==PWy7pKWQ3}JeEI@Fk14Gjv`t2+z>(~wdkxw#+B%_3NJ zH8xJ&VZ|wZz=KS8p~Q2Oz`U=`#qOkI3G)49=UjiS(GKO5fk2PKN}$VV=NF~q`f>Su zEd{;Vljx%CM%Z-fscM@sq?Fz#97n*dCk;KYDpu3&5qJ1?tIBE`x+$sXO}RZ=ghHZA zf1)GNUVKses?S`knaZS<{F%h{;ItxWB_1VOpM$sbxaDi4cJ-R?P!qK&%)Neo(%E%k zXLUzAH_1@zfQaoJW_1fL_4D$!JjVcf{HEi=3HEUNu2-K&p(|x%-6wnXZ0Kk5dBUJW zOQGf~)%a#-{;Ej~fO6uuaMn(`l=}$jo7RWok&1Am1CG!9{$^EK#&_9>!;<`083jTO z1sU>fpRXwUPt<_Pf|frODTrDKWQ6KN8cWB|RCI%-d?%l#Vc`gEQREeTiBC^_w%hbJ zGQtKJ3M~_Xz%hkBV2NmBGuB=cnh$J>_>}4wz9yfMzO?0zHMlqRMp;*dAAC`(5>y?0!P02}pUx5q52$v`!tg8j%e;eNtYTGyRaS zx?Af>3;A^>+4+!**F8K&V^W7t+y_DAZ9&d~eHCAA2_POe2y1V*p4;AybobsGC?4}|>6DRfnkD@5f=Kghrz;4w20P(40yb!4(B^e+2xa`~+ zN0~W2#Cdkpc!&3_@7+ysy?1f>2PSxuUPiEpVvkaVzKb{>#poaVY)8xNi324#ncva_ zIHpY5TWjy9qh_3S>#BHfH9}uWIDYHXS59pyCxYligp-t-afH)8Y&B3R=1lrqwsRdK zzRO6L&rVMvXK`i~I@GWkRXVe`0Tz*|Hk2K2`q8`%c{NEvcnF_CM18P`Q1h}ZQ|cO~w6Nl8#d;v_E{;(a z>h`M!esxayzD~#!bWQge6gQnXun*>&!_}1^!z~+0^UR0{?8c4Dh}QEY*#%1rCX($c z^zf=|PH=&^1Uup?>|CS{Cz%^XmX4hsupq^a&#NYXis&~1RA2-+lIsL2(qM8h%wXW1m^}O0Wl4@#pu-rm~x)ePle{Z(iy7MxyI@$&WYW80b zKt+NCKS?%N?hR#v<@`H7x(2gBo=8O)K>!XUQS1;>pGPxNHWBq-kKh4|qHstSLTeiK zwbK=6xGyT!o3q4bPxC z*g(bJXZ*b{{;kmb73(bTsMnM5B(CfuRo{KMnJ!Ry05m{6u{9=B!`u6mz#SY9MjK(; z4_)u{-C2FoZPUs*fr5CzKOR?R&}bS`cq*#rt$=>+j!f_2fPB&`7!Dr51lFBsf#eYT z+4ue0*jIN?zeSe~t~K&9dFRc#cDZFFNT5QIzc2%+KfmC!aqcG@DGflv!jys_wxx&j z3cRz3wl^t|fD09O1{bT8w0bb38L!C~&XY41T7fw76CZ@aLae^3z`Y}a-J4U(ruC&L zdi>|fvTwr#nDDd%W-}s~ME2S>v&@x;EA8G%f=xSRVMX_O;6wwAX#V!*yr<9#ix1`gn_g$SY7%$@lMRQuB~R}!ITR1&j^O77GFk0=iaP~gSc*3|JnQWQqcz|=D_JLefoI=bso@k0X@K1E-!%bd!9iCKc z9ImKVOk?P1AeLzaq_X2q}F+d|w%3klEm=v?E)K(V;l!#>HHyWD%6 zv!dRU%jj-v=&=j9tOSCwl25tsnFuubpoHL_Z$gez?Qc&@sderFKks zP253OjyzW1diQgdIuTqVJaNrWDa#mX#)F^>t0cbkY`_~-PL0_n;>2+66sfP#shfsE8(52Mp4{mkK+)KC53aBLJZwgk`Ih5A7cQ#cE|n5w{I5uCX)b*NbrXNByk2E z~FIh<5j|v+iKTo-(=K~^a)_vO|SoDD-v1JeOe>1H}t~Gm~+JBtn1)lpjTRXkH z{aQp%+;#)^j_4LD(3<$PlZ3MFwVu3V$|JtxxfMU(t!fQ#+rm=xk6AgC4-GcgfTkWHyDz$Ve+jW^M&CQxkl?uJ^yhx1`Hl(QM{c|$3&!9KAme` z@>uTL2fb?Na-7s*d1{FG1nq{KFFwu{SNE&+MAuxBg%7(Go)?C<*O<6owFX?U#i!|K z-y0cy9DOXaCk5<7`eSH~yJk?3FIV=zMS3GYiWmsoacD#Vv9S0ldZ7^mEap)|v|vxk z*L%v!M&>jqY&`b%tv<{3omt}#n_WfXxX+OKu%8eFt%<6mKC>I36h$)vlo7sdVeul` z%d?7JRY-7y2l#V;M-vNEFdur$s&B<=YIeUDuIszp=p&R3DCiVR28Ua8?wgLX5h6c`C>Aa)!#GD>nCJ zAUmmz4p6Qt`SBCsI&#>_Md-8#mQfP8odKy+5NE(XiLsIqZ0P(soC)JnTQ_ zA^#1CZ6@|-LN<(I@ngxK%y_ztaTIlAIU(vL9nDxXXQryXXz1tkUa~iA3=Hr9Qc$zh~0$rWH zAb7wox-bT#Z@1$6)2DAZZwrJafW(PyWMphxQD%tLfJ$-w-<1~CUFOk}i-BJ_;Hhkf z!#8}>Bj69Ol!3qk=funlAsENyVj~yv!;g36cf!7}9$)pp{Ayncagp;mHeIVTue9wn zsiSz_`X-00z1nimr`vT1uYAW%D#2-8#$`|>b**sqJ{&=#Z5hWALX(fU_Goh9tylojht zGX?-Eq<@!pb0xr;=M7SQ2r)v@EHH75su^h@TzI1EiWk76G3X*y??o8? zh-B?{A3mv8>8cihoBOf^J{GX`HvDH`MTT+Q6SE!kRkX|kY^lz*qPern-ugj__4%@MG~TnWCv-pz z^Y>)9&w}zg1JI>D&$OXGA(T(j@;+f*;C#xcm*6R9ddX1+o46A*K|eRpi$3o&`*n4^ z-BZCLBJ=Q+0@A3Wqy#u)IF0k}9Uyciw;bP0T0xvJ77@e|+r#XfB4a_Dx4fx$n_#eMTeMA1T9y3tcsPEM2C=#C!_ z^LobITY_1-G8j^=m3sjvNw_YjKgH~Hw#K4Dqe<_GP*AyZOrpyaGuNTeUu3;KljwDnm+52IHafr z%o=c?HDQ)(MD&7UN@_V;@TK0RFZ;1lqsq-(_sO>fFue=&V(ld+<}388g(A71(BYB% zgHh5@o?A&8^!JnbFRLrI+`}&Sw$SvRQ45NKwi7AnfSPi$)-K;A71&V>$TpVETYv_G zNl)1Yf(3&$JIeGx92MXZv#t)LF!<$+HXD%)m8h5M3U!+=j3>Iip0O ziy6)^n`oVHk~}~FazHejN#9R`0PO=ud}xu{lzN65`=tQM7Z)`&8GRM4`?N{8nU;M# ze!hAMHEaSq>wzF|A?vXby^H&=f-Ci3)kG+C^#v)Savu~{p8 zSfBJe2a_V|X3mtzue~Bq{ITs){`l(>sFT%wg zNsqtZN=-s)jaWp&EsoVB_$}@v^Foe-3uh5ilM{~9I5=Gnv!idwH=zO};)kIK!$Z8L zr{qp|cHvo+t9WOImrWh>$ynRjpl_)|IV;XEpv8fo9H1_e$s1M=WgTM5hQ+XmxPSXD z6Fz;noxEvwawrx$$BX1PEJy?&H)(D{Ogi#Kw}*JwtZ`}``n2D^Yi9;tN4;aU#T^@S zRFH4{^W!r%^~{fEala8h^dptUd|e&AEQ@(EgE>vJSSMZm@B#L%X#ak*XKnLhck|+3 zgw%k1ncog=o5r77lRo0}x)*wL2~+SY9}X6lCHWhVm!+Do5h}->eIx2HbH$mGP0Vg* z8!FLb_X|{;u*(s&2@`Y0p{-LwqHb4+jdaJ6n+%=g&G4s(w`i@MxN*jP9N((DjK_vo zs-KX4*RJna^Igh5~%_{uvJO+t4kxWNdZIcb*7wx<;p&*9`X?<*3QN zUI$;9FN*XemhN0LvJLQ4kCT+;BDJ;OIT*(`=JJRP45=L#pvfb|Ok5R$+YvdoxK9Pl zBq9Iy0;au={1m`yG7AFx%l zd+Cn*uAlGkdG5XMzk7DhnbR|K=8VO1r3+pPU)!l{#=%zGMB08`Km&4a4Rn96_s}4S zk1xu&K!k}FiZr%5*dBd9@h|rP|3h{+rp#_hm1?r>9$*;p(qdztDi(LFvDJg* zfCkahZZWf71UvdC+oP^6qH;>DN#shuM=#wrue#BDr{RkNFF0H1=o}&ZHHn|GGacTy z#6QHNZekjM^W_gFB?FQe2Cz$3WgdsqeQT4xjaE8^?FVci1(E4R7!wd9M*e1U^qS~| zBpuq&7fw~G%+>Mv`qxTI`AaDMx{5wZe~VCqh5b7BZtyxXxcgSHY-+)4s2+cMLDZbx%#mJZla>0m79U!|5MKI2op66PFA zLV+(bHiMZBtYADggWU%)X@|x5QUsSJBNtF09IBf!nXZ*P&=@^|i3TvnVa3@?zy_q3XtMAO+_I2DsT@2ROIvDS)VXhHaIgoInHeFSS zY1GD!_|g2dbN}-G$~Nohx1sy_0mSX|3<)j?=CL_$CDlBi)oi|b9~~_R%%Bwxl4D$- z*7+@>4R?>-MTSAN?9b}JmQ+}6;@MjWDj&J|hMsxv9h&sh#bS`SfAqP&L(G+m;>fG! zjVg-v%hs|KcZH7S$jU8`xaDNi>%^7t0FSXl)E2Uh;=>5`ZxZG>-zGjCgU&XrE4t`T0YtGx|vz$<3%ai7d( zDjdH15tc>)SUDpg!Ty`MB^!uqo1k+Fi9bRqoYJ*FfQdKK#FUhR_C>`H`A*(H=pm2l zwx@;}fb8zB-|2Zd*;hF~pXjaV)}l=|LmFQXro^bIMy?QKSgPuvVx*f>hA0u4VyyAe0!Zm2`i!i) z4fKI%^PvbPx-vx~DO%ok-^fDeZ13i@l_=*n60}|~=@PZG-8>JckNo%gW3|Kd|7FQy zJe$KGY84wua}p}@>{l1QWO~;1_4BjL47Z3qH-~qL$2&-9x509P=c!l8W}5iTM)q#7 z%myjZU5n(6xjMUZX9#ky`AhVBq{ClAtxW;SX@YysgO0Q* zO4ZjFZ4;eeeC_O|+g@GA-R?77t4Eq>bzh3?&VOizdZ@NxwU463c8pg2>agK@|J{Fg zOYvAFl=<^cX_o)M*t}870flZcA&+EEFWAPkX7CJ~HMq8(|MTxCbjG%oQ)lWY`+bX% zXt0b2WKw=yAoz3BF=yCwsN&d$x5;NpkjEDQCyKZkw zvO4_Kx%00n@4%JS(os0lyH`bwGMs&KFHHC(#@j7al zYZJfwc?9*|3#iYVYVTXZfR}qgm*9{e%abcKLnc0$cN(2Zv~6-l;Cx@WL7{O&t~8fI zJE;_16;I>8;jdqI9uda>?!UCs8JyhY?zYtW6wlRj^LCh#Y~xU_a?s+h0Q$o2a4uLw zxaXu+{pGZQ*?2G76TU=RVIkR%?8<$@YIaY@BqSO~fmnYD?RHQUCvkHAL|bmJVBxEh zPrI&yrborZ-`fkSFaD{|44czu%cx!hPuI&N^x`>8m%M4CRfYk1t?iIAtfEc07R?@3 za-4UU82iJ;I?!T7GHzk|wBkYD7dm1$*(!TowcpOAR%CwcotL0-I3wJW5#KV6E(8Ru z&tBm2p=Uh@OyQlmDC{ zUD~|%V43$Xi@Ayzqx>4YrMwRD>>8WhU-6kXg z0&n*0}RUJu_paw0t8@06J%a&<4GK{)39a+NbX&hY!57`6=&v+T`zQjSViFJw1w zjEqKKj$py6S+L`P4Xk78VKEVJkrdtEndYH%06q?uYdja3J<(%yOo^R&A@cT=YnKzM=HyRmT z!{6pdwZ?0kkbO*7uNsCUt7b3wHg|A$I~U1VI7)z`v-nQ#&o-)3=LxS4LK;`2fw##D zv%tsx>JfooymOySuhSkB_dmu$9-Xvs$=ID~D*x`W$!XTDs-p=SIVlLLCz#>4daNM! zh#Fg&Vd>O|rL4ho2vb+{;7s;fu_sk;6 z&?HQ9d3n*5hi-k4D{Avy-q_)zgsHC$u5h#kW=>qm{9!X)KSn!jNq~`W-52 z@UbGO!Wn+E!nyPWx`@tQI(!)y*D^};Vp;fL$MB3#P;1+(FR@s5_+6pnB;|I3=i|RZ; z(TUlfjoizRJH?utf5u6p+Rpa(xrjbi2$)OH_>`y==E>cCttp;uVeLXz!Wt+ju8s^O z#Fi*j^WwJK^m#9&YIS$*F&y$B%v9@S5$eG$gwQ%tdE05mnjUo9v62SG0FHA!V(_PgJlSBp6w0+ zk^|F2=3}K7+(OClepvG&p*B2gJbamV8~Q^Aw=K?zrCxz$?y65#lCfek-UCdCY@#r}qRaQ2Cz~wJ+l%|Py zgH`|8SF^?Q0(JbY@t^xsZ=aG$l%xLp`U+mY`*~>-!H){Z{IgLXf_zDAhC|-O{r?S2 zdZk_H?4F3@W$SI=K^?H+K@g~(j+3qUM386WQW*>xpjr5+o~U}V?)vikm8fC5gylq) zn7OpcW52iC`_N&Q5pk!m5s!fk6cZ0_<15l_dBgps#CD@C*@*(>v~^S7JrKZDDK;wt zbbIa2=A#2pE>!YXAA0NJu6yX%@U0QEu`7Fo`e?I7iFG z1bCV`99mS+xw5d(nuNBrq}VkiKNjI9T5t85;REnbXfGn4Raowh#xS859?c^o*EKl zj}TGW{gZN^6%GeAtaJT^BBD|5+OUS)fog&^`X$$ZR;mmrk#TD>yQA|C3JZ#Hw1=mp zvUYn9EQ4K)8E8%3I&ckpvg>%{JGXZ|b~e4vJuGnaDLKRJ`%fvCnkKYIpdowh_U;qhRes|{<% zEOm4qV)QX-of-gLtwJ&~RxfW0-k9gK$k619pw-+*1M`U!vK&UXB5=HdR*1UYYd=Lu z8$Q1AOAS*{+Z{p%4m3Y>s@>;}N~1G*{en_Y*@50aQ@(|{i1g}7i=@Q<2h3zq`#$dLy;m?cJ)zf z+aqC{z12D8i6mm=`LiGBxmFS;$W{kuYZffWC77eXk1&ihuHY((>fq!_|Gt&!C89z! zAWIc_buzQob^E4f12_Tr*$dF9J1a(UZhEa8qQ9eJTW}0p-pEuBuEvbDMt|FzTmmsd zIR9v=FRrcNs=HqL?DmV5~~YVG3zR?(7Xu2Y%r zQ}|0=K#F3n6OT20dR$}AT}3c_b0oSrBdADm{A%m!s3Y2zqMDvBFDx*>a1|}=6-Fzn zEel@*zU<*HOLY4(`4O2)KSo?+K3o*>NKZGL*6B8qPvuEaW{?e*(-YZ_g`@5MDYduI zaa47K>1NwEpKbRs{)(1sk<^GQ={zB?>U?&(u*lgx-0vfGs`yEXC$|tbnsV&M*emv6 z>Udi@nOH;~w-D|v^x(GmyUJLcSYLm9-#Wt^1v|NRBEcO%{J!>9f2py;z~`_l#5%$AfwN~%6&e0&G_(rm$JKr~Ra4wYqHbjH%26*FdNk$8aD#nB z7?r#Xm2(A`U> z<|VVTpx(?UO>HUf=-Q=Y%sBS4lZlH;5~Khp!C zcPGtn+}*uH!u2E?P%hKHkR4G6#{ndK{OMMC;^tgCf7wq__UuqzK@GM(@5;!x$A3tu z{uUM0xq^sZ(o;cRMgs#E$*Y4#WN~6~3GXiZgI9jT1|~r~4t1Tg)zUVXNUvlafF$#y z8Nx=+=lj4Y=6-Cp)BDFHNMb2|TEI4szQ`K`?mq14=nw3l83*MbSCi-N-m3gM`o>Sk3^djP2Bk+U{%qX%Gevi<^?Xbz4;icv zqhXG@o*?Q;8UcaC)4lVYpbcT@*cB0xt>}%U zdfSTs;2f)6(^@$KCz>O^b*eN!DJsBUPEA`$(?bZ%>IX$9+Zm+q{Tq5vn_{XXGcr$3XK14tJJgY z(;bDwHw?IsAEgCQ=WPDXr--94F=&-&vqcjF8jhU=6EJ58W}J21{)oElSXE|PfK>Dt zn!taP-)p4L1+9kvY4c6r@U6)&H<_m{lDPiBZq2SMeG>nLz_|Y(D<@sx=cm}uGR8Kq z%vX98CQX3>_Z``Kiv24Tc{@;+@j11)U{jiO!E?f&_f&cA><^N5O`-!c@!H0^?Ay`K zOLGqXFhp&{X1qvoaSMX+9sDu@N1mqPNTfPq=-I_{r%e`-B1 zc$~IoD>#3?(_&bLd?>DEqaEi0zr+j{`Qg>TX?fwW@R{JmH~U+DmNZOa^vZO_m!!PL zOLJF`CO5}xzgE>iR3>bG~(#t_-lqc=JccKM}7+cj>snnw7LIRz_(Mnb5iF3@I-*O zbm10!!{vTy)^wlaow)U6c5htRn@Vp*ItnoEtWBy^yxOhn*I!v|L_Oq`GWYcP|H*^5 zra3ga3_Y=&tm*Fr*$ZesgDabbpn}M);2RTYpfX%qz@+PcgzmqVxnI5A`{8g@SceZz zjRL5Rw~6hQ^_~NI_rd*^T~PcFZZdLF9}bHE_nrS&P0%3e!MA*p1v&8KfLhticqDsy z;0>etxY6uC^dBtn=JgYA89T?{w*lIq1aq=tp#vq zmjBrgP7mqe>svvbQ=9BD*&GI#-lWDOV#)uGCc|$3Y-)swiq-uHvC zT-8;C3snvyv;Vxnhfv;l)YY*+>cw!~oLC%1CBijQldZbdmSB8YM~)M_;%~%AfHuQq z;mS%!+drQ+a166s6~J&(4TJF6qDu{wKBH{v6pxYo^!jJt(@oZY3@S4+C)}SJ7w)aW zD`S8jK4`x^5gMefP-#TUooFU?()e%w843!#aDmHSNBsx#?f1J*Kv>Wp19V{|hQ>$; zqgAxBRw)FYFo@+pXlFbenOY4y54R!pG#v*qRX}U`$$-C{GiYINt1^V;lGsS@}P$7(@B*S;0S*r0rqlt1J8ToV!BF- z+g2;0^q+eZMyJI}G`rngvRSon_!yU8e(nF?+YBqpkr@`QC@0TNe9;t@;V=8#CX=Hn z*iZk`$|53$cY-0b-;COSz0MAlC8{lE{W8t@jn~#_1dpa_|AmljXMr^?nidWNy&Mfa z4mAW74uknUwISu0cXK0OeprZ?xxI_Gg`eb}H9vH}v^;a?Y0Wu$6xqm`kWa_sY>@QF zs;WBI(ZwQ7zcDI6&FoK2NlAsX#|=Ya^`8drgS#Lj#$8*G;PKr-yrDVq)zj`DOS6k> z@OC^NF96<&?DDgC5`0WKvwRlqe9B72&G!Yfvse67M&Io=g`$r4x=MwU?46q8Ix`{w zelSx~0nI2GZOc3U+sBpeBnvt)io~nraZss-9_w)rx7Ek#7JJ)8=V!y-1e&dg!vOou zBtU&09ViEXJ`2h*!|_SagKUTW^P{(S%N3t!2F?rgu>jEF#yX?FOc{53>RDbh>2tRb zZCZe6)3K%N$k9=3A(v~LIDItp?8s2 z8Er1_ema0>%)s0E7%*6t3{&BO$L`>F&&PSs+Kk(sKK1NgYq2T7yt{w+%Mm!Z+c!|>COXtSy?p` zz?CMABL8{t<2Dr+>-e4J3H;uznbX0Th3PL$6}&k&o?DQB>B00 zHUblzv7d)ZV$An6^f5aRaRouo4L_!jOWZWw_2V}e=~p(O*a5I-pKKM&kkA{(jv60| z@~|m58tjY+N%9cWV-_2HjO63o-K!<{zQqG|aUfeArXrOJ`o|vm)tmlBK1fPl4cyJS zTfx~W2Faa5oI8U!lQ{qe3ExwEtmM7hUhj~IMS0qX12`WKaNd8FEDoXREU?@sKMuW* z0&`Rx0Iu}Z2V;WUQ_B0OT5bka&w`8rhT47s*tGEI8ncl78q?onKRrMImfNS1A2ogu)!ED?II`j zAMYbFTP?2N7U*Ml7NC+rB}gi_Pi(_!b^oON;yy>%%(-zhP7BweQEtbL&w0<&fyhSNd$ypbc^!1= z7>U@;o(&5#9)18$Y1HG(haKl6axD+1Q@)7f<<8-$1<*s)JH}8$PY-`4s?k?QCvHeE zNR1ygdUCeo7VAJtUn=1|dQVNq0>tzDypHV#J~L+|eB6V;!_;$6Me~Q6=gp17 zJAV#vVq$?FekbA$F0MzflidC2aR>ii14D`-CTXn`0Nweev`pr3GkQiD^LV8*ks6@# z4-$&uxb!t!oLQVTw007npH5x zfQ%-a<8wq~Fr@wOLzejN1|3`Q0?N8#!e3W^-_#1B_n$~0i_f1TC`$)mxrIwi;)~CY zRJVrrG}AwyBiCb~=LVSi)b1&^Ne=wFk#Z&Xgbm3nl9A7*t+Jn)Ff4f${L+xPK%cNP zA8?a#V~q0064jDGySkX4{}Z<24=;r?!;JQwKj_%l_N$#5w6>6=Kul{m+7BTbkTl?-A+iFZo+ z{Jq!mPOGUZdr--YT67hxKh80DI>yobhqhGZr)Gn6%-OBS1onI&dsxWP;cVp7*(%$$ z%bkomr{d2KRm7ygV2nj^#~*+Ae-L$Bz6{4Ma}!`!ZeWLiCl^3V3qjx?F&bN`rFG6P zV4z0TBKqnXn`>Oc9yfCi59{l@b4f}q%#Z;*!A>_SB3QBsODsa3PH8%BI@Qyh(h zh|*QuGpT{zlLOz~KkO3|;oZk$?~N6DI|@xo_dZ?`Pjf!^+j*84Gl|4wPfK%9iKFR` zZ(wW^*en083!4fz(F$1HAc1PxW&PVzHLhZ(%$_a8%=!7z^>*mlMB(fwm{URX(-&B9 z8P@nYwF1U0da?>RUDF)~DJ56JC5|w?o9Q9acd?6Gii>1{Z3lsjwpkO3c?R}eR-6~^ z>iVeKjZO4iv_a>e021OyrZeTQF^c}q(rYs4-jga?z!Yg%!~LhV!kONrp}+N<8iDA` z0JN8aoxHc;{a+Td28n}9q6^vs)c<0O=grZ^l`orXm$dwGtL`{RDfN`4l3g$^efSl9 zg_4sugEU425a1!Vg^}RNy|MOBkArINzE22S%~afGfHbxB(rE@>WgbeFOtZz)Z+(ZM zcOGwZ9k?FQA?fgX#O|ov^#X0H%!7v3P4D)1D%vlUcBDI;4-xSiF(z4VgDo4Zv9Lb)YyTFAZ3UDIu1U|x)|9px2I6FZJV zJbsuq`CMGZDRacaa*;2{!+A*R4Q2~k-tw-)Lg4y0FVgrBo+1K91v2$ zzAT}0kOV?l zg1*E#0LIOgp`yvU^0ynMgF@*eJYOI>e#t*!~~vl>sIuD9h;2z7Bf zBfu62N;9ql$9XN9ycdQAqF`6VNEkGBM%i1xG0h#mIdQL>!!^*`ZlV}&Su$`mgN^Gz z06la$GkY@@Ci3&~3|l0uHSN9AE|WP2jI=Z$qZ^W)2dTLj-K$?_s?4&I(7~REgm~@( zc~8-1e@a5S*val+**V0MTs}Fpf?c*Ewz=z$+)zLHX3-+4X#f^1K;Cg4 za608*3P@7|(7CUxNs2RM#m;u>QUCeG62-IklahYWHSZTFiSeVz$*CjLch}by1!qiP zPN=N|3^T~Qe9Gj93e)ZO^O3~qCSQW%ga90SAPm@qL}P3dJ8pS#FJZA+pT+?IhAfDB z_d!$k$vsDU{HJ4}OIj|;75n1pagKi$B)q4H4Q_Ys+7ol>?hfsh zcBjyR!5T;6DGhKmV1Ro!!`(HjMZqaKuteE;0?bli6T^TRSjAm*8wOZcj zMA(~N`nh`on@TxuRGv^DtMe_8@W09uPahnmX9KJ+W2N`s+F;l<%XhV$-cSj9%$|Ia zdF~N33ZwM!eXsA&@}@!&Dy3?1DKucj9o>V{GS}uc^#R2=o+|+W ztaI4aOKJZ$zrFr^QolpYt(ymMl^yc)AYjB5Q9aKAla_d|rK@7(EDIO~ZRO=O8HUqZ z@~aP7^1U%nBU2IOXnz=Xgn%Dmq1HQ6PtzCW1PV>}-l@WNn8n6R|Ltgtr=akGl7<5p zaf*;N8@mqYYb@*K*i-QDEOmz34?kWo<0Y`x;Uz38CP3EZP<67IgT)4=Yr!7;SetwD zp8{WshPN3&kB7x~<|Id(Vp1{|QuHgt`3|7+)w81B&%o$=|pk07c8N&yGXA5ceAwbkY4}9+!N&n@U`4AE?hG6~z$5QD$6tj(_Y$UoH50 zJ5Q|B#j6NA0|Gu>FkBewXxN~n_<4whT$`kfj7fxcdS3OGm&<+{<2oig%uvbX}F)!7i2(i`b|C{y%!(X^`;28jJt;mj-xT;j? zxXS!sLeTP~w0}bBbj}?oGU@d7X{H4_w{&CncKTFL;VCe2RE#HU@l| zuKs=#r6RfX1EwgRs7jlP-+>Ln$vbL*bE5c2A#)gZ4U{&+K1**^RKyDHo}Knf3+&K> z@$`Lp8Gal-08P(a00I$K;p=1M*w^zF|Ht#UEFe|TO`P}ra+NeTB_50kA>Bp@6Zu+@ zMwSJ%KlZOVUR4DCZ|osveth6DM&|z~ zC=JxDcygIhmWvXh(RXdtl_1Ie63q#3$aRB%g3>a0w??tBrwH`bRAdr9Ja`9x|@v^gd5nQaP90QKZc zvG7BUyV#F+YZv@cx=tiecRy!V3Qq(b{V{BHXq%;eAsJe{Tk%e>evnYUzY@? zMjdQUe}RpRBVqA>4^=?)lgJqY~|0dh6-+p`c+}Q{l=765I*d z{vgyzPr6x*^S+dD+3_5aaW2UG=OCWH4sp-5%=SW#Bs>uC;N*)>zwRjRsUcvt2FzOq zP4PeaW>A7Hb|v*2b|1qlmA~R3^}?8;qBr_J4+c4`vRL{8^BSE>M2n}$xWyzh=ea^H7t7B+URyYlbCc(V2^W?a>cF;K9Ax9!sE(b*G94U=>hW=V zuJ3IurSOs1ngK6mY#;v3Xv^5MOb49}7kYS@B}^fsYEU@r8%;(*J6KU(nqgs#>hkrF z-T>!3GcW>L031NNG>5qf(kHky)ZdB^`bM_I@0kOUJY(T#`l)GU6&lIEC+%Z@Pr*ebd-`Bmf6*+jLa_totz4v8f!!0JU9Xg_oXX;wfNxBKb;$I7mSIu zme?-#d1JdT-@ZbIis0f-%vT8@q;2m&Z)!y2D}e_iu05AP^~OeNj*NkcJ4R4}OihAz zifUTDhn=O<`eA7SC3eW1B7{mwbXi2=>3%HVK(u)>RqfAV;WaS5Pdxtw=7oRu`^hu7 zN#2A8-QWY>1VND|M^?F4|83HPSpECRC9;4rG$q!aKT zC}j7Cys!A2@~h#^0P5UTzfMlHD=|Hq)K{OjhbLu>;}aP3yN@~Mj$HmCrz)eK6B{otKJ;v5YcwExL_pGheT+FM1Dl54cGXO{G0@K^7Hu>up zMyv3<(W+2%+zAHFUeK8#4Scdzb^p9rERO%IQomLqnk~EYM@0N)p~zRUnMpKS7F1`B z!R>qqbKhAOCBF9Qp($Nh>*$+)b15aWup$j8gG;Wr+#V7Qc87>i!Q+<<#bf;)Sn(Gd- z{G-@%NSAA8+y=K^UHbaL0xq6-9$#S}*=nkDR$29|zaYU6P427hm)tff2{VHq?DF(F zh&Z!l4y6>5H{rTG%-(brpA)bLH(yHCu{oK3c>N(LU)8+ii+Ng(OuR#1WY{Y;KHaN+ z4e2)Pte&pK8?R~^L|k0`7sW5qNa-;VC?*=u$9Edboy+FAg{40rEb;g7dJ5)T^W0F~ zOEo5A;tulNj!XUuHj1}tB%4f`n|?e5i;v9-(cM1 zXvS!Y8#pgvms;;#(&X{h@6wc!%C57`#Ui+#7_k+UO_v7u+e}z3s!(Fw2{%|kY81iv z*%2`pu`5+bOc0%dGXcE6a!BZl(@mtzlLJ?yj1dl% z(k~{E=jp@S-P1eNPix5G+PE2T`FfMw3I!OX=V&qqCn^yjnfpNLdU6Yk`g1&`7c*iy zU131tf%%T0aHK#Mc`ILEw{$LFhklHi{ax+MnGz!pcM+U9)k`g=!fI;?#?5l=d@3aA>Zl#M1rQ%+Oc%S#8u|Va#}N)-_;x?4L*3 znhs$G(@9d{pH^gI83~iIy5);=)}$v&o6G)+Epw)Qyq}L?!B)W6E>6gNpNF~0jDN-t zdA4l(@lC3Jszh0aUk7IMdC)aG&?~!#eSP>+D_2DsmjzcJDvYSabMOWu!L&Plp|b9D zf%NCD{G1%Vk8hgND|NIQcn_36?fWfg1_ZTF7cuv!lQYr0`q8dMP3|BNf&cpD-{dKb z&vvr)hvPaX4H8z&c=}ny~^aZYdQ*lta8J~H8R?uQ(wxFHrnz3qH zbbmzogKD-OYUz5s)Q_RPGcQ~vMmb_Xwa5~#Lq4eby4vr4soSQ);>D%5zn()}aI>Tg^u+Gf2$ul8GxoV7q@h6|nK7s~1J1yUc-YZi(hN%-03q$O%F zAF5T73@(Y|lNVx>YzsdIqHeYBqXBj>ZPo9ig+_wC;DjOZdlj1k8Z>lg3B-?&`_6lX z?#An-L=fgDsK~uz%5M;w5gBsWSd-TmTT~)O_{N!Jq=~cf`cNAi=CMuu6B;&nR@pGR zVVADvcwPQsUn`c)F(PHBZEsPBo*0SKJPuDvKr>+iSYAeYO?}2J0aBpb&aM8AhpSKO zx#GovVqvEoE68EZN7ERqF-TjqX?0Om&IO99>55PkO6bz>C9%XGT!^uGPMpgN0fEI4 zC- z9|W3;n6qx1rSN}0y|6QUU?bJ2c-82}zJmWuu(Q7&_xkMf?`zP5_oJRZZTsD>XJ4eYAhFxCDxcOi$^g+81NlE#*y_ zMQF2e@aAgS_HD?_iHUJqXx&UIc8TN(`}P^tv$M{mxBC{OOcrJC1w+!OmVs4hn``E} z0GIRHShECIKaLP~O-fE?UR0^X=K$-bh|wL(LUp0Dr~WaM42L$?B^Ptb@#mdE1F*Zt%&FJJx$cx#%wB)sk#n%%1RJ4*yukn@Z zwr}T@cH!1IxkNm8YuJJD^YtX-{|c{K~#b(nrQZ-gKFx=w(ah}cX&j$T~9$0cYyk8Qi2n_3 z-GxHdSwUD3iY-pui7!(pW^a`&$2Dz8r$4Ff`QQfI7k9+2BY(Z%;=j-1_I$9u~Rs{1L>0Pxe_r`t`kWH zKF2>h9&W1E{3hxiCYR|fmMTKbCq3uU-}mb`qEr1wIh_{D{MC+q)cy0+s-PEVf*=Z( z(4BdK3=uwa92YBjG0>7`^UiQSom3%0%Fy;}SV%Rsr+;$TD!+FL7(l={y(fO#iQ~$; z`tsIvef=>P2O)n7xsD}bn=@F1TK7_RR{Ee7U6}*d{KxsDtPH>38J*j<;i8ft9?HCiV#Y}!DtHq zyZbRJ|BbFki_glq%gli|p_H#o-7*$}mn3~eqyL0a_8LQeq=fCh=;C9Zc(s7J;C|h% zJ+a9Rxwc{6?!0Dk-H#`1w-0$Xe@cFL7)PUsZp;6p)hUTRuhwnCc!+tcXmf^3<7;fs z_`LDNa!Pg+T|n8}iSefSEiG*KLb!3b`;P4`RfySluhMQ_#f&AY8eYZQm-+oe%n6Um zUJ0*MIpo=kuWgjHfT>$@m}?2A<+!fW=&FM|+nN{dSkjeX z>t#Qbnv?vvMC;^L)E9C%Y&@u{5f|h?nP2U9oHH@$ZfE$~$78v1+6LhBt&jSPwZ*E- zm)v1SSZ}=kLptkx0-{E!od1w8FlPKknLkqy`el`8dK5QQBhMi%G6-wBZ?(p zV{=HQjW(s8yND$y+l8U%%N;!;1wAqqeMs;6J2Yczk=r1V;1$B3 zNO-0k4})y3>2zOXe?iy5(&1KC!W{#Tiz;W}3bd=6=NS51L+_3FmHQk(Me;9anp^h@ zgp8j$#Rw}qCzWLQd0^3>>8Cqe+|)h6JO_m6ulM(`!2RJjQRmr8FQ(1eNu3Gnv?KEE zjcl8gG6y;XlycwxTszbZhUZB(`XFV(DPcVR%krUFP-;yxf* zPoYI(<_){_93)wM1R4!KB|fhre&&F*fsWs+1sXNAdA13Nh5~(_v?Ks zN4|f-k5A{@q~fQ8Y(EW~4^V_UuJCjswnBzlbjFc9cLPF)pG-R_{jVJ#IopS%6T^D3 zPyeIn1%$1;v+&ZsSL^3gT_Ld`od2v(Z9t86Lh_NEdPh0&@r=|YbI$x~xQK}I z`4%X?d%lm~d>rGHY;3;4^vM$sBAIi1_u>{+BCxlCte|fCm%6`8f*+jW3ArqFuIk@D z?1@G#2v9+ZFa>%-?#yB}xNb@y0eIkbo<4uof(1pr!i7~^cr{R0? z%}BJmIRUlO^r1>G!EWne4~YEpT*=zwM|(>1ju0<$GHu^K@LLuF-h!p?Kv%ZA&7LNG z`Y{kxrn%-r5;Dp?|kQfrPfu`IpXh8r_YtYjgf3((tRno}Il0HF zN#85lFWTGlIw-sLT-%u#ME>?@2K3*=aG)#jenne7R~*0qq5h)7#y(Z?MJCEfE7Uj? zAFMM$UG0xKIyP}W-S#RA6E&v_e@ZKC;7+9@V?y`cp51o7E{XPwMgoMfY=gkC{_eq? zcAS^LyQniV`YkMpHOQg0nt$Cbw1_^Pyc&l$Kr|rs%%!xa_|x3Ygq*ecIU_70%kN@} ztuKr)+BTgS3B0?X3cRbt8>~h2G{|{4N8C6x+wM|G#gLEHKy1Ppnk#3~B zQ@T42eQ2e-rCYjNkd%@x>H0Re&pXC92LAKxwPw$`_gdFA_#+kynP6;Jl>{E#*FW+V zj;B~|^hh)Tzme)2H{K>B$vxY?<=|@*WK)}sjvK{D;aC#`ldl;jzcU%CFBBW3YP8eU zRykN|PgGWj&P5Kri;_dn?Ff4aneN{g?cAw>5H|JtZS}V8O}_Y&FxMR6iFh9R`~J=F z-O16p5RPcxFQlQwTB`P$92Cwt&m(k z=kWRZ>BER}ZaSOrv{@k>elF#8?Wf zyb)%-)eZ0By19XQ#QK>sR$-SAyqD^Ywq0L;xbnDBdbaS$l;iuT{j!FU?+E46spcEUJP8Uwq@p> zNQ5h9$6UZo1TN&WqAhO9nQ2K${O%%nRf~h(SNu^~LNe}qnZAPgmRKbtSYqJhLYsGu z8vhWL*WUbA(A=e)Z$sWFY;)JvsABVbSbb{dDq`KyNcGcMu6_@~Kc2chvhK0)|$ zOcY1T$?RrKRu6VS`hvi0FTEJss! zEHNeQJ-lyIg#%wxFZpe^@=CMk%HvB@J^H%Plg8hPYDvS+_KZ+Faue5M^OoJ;O;yjS z`nQ{K0#C@rPeAhMG@(PGa~9oCq-VFQ#@pM3Otkp#osrq4<7jN3xXaMA+3;^7+?n&C zOK}mM)ZJaLoZoy=K}j?hz4RO#lT*M*h7C2t`?8LJM>8hkV1mB#fpizi`SbcY2hE+X z`ry|L)IO16l0l&!vMYnTrVq~E%C=_$_R8>nX|(T~gq*pE+`nM2?C7c+&3^cns-8Dn z|E0Pf$BAzgZioJT&i^YTe)A9LdZa-*Bn+nWztqS>L+3C_}xy_kU>>aycS+ z=@}K-5b}1=sSb@e5@jHgEINi^%=Y4Ueaux_p2P+FPDE$UlLy`F4UIV~*fCQn1Q~BI ztaFpofi5u0+<%OK#hN~g&cawS_Rryg>g<&qgz{Yk^1D(J-CP8D8YMu^1@FY*XzfG$ zMEjECWw!(He_W36F>rsEtK)5KkLgTv>4MLWF&j(kd3GXj;&lEV@C!e8!=2zZM6fGE z_u_mwpj^1E@qTl?-8Xin%9r73d3o2+-tC3KpG(;K_bty|k#8i+`HBCRv}S_YJM(ZJ zuUR+aXoc_~RM6~SqW+g%;fuSKJFnzP(QQ#8l#@_t7rt*TSV;}yj1}BQte0BB-k=Le ziTy)m28`gNp%%L394z4|n>I^vTh6rh;jHfD(CMdjvC>q@?V7hRlvX%>6zX{zlBCO) zw59^kubiGgWbA|kO zFPi+$b<@^%?V8SW_XB*d5DZZ#-dH?dXfi+C+zHchB@N|Ftp*QqJ|RFIjlBrpz-7IJ z)rMdnj3w(I*K~R>;yj~Yj5}w^StSE*Y{{QS&mdtS_)`l}+p|u3hTa)U^QH=cznS&3 z96pivhVUm!g@l~nak*^6>t+0Cg(`&OSPgc+ke*9!*PXom;@WoFM6Hs) zpZesU#!su!<(H-g<#~!d9A{P92z|FNDmbq2%pP6poM7#r`QZ@lZO@wX*4*_W(p{af z5Xoc3>!GbEli{zOXN!VLDeJ%pesQ2op!psOe71#jb&NUwIKx(K(x z>_c~O-sw}xBy!gos`tZjQ}9xBJ!9ARqxDUJJEC?rLA0#(+I7f)Jh`)_r5T_<{Yv5U zG!pZp9FMo4I)Ak%!$Fw*TKri-(pfFUo*2P$_&@GLq0At5GcU*tQyIdTkV>)J%zjm| ztA^?qA_8p|7U_eI<~t2Ibxgi@&L!hgZ@w1sMIYe>heEb6hpd-1aF7{AP&m+6?0Sr# zkKT{H@SSW+K_3v=UzcvCIWimhQQVvb*N_=J4BvHWWd~nv+%}FkUh?qx$2!>Fv3$`` zWUKvc5j`XUVBVT$bOsBZv*bn)drtr_>Ify#Lg)o#F(gdbKATg6tU}*>=7V*#)y-Z2 z=!q597 zKQ3^eGSFyQ-D|!9T*l%|5My=nz!P&x;Dpjj^5S<@LoGhri>LSuJu-W8Dg1W_7Es-~ zw)V$mI%Ihw$;Nbx zJ+{;Hb1B5`iXwKRFmAe|QPO#g1R9)g;;r2BbQ}5)bcGIm1;`DCIHf#uYHcUplXGMz zfgTcL-}wO+8Ov1yT0SY~>CN8;Qpi%<-Gs7a9}5(Wwbm&r5XQ1A*u1|<@44q*Uy-i< zBJj$ zGhKG#5bR8M(a^i>4tMSwZ2_dL-RIH3s3D7r=J!l*!PNE8l_qSlI}xmC@KzrrCDAhJ zJ#}J6`FOW?$n||Gin#H>ZqEEos;y0*W-4Ra4a4Zh5TKD&)1)P@G5Zj)^0~>-mpL){ zjBOvfG{zx_0jOCM45uAfdK=>0*|6{UZUKHb2x&f2b8eq)=zTb)xQ0dlI^p9jOunfgE3$wg@D<_i*U)s|H7B@d$!lnq z@;4g6RxZU@O6|N7hqWQ(^s3QnR!L)=o;08jBc5%VN^enO3vk%{izY^*nNo9dC?E{Z zU-uyB*Vvd4{@`VCPDJ+RWg1L^x7`cFK@)h-{df(3Ww$9T15{0Qs=D6R8mBG&Qk<({t>(2#tOSKJp21{Ku+A3uc!+=-MLik zB0zn(D|OdzY@x@cEoF+X{?tT{7S%hY{=l`fg#~`^MI|;{>|F#oVU=SE49Z*1h=_OJ7fo1AFtXre zbSRuS3YOfyWWLXC6z+(PsSvG08i#XQcBtSKmbX>P=qlSTuToZa{UC^MfhFE z4Hh^XXr|avyCR`UAAjUb#3t?Jx6a}&nV5&|DQO|6i)2p;;-+~Gl=n;Ph%tbim4nCR z`s+fisqsa%c+3xwV*Aq@GH11q>)kp&ET4Z%|4V+xnk|6`&hK$4{*HkiB4x5gkHG|z zuup)one@Foe1&K%3MT-$fU#BzW`z)(|jOCVsIbkkV zN?}mtAOJ%Ci?n7?i}%v{`-4qM4rrH3{>mh-Wu6CHgX38sWsj8?2+D&lBH(JlV}rr> zx(8d4GX2r^a%7j~Rm0{Wbj8;M!8SDBrBa0UaU32jv|&(m$XYTU)}S;n#we98mV>TJ zk8_jDPc0=$D$SL?$Gad&Fq?~+_i@ZOA!qsanhv=+1fZir`Vm{I$ zs4k-PeKR?zZctj2SuNlHGm}vfDZ5JrBEPNv@oeW3tuhJnNP_}B4HM|5$7zTH5+7-i zF9z+636An|>$7|kJhPb*E*G`BJBVk-wtoFE@K#C&LCgFjXxmhF%4j zGWT*+T4R9QYRg)he_PEx!#*1=BTzYS0E{4YH%EV02J26rKY1lp2$+FCnDc7k%){d5 zRcMV^C{?q4?%nWn>-V~4>5v(f}dsJF@h&abpY z4w@=q8j$-+1rngQ;ojIz%g9vpzN*x0bo{hUVFmOR1`p@R<`qI{!WQNP{OD4oa_UBN ztbn~d>ZA`P#WCU*&8JX{B8GZ66zbK4H>7j;aN#+X=PVhiT^(+$s;~DeEw)Rs7$b?@ zq}lGMAkmSTDr^?oPokJD$UHm@IuX&bERgHX2;#Sd+wYci-JP%BR`5&&G=6+b4G!O+ zOw!CA_%!yoA5ws`=48GPuPV8nzzSbJk3t!dS4*sF7_;wS=DP5Szufo!xZ>x^J5LP0 zsFkmsi5Nfnx3Mw7ZERzXjz_&N%EEh4>w6Eg!i-?p*C_7zds_SFg_E-P(Fz4186chd zDF+waPir%lEf=*NAe`YWQJfwz^qFJ%ySMtnG`W2kRb|A&aL9!9$ZoMd5L@_f%n#fm zi7`)<<`AtIsdeVbK{v+uPXTAe{ulAjl3-czhyQ#%IY8uSVKZ8Pf9W_xoow%SwIYbN-%XwD{8-@&{qF+dVTC{t~}c{8-uT6rRVFN7HTx= zq*}eaq`Qi#VSC4X42xmY;jAzrSOOp^0(ZE=jY0YVuz49SGG$4cjbPOQD^lfje?bcS zknNq=f+*4G2x1}iZ&Vgq#e*b>Bk$yqF+0X%CUkO7Dw7+szn-KGZQ^i=6EZZ4-BVow zq(KN~PL|AB8?$Q-=+fIYugx0E>W|>5-HVl6Ix>|>O;eb8C@g!)$Xdsui7~mcYwr)M z3Q-Zn`tw|QZ+X=kNnZ0IRb|3s$Sg2ObWRsHfpOn!1hH#v(laqRC#W9|5UE$fR~lh~ zSNWt;`;q-0UHr3c=u3w30TPBGgFAON5`l-V=k}i72J{cx8>jC#Zz-jRdb`^`@iBC0+cM_W@d@IVj0vf-yi`R z^-7nuAtyQ`1GGY4h~As`lNWu(aRWW1>?xV>Q9xp&V9tv+@*-9wrX_7NmIl|o&%ITJ z@xgtR>DSN^#7N3`WW{aDxo|o3yVIpN40WqU7=xe9*?#|sMm<2@%oA-e2R=Ct<+~0x z_LKZq^ac%V>n>JM8t)M6&tYa-Nh6O~a0x3_uf&W#2Et=P0$?+}PI4dlyC$gH3ZmPF zDDzSPkv8}I2cUw+pGBaJi3;G~fuqzzpTzUs*v$bYk~6-QC>I8fy!mK+H`HArVX=Xo zPs2{UOMjM@elXWw{Hi)zNg)nzE~#I1#i9%u{0WnLhvTE&Hg0 z-rg(ax66q|m;~Bs0o{SPwzDx&DJHBPF5AY*+jn*^iS~8J($S2WX5894%5)fczqrTg z>0(+HlY0O3Hy-=|zmKe=GT3#VnC<7YkQtCRmgmUYJi7^u1bado4254BjQ6)j0~_h|gH!tk-ZE(H!*~@U%|!aB6;8bze`y z+8%6F4$nG02-^tWOl4+GA@UbROcW$C!Us+rXC3;C!1G-A^bl3jQ~~IJTIlRO*o+7D z_dA?ZxUSsTv^pVmo=gPlc&glhpN+NF&nEM*g?7uNf)WcOzNI<-Etx!j4)|th9JtE` zc5^Kf5l=(N83~U4C}I^)q|@KDyx%No2Y$d?+30iJhTm221(;&>7jY3r28u z6laAwf`+t~ZuTW^1ra_{@X6g214+*+4Bd1^LUdrS*BrXNwD3Xqy*W>y<8m-2 zB$YnzBiEu{XZDOvBwaK;)Yn&TGChqh0sj^O15tbg*Q&yX1!JWgG+sV@c2BkfVhspJ z6jww$ai2^p=G~W1BzWI0GC>!Oyq-|kz1hX#$9-1uA55!C?AwP5d_xF6mT%6+EKaQIJbJ}Y}>GfY!sINjviXv z;KkQ6ZD^X|ub08okld!`g+A+DK{M!jXe}}UvwboT9x5RD9LKcP`Surd;~?ULO;j_BnkE;WMkxV}1u2(7CZoj{qHa1JC;!XA+a_0}mx^ zh#rA?*j9rE<$~elhrqC1n`LsKO%!~n!;&}K|Di2&<32Eui415@Qd{3jHM|&PI8u7g z8RC>OkMV~4;Eoz}aRni|&dl#m*`sy;#)Ab21k{~gcj2FGS$0Nnl%i(I+ixuiZ#Jiv z16V2!R^|RZ%qE2EJJnNlpw#PCO<%_R;;TF`g6^SQI0(F6iUwpki&*n2(sV>QtEILdZ@jJq{oOMEr$9MOto|)K?c>w}3 z0dK zMr65Ey;0y$hL`RnOsf9zSD5VL_bllXp2U1n8pG%+TMRijuEUO&(H^_Mq+};E>>$b@ z>EmBAzh#B0FD94-|Hc3QqQ7KKEg9bmlw7hRl}q(oPFIH_Mt%8%t^-FvQ`@8JW+{Xx z!u&FdZJ5KxGA~{|=Sjj(77|f@kq>vdm=KF`>eK}dx#V!qQlRznq6S#EvjY6TFtn=s zDoGAV1HF^%{oUl~28)3WUh*QeOY$%BOW-S579WOWjSoY9J~gtF}})SyM7ZS zw>N9x#)`{D;d^Wt+-U9w0D8;E8Yiw|SZh_1EMFIpE4xW}Qr657zI*>t0mOWIX+iW* z!H=tOoTdPj!rftFYi=L&8fSrgbp*nR`LDPDGG>~w`G&e|uep8Wl%)f8MMq=zg$>h8 ze+|8;{$!gq71L#&)!PnFN?IU9veo9>O_u?dmeES9)W4_x_XD{uxesOc4D9BwVZ!_1 zei>ehCSf|3@her#wBo3+fyX!_5v|pY2Iy=IEP@dYc*QIm7O?8<6<+!il7cBZCK28} z9Z*Tl*63*{s{XNMDr(Hm=9XEM0?4Vt4}^Att>`wODk`jSGnXkp{XuHN78l(bY0nHif)RwjgI zx8FaMoM)4oV-leEJ)13?U_dlqP0;HL^|&CiI?_JA=88bc?x*f+snwDc`-L+dBF6(b ztzN<@904CNGTz{X8K0UN z%4jdrw}1&HX&a`m9;_R;vbjAffp`{vT34rL1DunN7PPd70~RB+ir%ImcG~v)GvyJ+ zr5EA##kT07Hzi^XLsUMuxIVY3pL^``;55D+@;Wbhsnfidi@EaVL)Mjblin;LXaF?! zPMt0I-dUc5Crv3G|9CtkrOht&MyEjooAJ$v^_qqmAp~xmeP-3luArfbLnsZz?pLh4 zpnUD!fp_|}LP%l)+p1|dUrcB)bt;l~3c0CyFF zqsV={6xNDMxbLj697~XsOe}Qd^tV}=&oQXGjKQ+X6af;qtD=}@jO(zQXD|g+|KiJE zgNC;;5izmsKt9=YK!3`%Sa&@0zOvwq9NyV+%U*#>btr1kQ1<4edu_(p`zFR_6)`{) z5~=o0TK@SG7POQyhkj_BX0}CaA6v@GQcQ&9ZXm6LEwS_G%GD{4s5m*hb0_FK)V#t zJkC0qNFBuzKy}1#$N#O^rJ#8342?1f%6G|^T8V1_NKRxKR_-Rr&R{=&zz0XZ4og_i zgbc#weX&eTDLZw})z%`JJr|Y9h1uJBk#Kfzfa_JvNcAi~&@wh8lHo&$knXH|Hynq~ zx1ed25t3mM1nic}y$lD+hqJg+ua^t-NfaZ7w)q5I>XqMp#Dfs0s9-@tlwmo3vi*UQ z8&8rSEJeo|(_U88T9!SumeWZA&cTia(|Atl9X4Rh*pC4LzObg1*9bNaRKeYYMXid? zyC}=pNa>k5#=Wx+da#00kTiuMb_`yJAL#Mz5;;DP7-P~W!+?ZrIbntq$qgC}2W}Vc%|GQnQc>dSWd2`p-YBtmqspLcqdzR zjrhtu8PXzhk?0w12P#eqwV?i){w9N~yX40w+!{xw!p77of8p(IBhgbYF+RG+-jr&) zt)k zAe+<;izYyMpY%}#h7n9~xsjT|@L|UN$(vemHH~RGTVH-+{*&-v{QWx#T116Fgu7sA z8(9xr2aUk6GVx;OhKQk1#}#>whaWHk_Z!FPY9~6T;&b(4rYk2V&{ozp$ddHVENP(x z8wqX_8YiY*ms~;s+c`*cc&WwT^>T&60CE3hr^3Iy@3*~lI>KHX@1L;NM>LVy{LhIW}OF02!_Y71=(*|5t6dtlGH^ig>pl~dF5r0`q0CFXKI9xxJqka=O%6tA-ABh$u+S=~s6RSqL2Shjqx0DFUCo+ut@B(PtnSX0;T@5Mrh;OcL!+Pjjn-OC*@4cJOR z8vq1ku=Jwk<6jIunHV1~8r?Vo(llZ+6ke~HV&2kweomg{9c#W{!9C(y?Mom-`7#R_ zRhSsyEiG6exA`{;2piz=9+Lbio&renYo#1DH+0~hi0|%`q_*`rHSqMV557h*4}aWS z;gs4j5}Bow7dhf?9*BjH*mxPqp^%ll#pqm|JGoxsSF_34Q%{)_+)PG#*$^}zWhI$4 z>U)IV3f^{=0&hOwz6NF1Gyc};`=!5%Mo!Cpn0LMzv3a32&J5IsXz%4U^M!#6m3P(| zjpF*;!`TO-OEC-Pa^F*@UVMh8x9IGtSJK%%2WAUcb5G8&^@b3bee*DiLC`M)Xwq0i(|XCV zDLHUa8PiM>ld8Rp0bH>jqKaK0v>2uKazpAhrZiL>N;QcBxXs)>`Hjwec&!E-J z+cVC7x?zq^EWn=an5D4}{rIJ^fK%;RPSRW&+lqBB_-XS@(m@%NRQ%-vv~?jAbNV@X zCzCFLmSdojUURAg49vK8sd~!=(ST@bTnMv@)$k=~jUBGP1x?S*qZ^y}8P~0nDu29j z>aah*6r$J$slBX;Vbyq+j~`@atK{_@5HSLs{tzP@3J38Po_sFLlHt>;;XbjNX|F3e zJv(z(D?)%&9}ipBL1(kZFLqzI#=z?@VZ&V9BWCf{pAGZ1fOg`N@(HI?VGH-uh$V z%!VX$_X_|K@_M9EH%8CHxBDDGcxb7->2z;*Z?9cc633`a(4m7Xl`EAjEWs(nVJY-I zP|fu`P*qpglEGm)Hc@%_NO3+Dod**osXiCJ@d=D8(~^{6G}Qm2MT{80cMx##^X26L zPLFl)tzG?C1E3u&8eFc&{3j;H?s6{$y4EL+f*Ul2??5-tCmrMVDomN86-_~6Lkuvu z6Rwsd^g|7uwN$dL9djKdP>C`_ez+2RDy)3-pD#Sa=NDVs&oAgT4Ydm&q#d?BpjjGz zru1+V+7>BTj&nlzr@smd-54@Z;&5z1f$Lv z+=}|nGPTv4dO7%y9FOU4&Bt?(!zxmc0Cnz^_aB z89P&q;%C`6QTQ9PTGvk6Z)0MHJf)p(_w=HtX-jZQhDY1^W*v7yz!WWywUrM4-na< z_mFglnH-y$EZdLCS9SS;Vbi*@U&`glgUHNk*iUL@5JG$4tN%v(J9^h(k>QG)(NIJrshuWAXv?5AO3F4x zzR#U33a2Oc`?2sMc1?RC&P!&d$EZeZ8CisQO#t$dmt?Wo^ySZ&XSMKaSJ;}ODgcJr z(-@y6qVX9GGIdI#&y7rj)|9Rlux6dP));kiDAelkSIf8ZgG1propG>%=6ULIX!}l0 z;%9T4C3;KOw;8IaI zl0^svEWq-JT>JNz{P>@mbW>4Yu0<`=l(E%W^8>B&btn}86xZn2&voc~%_mhJ0p<*` zX+|rh6iIQ7Dc#aP2FJBuT1H2JEom}*VVED{KYST*Q5n=3F7BDNxQ3;NLXyJdq?OMI zm(!V5%ut0hE2ko~fuOlbgkAaKx64S)Wapu!nM0pD)3B^vjtQO9#m9MT%>@3Z9e>#$ z`N!|;_}6mt1mqW)Ql2hk!*Mf+Tl|B{*5dsc0w!idb<5E9mDVaxvqd~ zwt!E4=1+2REWaoF*wLSA>JLSc@c2}#U{F-RUUY@QZEtv|kw&mQ%izUZO%H?zz`BWQ7cjrnTg|oZ4pVcY<8Veh<9{4FLLmGit1;KK3f_=_ zQ?J%x(C55wcybM<3#JRA`-6ZR1VA%Klgr)559(a*X^pz$$FPBh0>1f&*(G4to_JC3 zPpD)54Hy);d=B@fGz>|+hP--{&lV)=CJO>v6dd7qrRrg}?13pZFJBbjlrFqB!2AmC z`(W}{Jnm?Z9lahek2!x1aYW28B!*;^UjK!v=Da}59t?oyvBsFcuju;uqYqOSK||a< zkd{>N#t2$%kC*3!O%@^OHF2~bN}P_Q$i*I|eM}(DOO3|6twmYt!il zmTL84W0Z4!8uS0@lR@QzA@s8bMVFY>)@fDd2d+!Io(QQd77}M-bF!n~<{t7EX}oLR ztBt#NG@0?HxFNXtOXDwcKIjG%PRlN{Y!-BA4q6>ob0Sm! z`)x4*+8qcmDEWYZ)90Cob^j|y3&rO|dkUZ&jNjv9%5reTo7_>Y!US{PPbdtJMdF5- zCH)6EOo(`U&^$;^BAKd^Xupsj4b2Jq4fv2@%C&;{G$O8&#{qoEwbegJb@Id`ai1qR z1AHL$!44V)yVe((Co!zj)I{{aALma8^!7r~vRmM(;Qv8Sm!ZcaHGkwBxy;>8;yZzs zMTj*^F37y&sODTiBm)Vzb;!@* zPmlu_GiTkrwYIl-Yd>Q?)oP5${<sa(1nS~CI)NU+&3)wS~R$aMgL(yi)Jr=gx(wWL}GMiiUodU zh5l~1ENqkeSD(lBk|B{SOJeq=JJe(T8T3f$Vk?J$Z{X(G`OL@F&sU zi{`;R0W})c519%~+{0x`SwLZUm0%`9<{LBjc~Zz?Rb#dKe?QPRF=*v$`TJC;VNQDU zrsjHv-23bFdx*aEA|D6t{(s80!d8KHcq4ee{X5iV-DkrIa2NdaCGrmK!GNyd3u`Y% z(5@h6MaMf#Ad_cVPUkRFJW!{gSidfq$VtzEy}{n2O6IdciQAGo008XlkKa4`FJ8Gi zp`;U>8o3q^)9;UQ0nz&AfDys_pMhMn5kc%;a8YFO-mEiX<~3qp>T^74MNJ^uppyo*|=jp`~vex}UCW|Do~EEZpPyOZ%LL)A~E_yxi6TidQ)?9s)#tYk z{E8~VG-aUmEsN{{z9fzIXK%w}at`1efnG3Vi>b_Dx%eMNz%fcZ9!>}M%mj3ZRk)xa4 z5uOg3{qU!^KYBVe&K0_}F?Jt$hsJM)2*;E0veBMPYK0@*nz5fNLVAOx5y6;dP%{bVSTD+BO~U!$>hQ-3{iZ++JI z=i0v_$6Dh)Juh~>ENg0-8)QdnS{QO|kjDa`9{ao0FOm*Px$&veWq#NFxs_0Oe503w zgM5CE_DTwdf%XpH^LWU>gP`B0DU1k=Qa{+(@hFNoAQb6}&NPYA+1QvkSN2?p>EH*5sUr5WHA>947GR3z!F(aysW zPxwabf;_D`UXyP`dH({@AN9lY#&Q4GG653x2~jR=Ob%HmUiNtGmN$$lX=XZ9yjV4& zU4pY=LGlpUcyi;UPK+nyJ*H_+X*UfCRs^7M_xmQ!ph&J3|=MVaKd57LP zsQHAY-650i!St{XulLSWGpCr9ci>}=;>_>MC`n{NpTM4cvo{xlc4e=}!5jzgRk~mt zvi=z0Sj&M1P%0cS{r<>APv}|2|I@rX%R@0!X9@v>N^U>vPx4qWVDRh2N8cBBCJvZ| zASmdwBY(kPTPBY&fXVB-?hw)asMEUYh^6u^-D!V2g1s1n`y+VYGQ!BqGABCW_2>f} zEwmK;q9`*Y+*v4wzXBI!v2&=qRFI_Vjdmq7dyD>&3LG2w)`0>~Y39v4IH^~Sf%p;V zF|@;KA>02YnjqqPTZ~lUn6c*>5iNMf(DTrlEx*o(BUL?3p=|sqz_%Ws`C!%pip@sPf!|f9#CT6PTa$Z^D9kv}m2b`(@7Qz1#kcAjrd*U{F zm2`E~y^gG`$+k9=Y!4aqM@Nz2+3w;Js9TN=gqyyLa>kCi80q=+s1#nXN_+l@k45*d zz@)kHGQ2-Gelm3>-k-2V(Mz-rk=ZUflKy&26PJienv09ul$q|Ys`eS6!V~^Y<+=^A zKerzSKC8OIgZ7<#@LLf9G5U)EhTp|!-GWE0<*4Z0Y&BpWin}%VZMZhO#wZeb#6us(~sM}b3CmB)N zs&RxswfALsczN52L+5zrhGM%2h3l`6HOAGj^ zJ8oS$ld)!WkvAQ3a)1RP`98QT{)ER}M@G1^dQH7Dv}YEbqTiJP_Ptbk=%02&x2=D4 zOcC%yLlDqgz+KyUFwyMu<9PT3W*N47so<#*qB`z+))Ytg#QGi2qS0|G_^6BSF(|~m zpT|)z_UR&Cv?GbM(LU$t$RejQV6@xhkuUzTZ)wtL(=Lne%GukDdUy1QgeIDLXeWX< z+Yz*(Wj+BtE2e<0kfeYX@9vxq1~|7!1y-D9ZzIU%w0LJJM#vdhI{#|`_N7ffNuSv! zOp<+h`p9*1F2nwl+{$KnJ>l%fcjWAsqdS|d9Z=T>h`}dUD*ffJ;B1#qbGAB{yvmp~ zdz#uMgqZ1VTvDy%E*7Ro5+l|ag2I(%3tMx7DA&bLJAWY+b9S%h{;ziftW&_O@Ly_g zOUC#J_gI2ra6fbEGi((67x(Pte=wGYw(~c@iISU3fonc|6V?zYnl~%&h77UHrb6K} z5-pcRrl-ummdzQs&vV;l(7P>5vHZ?-P2n!}Xp1N^xH5j5Qf8J}#HG?FjyO(Uq5U>+ ziaHGI6G9NSLQK!CU>mRS07l76_ICRAQ{ourGi3el?XM4Ar+1Gzd#^+uZvG#7AG+7d zNl*OqbDw$c!*5+CE|>9?*?a&>rYhzZUnDy_7i8%uXHmYdDc0YmN}EgNm>G-|dyl*A zkji2B1G)1`7Izluvp7B=mwu2wtUjDSQMD^Lt1WAiqt`*^Pi+z}T_~WO9r>4UXc&g* zG4a^F-0UA7_AK_=pk|8WyP^_>4dfA@gYxir??X3Q^eF}5$DlP}X#;3K@At{?jag+j z(bu(>$yJ2uk^Hcra2Src!&D0Z(Blww0(0Dn=jm|N~^uK75Q67Ry=KfnK9JX ziPbMtJxm&|{r1%h-Wlc`b~o=+?{rVx>)eg3;&q*OQ~sUF-@~7^#0qgSd^-ENFZ@^N zg-PVi?CqVSc^?jqmhJDcFr-DN`B~oj%>%>jv9R)-hUZ+N91CBsr{XRc(~A@DugWbpTo(Wu#JKCglYO6$865oTJMdhQRAu ztcZJkg~ssvgd_A&^egXth%7l+c5j4FZ8y!Drc4;EZ7;HIZK7!9@Q#>lmQN!H5na1A&R58LxiDY_>?4SW(HE)k=1E{qfXaiF&?>`;6Qu^WF zwmRaxBu7C}dN5AN!xo@#M9y$Oeh0*jrKgE`iwa13{nbv&8`(+YB0Jb6#FXp~!b#ED zTEYBJ%QJKHH_v!wY92Y;rmA?9`_8Y6wLF)uB}!$~JK3S4Phw-SEKQfEsL0 z>NrBkq0zKEH0YLL9LuXG$5W3a!fJ)Fhe^eDHLHu+fX~CGGc-xJ(7;Vj_m)8BOZ+VL zFHOvT{N;?`SfXctOk$o+>oo&GonZvDx<9+;mAD6Opx_5D$nL&fhn$@M@MW?l7CLU_ z(#D;vlzDXpEH%3Ft?*qXoEkX;22PomgfwG(5Dt|M)`D~$uJe1$OC%j2HX78drEmdO znpd%`2#symJ70Jpd!FaxL5iBkuH>ai01M6j{xo_3$(Ha7?yyMW*;^=I5t270FnG7j zeeKS(2!ELs{O(4#e8M$(-&R2RLD??9Tg~>3F4xxQd)d86TgGehODjm$TKYHAaL#kj z5wO^{`eTa<_i-rdClts7D_9*Q(#m*7FAo-eSC}iOg!h9EP`=(utyr%bl~ z(7q}D>ShI2B@QLZW<8xbe+XXqWa|Sy2UCsfU7+X3=aW7jBG?Eet@)m!UxI!GjV)JL zmj9btGs2*x*)KnK4<9SrvA6?)*|-#)=qfvX1Sc~?tJGUneF}Pbz=IJ=FasI8Mx^{_ z;*3@*4$$u_g^3_C3*bvMxsGhRyk$T768HXNGb@meSZ4fzXt3;W-z65zDNn#H z^9i=y{g)<81n=|iV$!W`H=;)Te+@gQDg^0`Lk^MkU4NheIzY%&pX?AK`w4c%?+@)X za92D<(udNzGWl)A|2(aT9R{?uZm2u&?RR`=)3^GaQvi7Si~@E0T<3Sm9~wre5ZR(M z;a7`OaSil?ZYP;wb&W^6Q_ZWTX1IPz%O;xt0T+|KhmSJhffszsmlkoKX9`ut6TL3tw|w`mQ~3W;n?azY$(3PW9>|EEGjHx7cCTCEmP_O$K@#yh!il@mPbWGf z$#eS~A@(oSIg%myJ>tZp8@EC%)hsPrspdQYp;ShgTXoe|U@ET)tgn$=qA8RMur>06p{ltRESJS++ z^SAbPx<1m~iTRm2%szB)QwsjSeVfuWm~Q{ljtV|(s+vUA<>BX#el&$!~ge zrJT+S$u1-$;P?4A$AIS+Y&rvjF}1^GQWe>&g9WbpM&du_XX6FBb?*(hDP1H2dW7IOi|8pwFA%(XaqAiVAKW=Vw#DZP3fflmB=I8BYYIyZXA0g zMX!f5J`>*?Z00!CWN%yI6Dl6|+q--aG&}{Qdf99f5ynxT5NQ;oMNtFe7e&Qvv6*g-Bj+C8h zFb$^RpxdT3`-6L>3v#wv55xx;EFC1gsp;;nwW z)9Fs5yYkZoJ=SaYUwwF|8oK6FMs7c-s})WiWlR4k17RZUWs8C1-XD|%h)GvuhGkPv zCy)XMGM)(N*eWbw;kUOj3XdikG=&@NF?bccz4T{AHX7fB&ZY! zg@*WcuckP4JM)ER+iViOl|a~N;Ssn$jsD9_qw<^!3keU{?&CRRrx9fvHm@I9e%DtT zn%vYPH2MKJJtbPVrVW!zh-H>#mv4Oo!02=TjaF`auu<7ONZSFtdNvK{=I z1vXk{BN8z&6nll7MmZyhANjw7$d2N2VpP9Sc8T!;g@91XtrcJcyh)l@IkIb#4qnPm z?zf`HRY)wvu?WbD5YELtV{m)mlc-DrU?RP~EPXK$Skv%-0Pg)a93b|h*StTTMo*wc zu}2Q+$&;j{Cev5bFQ}h8(@1O%0x*bzJnp?#p1)+U+A!3I6iE)a=|ut2$rJDz^4Z=*O?CbaV$ zU=_-2f8h?35+hbQk)i(Q*Z+A;I|I@K%m74vM)!e*sZ(bv2~9m9H_(}=nOL1pS{3RD zZM9BEW5{`8bUucVft?l4w-2*UuDhpShL#mbA2ZXkSn1{$BPDd;D-6cCL4(Yue?F+5 z!Asnl$kEnyr1!Yss1OU3&A);?5`{9U|1hr-rp;Nw>yxzYiv?hRJ}vsCI2lGj6VlLu zT4i^-&<+bb2#lT0Q@td=r|E|Jb{_phg45i8;m>=$7(w)-la)37Vi$KCIY*4R>)-(t z3B*k=)a9d29Q{3#x?gB8guQ3wugkk%jHDf;AloDzh5 zr-Y>*#W8Ltp{K_aAkjlzT5G?yB+$4e=7+72Rxv|nWC`ATxLtr>|EcFr&Qpx?AO36p zjW^bJw0N?h1yl#wQ)dc^myct0iXIS|xQ>iP%TT_5itzf+VJP?R6}`AzFxhN!i5Y4% zDHPh#eH2JYQrg>qHwfma8y{c)$K4-$MIXYJZIN)Q{M3K@sW+ucDm+HG*nYm+uF=*s z>QbI|)BlQk`P?ZtcwU#Q$e0B8XVtsrx)*j0E`I7DXNo#?q?UW+K&CT@v@5!Dc}N^9sTJy1xKpzsp!@xbMEKC2%w70KE=(}^m0 z^h|CCof92@>-y;jpcwuHk8)Sa==C63TSk$S+5hjO(o5jL&B*H?< zl}f>F{r_AdnM69$AQJDZyiI8~Id(HPam2^+fQQt|%$13;&{v!fCY{k?jV++eiXEgs8Ga#VrwU*9_#WlJvMgaEBC`K=EL#dsnXp4y zb|4;lf!dAx(U37c8`n}A6G0%%E~ywd;OD zDTR5#ux0Ft8Bqog1X|0bu)e)fkk4wjU(I-#dGA)tkIhG%uMiCb)t@txsTw5X4h+sy zo!%(5f=*W`MO;ZZd%b-b22nfVcGsD;Pmq0sKkk?2@OCXcbf?TpyGh>As{*?lNO)Ks z&v1U|vb9&9Fclr*4t^y2x<&HZrGFvZ{cRS*@*gmOa++MXV6$sHJ(cS$74>tB$tM^D z4Ac2qFGe6tonL?&c6wNK7QAa>aV}fSsG|U2xh66Tq#X6w%ZhGP>P@AqS%8&@2u{Nl5hpz}FBrNT$^E7< zMP0{~RVK6yjD%aAV8b9tl|Cl@+2=YSR}0n|4UtEf3`sg)hykk&MlQ)5!$My1|9J#E zdz}aSRuD#gHr=p;Sh}x0U0Mh~3@8k-_Fad{&Gfx)<@UTyy^G@T6WMWz0+bZ~h{35a zQf~h3AkPy3KvYL2K25HIr>gdE9!H+BhQbq!*y~bR{dhgioO|o_pHd#lU_idowI7yU z0gTE?-_F#+gkXb$N#Z-bdRhQj$u7DC6CghsO9DQ-)4K|0aNX*3KaVvC{frO=Ks6QN z*;K{$gTt)F~W6~DmpEXhH^Al=+?HwK%4;JZPCk#CIIShHyUg8>TzSM z<5>sJ{0lgIwP$Vh*1JCeq&t?z5X4+<>Y+tThxa~a67)j}$hg2rMijS=$`iw!XC72( z`3qGpnV;Y{2>>wFvuY2Qo8^f(k6QliVhMJ=Q`51YM_8#(vV~2eb z*=q2zD}c$CyLfKV5?j#7(JQm9^kkBZBq_4Ydn4{Qz2C4?lWZkguOz17q?<09j{h)j z(?&Hj{S3mBd|U!a)~ajDskQUv4}RB~-f0I!fo^CvCY);Mz>q}=1K4ds_iSY6YXU#< zBXAVl>aYZg@>xechrz3d_0^?49~I(cTbWiTae#PLU8mH03DT|gxoGFzjvuv;?D}HC zDw2OJs&dyWRVgKvq&=PNqk;+YeCU7uR>#@yxE;qePx~v;*Qjx^=oo%k;2&N`%MV9@ zwFw8Iymp;(CBHg(2+W$i(xeO!8LKuN!ee=tYW18TAA59c|~6o4+olwV!Wg0KjwOC2^K+EYD%na|=y;KW9SJ zdFb4L!8$+dS&H;>{O?-*4{BGt)9xqa8eR}x<^TpgetpKERn;6tOvu-dlKH4ksyVVM z`Vni}k^-(<3Bu7OXz}=6H1LYsC43Ipvg1;u(gsrhpeRGyG*}R2?RF|}mK@evqA9CN z&t+;q=nw(Or@3;}bE)nhwp|%}bHVLsPhN$sek_l{59UFVoi=@(rh#%}zG&c!e^~uE ze6YJE;d-(w3H4`lxni9Di{u@1U?rZ)zmx!0YvO2~ruHvh?#_|ov%*;<0hYMqx^grw zi8JZ2ISFow8mW|ivRZ?zu@rd|VU_bQJG)}$S4MdN=J6sspx-I)K?-$eP-`@RC@0TP zrHiun7GKue{svPO4tv>0P~anY2t1xbN7k4@vjBSl--$KzS2LLS90u_s;cz1 z43#7~t(6nYJqvHX*vc+M$PEFOQn2T0Y_JdfDl`>FIY<#cvRj$^r_zoib(-7N8gNDB zF}I;gdKd;k1sk1w0c{fJd5ldyT9?5lG_}6q;eI^7O~8z^oILztaP@q)l?M`n$g zroFXvU%7uEQ9-+&{0Od_oHO{#<6Hcip`VYyoqt_tPKP;&lZPARnSYdjRk*8oqN37L zXX_FrHD>Ti6d2#i!?dIMno3QgBErt;KDDL6pp3TxKttrD{l6dVDxbXsUPsRwpnTHN zd5x!N7lVNCNhs4ymr^`{O@?TU{WrLgRVI;@%FTo{@pR+$zLeR%l#KMgj11V$J6GJf zawR9fI6rnW|3&fes~19Eco9j1Gle*tt&HL{abA`FSME`6@iR7%OM#T+hpW3Obsz;1 z4e?-#-h|jjmidax^;S%nJf#&zA{afQMTaQ8?T8xG2m6|nyZjoX?|?!QE5+$)>-W@5 z6OCfZ-tduMhKFp@Pmz^kG!pXRF2%9hp^u^C?=3lGQ@^ z)Ot^`3ajwgfrFL5O`$>+ks?x~*mxUqLHraPN#v~!OZz$hNl{s>J$y;#oY}309VHw5 z6IiJ4T#L-D{@%oXL?uGkN+9M_6-f3AJLz*reoUC#Re2mH3L=^Ww?0rdBEpL;xiu}X zG;0^pq5llPF)&&@k>Bpn7mPtd^>X4T@8a3krI*k3#`)1xQNEfI_=M)mz?^ zVuQZwiZ@b>3=~AfR8Nc^eTW+<@LO&QsonJk@i})JPEzVc&@u ziRYd^{))2Aj3Q%xN9mZ+UauW>q#z8xXzb6erzqotrJ8-qg5ej%Zg{z0d0G|EEr1@t%MH z0pZ)+yJAcy$C>tGt>|o<7$6((+u4SnJUd>iHK8K-^mQ)e^?%tJceC)xYi7!4DD!+S zBY%p;=Hs%zZF(9?{5;z^O>(lk9>Dtqg{Mc@d-v{$YAJM$Gx}c~tHDG+BNk{zllg)N%zG72ARO>A&5Tzm*{TEE0(`P;WJ|YGaJw?m$Xa})|j?3vM?ZPQ4qZdc*JQ6=+;38K8 ze|k-d4>l52d&?QVe$%rbv9^;lq7n-0^QSjS2tC|9n;-3|zK#C7!ujm~o`5-!yEmLu zRikF7O8E<`xG_2{U=*?j9tO7O4hUS~A?iRq{*iQc#_^#pZc)k9aa+|w($3Vww)4es zl=@?mwth;#OQ&|B07puWw)D^Ou!`V^Mxp2^x->eNT>M5xjU7^#J*ZgxQYte_1JqXY z)hn#_Ia}QDEwMRE|0xM28_v2u(jEFz<8A$?ISzq_gw(C0#?a6azJ{dXwG-fFZ<6^D2 zC#6!xm4JLkNDA_Hsh+eM`k5`{ll@q!S0YB2JGQ02-S*DB+mBC!`}UvfOk~c$qCs!2 z`TjSt3Qn#|kxnZX%msYu@#BLwe7_2A)k4*vZ((B1f8{1)`_Dn?a3mDQ7Yu5Z9ekD9 zeZV4>2rIRWzUsLVG5+WRy<6gZ;-hGTa2AndPs>Mlw=REy`W6#0m3os{rI*$6QA%8q zP=rC90V%go}s(y!)g4MRTO1457Y*YYRl3aVXVti}OwS zNt>lE%@h66*%yzVixBf9!C6oG?Fl{{^JCfe@;IO{+v=Pyyxt>I#i?TopkiE(M!|wV zO>kJ%JZNTOaz+&X!L0+hBY)ou6!PD%&K#XEe|z8d=?#&`TZz7m2a;=haWbCEWO1^U z!%EKU;5O}mj3pAM210Hur^!eU^00eEfG80}Li9807ku7n2RrT4f!!0Gfb2e?vZRD9 z5wpYq@P`Rr;1BTms6I32HUniPI5S->G%=KvV{{tKvW4Ra+8WX!D5DP8A6RU*KtRQ* z$>w?QhL#E52FIh>3d;J$OEaU#BZPpU#4E!V?6hQ2rf;f)Igd9{aDlno$uo}V>2-u# zaZv1~=R;rqihBR(e%^l2EN8VZD@TE%Ycxs_@f{BfV^uR1u&w$zcPkyStzu? zYH^Xf!8#_N_ln|B?WeMuZ*IfP?ak&oI~D13%}hbh&rLI2PDsOV(n{0LjCQK*s}JS| zb1aH=&o-9=O-Pf*KO$X4hC zYinQASJcLFwcJ|`LI+`kFen*pZ~f-pM-7tdw2{EFd3`&0;sU%IjCB9odXA{dhQ4fD zuYZAyM~Kuork#4%-+GA4i8P6{hwOrVnb6Sk9a8%IvLyK2j7tyzde}atO{lzsw}<*2 zJh&@Oi8Tw*rR$ywUC0d#S(DtUM2GnmmM*w%?KE)Bv+o5>ZJ26Ty;CgvcCAK9tKpxr z!icRKTQ>kNi^`KggC-yRDT};lwc(TQhoUiqM;KZ0A?D2>qmRu@4o8`!2w*z3NzuT7 z7s72Qc<%)KQHcIXSv&|9`vgDY}%!Y|vnpE0Ntn%?`kORL+B4`|BIF}?C^Zi|uYpIZQCeg)?Gp-bJ<}oT$C?(8 z<6deXOoqlo&cPEAk?Y6)PYU)PR}Le@RUrR4B^KFo8hHN|pxaTzde~RARbq7tk{;l3 zxj&ieH%G)Srf!Wl7C1?ws4RK>cQI3yVz=E4KdgXghWs*H>en<+D-(jkxNWADC*FR!r|jBnin4B$*Z3?hO}BfzMGT6`Ds^5wK@G2`gx@! zZAt3N^e1vnI}|=H?9ZnX(obv+%h!=&gR&Jh)Jy;7}ex5wZ$82+jO)g>VJdd=&EZU z`lBUKI?FCM1p)-p2%W50a2bAns-}0l(66*lo^ynS1}#`{8(=5c>n{Er-pCCd#{zm%ittov1_?h}9POd*8U>uzOJ~Xr!`k0@@(#Hyf8N zmHfoWI9j(`C6fZzllPjfC0*|fO3blE$6rg^SF%{~V|_JcEX;akfhyHO9x})w3p{iU zz;e~}>p4RFvrIaN6Jj#wrc>i#)5Xz0&59Q}y8T^7q;Drz582b~watd~d^MczO5AS` z{B4F9(R>Xx4hI&N`F2y%+8KW61IyvLM*+9~WZRX1#y1P;hqGmv$(KBrtF?^&^0)nQ zNd0jiaH9JUryyVZQq%L_I~uI5oBuUT zD|ZaL3&Ds?eghI1aN0$;6J!ltgtw2Mk(_T<;jx+wJG0xp^A4@_Zn+{N&lMC7$I>1= zHoO97HK$O=HO}6y&n>zyPb9?gmDQZ}7;y#zAF^&BDl(Oxhm}CX5`lNfA}A%l+hn2U zvMq`uO0cegfJP9|OhH_20vcfbnSI}sTX=>^BwITe#)D}Cn{%C6XhG!VG#}j~=&AE} z=!|;l^PR-6IZAq^tgDXd`k`ow|stj)-80I>n7_I13>i+Faj z(C2Gd;*T)c+Yj8LtVHHDIdqPh#dUp8&Vw0v51w75Af*V79{%h$*;t}R3wS|12TIlt zZ~_}h53)KnW2uWgux&M#`MZymnH6h6;@U*@HtddrCK;<{etbSR1A!d@XS!6WD{%Qa z?=)YWBX>vjGdj5LHaag6H=9m~z278q#W)G);-8rB>M*+Vq2Cp|(AKtLe=!3Ym`UdX z9lI(m8nYS*-+xT3B)7;(tQ7JqnLp`bKSUk;rJ;lq@mtSH9cX8ZV5A2a(u6;0ipAWY zplBvi(#IxJ*N8*>qHYFrQ165K91lj5=}MPp;a9Z_g=E4@%)B#9J8h}AYc`JtJmg=6 z-B5SFIsc8Ep!P~%htxXW!cjj}R>$rUXI}Lz;Pkc%|{!_z8&=ND+IZp}gY|$44drhn9T7LUjUO3{bgiQC7GQED;dW2;PnR z9ZQGU8Ris?pq_Nxm_Hmg-THj{{X-7wYTCDX0a#Q-Gh`I{HusA0 zW}Hg!{QVj46CIVy0j6MvN89qqVs_d1-K~FJYJ^o?+*Mma-}t;pgsT^jq+;>Nd2`4D zD>ML4Hx}n>wl0|`TMeeXqAIc6d~Y-OXHV}?5*iYQhm-CT0eGrLj!c_pHI%J%s{{jg zOgauTnvbvT)1N%&fEY>FWcW8<-LVg|q(;Ag2E+*SMzz5$!aqEl-rq+p)YAWOzHA|| zwc|~q3YZJr-$wApGu;9RDT2G@)>a`c^!bTZ3))^*tG_4S(Ht|u4P<2QwD7SJK*LY2 z7BsI{(1(S;gYOIWzL+Zm?Ho{u?e>6EJKl>c3oExvZd*@EmYRY#OUAldNPgQ{ z+gquHUPRHjD*D3kb!(J_>r6#hZ?ngBLRVI|eV8lN;c}YS67mi4vP&yDw>RcC)c9|0 zm=th89GmOqBC;$qLCrCj-b`@^$#ZwVh!m1|JgH2>Lg6?Hyo`<%xfk#wn{~rJHKf?< zls0G!l;>Zy^(D;JHn<1V!=XkxW+Qr*>S|smi~gZi8A0N$|GU;tTD81?fgIcX>=Mkl z7}EDkr4_+il=sxFALw19=NWYH)shj@GY;)m>TfE#1;V${sCCn%fF2jo$BB90-2WZ2 zI<#s9FL1x7aOK$6ik4u~RphS#?* zOob@j)6FD_M^duAwoBwA@B6pxFf@0se|J8p;#l;k2zh0u@MleLyN1#jXjIeb`LXCJ z919?RRgqV#nn@D#Gci}sDp@1fTi~8foZUIu*@U+|4@)Dl2c7TD{mdfeFl;RXGMe$k zgw7gjQHyE>6K%XX>AW}$fsy_s7lX;G@=b5PiImM=dbyVq*$T5M7nF1l-x=(j4=64; zR0o;+HL4G-x2p&{@97h+or@a!gLCfLbMEQ+Vk$4S`>&Q7?gm_LFA?TcGW17HSR^@Z z&#HO333e94GMoP#{cf*s8Nb?2W>D=rP)Mg+s80C)e!v{5vngi_Lh!X#v){p7u2jGz zvR~M*){qtPbyzv}9%lcL$8iD|!vJ{|YmSW!9^rV5sDw!0_nXCfIB`WcJ@(JvW`Jh! z6bC=I`i88+8=jNE^EV$BcTJvmSZXDnFlpXm%O~()ZN5F4kkXPHa&)`)dgs!`?{qo6 znD=p&y?w_^07cd&c;f;NdX)Yd`q;0;??pEj@Je(>$S29mj_xNN(FhrZuy;wANcM-F zgF=qhBzxE;{o&0ECyV%i7$K@xhFl&Oht}QCpCKLTddcw6&uT!+=L}AVV__CS2On(u z8@rj*z5Ewy%VC16^bS1M^`j3rBrxhY5SreM~d1ii!~K0BVZe zKmMM&KKk4N&6~nKZr=H%I;TI_d?8k>Z7DbY&gdz`+)xRkrTgX-WBZ1t%xzs$=aah_ zbu-}=(ueS{k4FUkZ~V6|E2m07_nnUdZ_^8Vx!5;<=jkjEHieq@EI@+tSu4vh$CKQo z$_MCc-Pa;3qxa4X0CGJMKe^JdtisfmwUa6>M>r0apYiAb-6Y=ueA@uhy@~+;@WfSv zOhr39CkuV+eV5a4fxWJ@(z*;QYM?I%-%V1>pVGTh!@KF@q`C0%koePf-xDJie$0EB zhMOBUl zHLHv`ty@$8)?46A7P+2RY0=V$0~O!hab^Y8PvhZnxx++f%eomG>eu%M{NeWzazFmlUmfmZa!?cA%y%srzG27Ne;6qkpf;=@;xow&w4rLF!eG-A z<+z8#x!1RFaWQGn!QQrJmlDZ-^O#2SU))|w!5?Nd3{`Bss#SoAy}*0-12KaO#Q0G8 z1C=PejA+iXe0092AzB)L#d2o#bz@6$Mef~wmc@ZOv2S(H{0^}@wn6>h_7&meFdM)H z`-C@iuJ$Fbzq*v!cB}HIw$J|Z0*_GPX)X@)gJ8Hf#U)%UvL-7#K6sJOdm4Nhmn=_8 z$D6A3X$6_{1$~mqP{L1Y5kJ&j{*l) z`wop9ND0X7WK{?}A8_|*_g$#>5I^R~;zt5)4@H8-m#i<3;SP4?)R_sFw09f&mpx=PB-(;h^wlWM~b=14-boz`|j#R^4J8v`R+NMp?lSuRWl z_K@e>R+9%~2QW(QfOgS(>47CWStFP*0j8SL?2B*};7If1wL1(HPvbr@fSc~{7hsGO z`TpF}_%`ZXjN)#hHIa6fx&MX9 zRN2Ku-3#SiFc3wpT8^L;>CbMo+wET7kFgATz_~^?c)X~c4^iX7tIw=w01miptj5)) zOV7Jn)cYJ4f|420x{sF(6DS=6@aS%CB+XqxP zH`1CM{>~Egf+c|1ITX;)=84n*k^xgHS!Cez0uk8|>AWI%hSg#Y_pP3D;g=WH&J`h{ z_`TvlJha^Jrd)6CwlLCrL)C)TcxZnz$dhu&y^INw4txH?R!=a{JZ=045Mg%Xn-55- z$PZb-b`}D|hAAjg4C81h-1@)$Z5b&1Wk_<5y^NB17a^(^cxrIxF^Dqsu68Wt`X~>& zh-5_sigYi!Z@$)9oK!-a?jqbwQ4%_2;)wN3!RF`J>ZJo&4ku%GYg_njm~Ne!yqE}U zoG={pyZr%#-;0uL20mCHQf<5&xUlY|F6guxBEu*v0|Gk6+o%DVRX&6&v*M6qC*#Y6 zyrVcSNe~XW(Ri)Rk%jldFv5$RB`tvG>)~~7)6bVx58sf|kV_DoQTM{lvys9_eVuqG zg?4Lzn9C)9EOOHF_T4hhs-SQUfZz5Q$5{)iAZ{+4Qe{A;5Fu__MWWp`pKV z@qxFt^CdtYoZze9p9%LTRn31C)d1Cn*6j4XO$iR~tzDS~{6H-FsKdN#;n`Q9nN-tv zPnQ56p29ZwgVcJqp{P2)iJwIQ;vA2uTpE$vq$4$&i6;@X-H;KmIIHd2hPk_{;XBe% zf8#}SopLJQSon7dzM%x>dhMN{KkF)`&k752i9u>?cb$|h{+gtTX`AK_a4m4^UaTo% zTr`J3vqtNcS|72x2}3yZdDWU#JLddo+n2NyQE@=UYBcYQyQzM_9A`R84IGDE7%-!C z>%u}f?sVGp?QGoM#}hw2;W`kN^+!F05Af`+duwLhUCk%muT>Cg;2tnpH`ju`v;t@L zT8CxN;AO?DyIZy=f< z?gS*Hk>B-2p^(wL`R#@S)CLnsN?KEHsH3-Y0c zpBdbrUltv+HVDs%jsPYqc#3sP*@*KX!R8MJ3EG>U+Z&8gZSyLMWRpE+!b4v@rlcz) zzWEIZ<{491^YYG_5FxZ6z<%Scp6Bc+CgutGh3Mh8Tqs`T!HcG`a=+oTo>jNeHifCY zo=4n68Vxf*w9NGc`l^b{@it@AvmUnYxootB{=Gj!1z5AqTq7f*Cz$^frEX1c2aA{44;T|yCNe_xlAl> zTU6k4Xv>oZPzqZ&$byMpE0hc?B98(59rOBqmWL=v$ zO~Fz-gHr{54gI!##*+U(wE7mi@Y>~0O-hx7IbAO-bO30kG^4qHV;s&VV~7EwH=?l_ z1L`p(#3Y}xEkrcEv>a~g#_&l>9B!3@OBjEX;%^^ZOO>@PV85xfXL)elj~Q#mw4!&x z+t!-}jhS}svY0~uGJQMoYNr&XQZKc+d;`l%nE91#4m0c@JjJJ-PS+7;+V9Z_^~S!! zd^a6Yqks&`zJ1f0@|#f1Qv<(UY`**^WuxqG6bf))<8jG8;QYH$aEo~};kI#fQ0mO; zT)xQWGYlfb!uOs=30Cp(#cC@=n$w9HndP6s=I310r3TFzL`N_9YR;NG50eS7sn`W` zUh3~xIT`u36EO<06MA7GA^t(>5F!KPM&VMTlMl~9ZTW7*l!tz2$2#lDnLt>F{Ij+* zZqE1Tloe~tCz@JZnjk(2#4kyksc+(F_?{Wsi2;A&NnFWz;?B2J>K|OR5o1IAk9Pt~ zcQSt9pVOZuBFab6F+M%GhH zuk34VYwUm5XSG51IF<)dSa{wKx-;Jpj0U!DdC`X_U^C&tXXBOQZG$kUnpcuCA!kVQ zCy_2ljP9F`gPJGP8wL!{dkyJwh$@)P$a{ULSq<%NP-vLl&&wCb#<5ow>mo( zng!7eTxwU&;t0z$Sfe|piim- zprB8qtUiC<5L_p7*apGO>45eMPHKdcnhxrhe=Vf`@?nNg3OtM*p-BX zrLwK0zLNLtH2SryTKzW{hi^A}hrcBtkUJ;=I%Lw(>AA(o)FRJYjNa0K_}G>e?jBQ` zUr=+9atrCo`XV(F_)0fLm`_ff*20+qUt5AEt>!$7hX<~h$7!MT=o7Svs_iX~)}I(N zMYyOY7j3B+!=M+NxZ9)|sv?XS6a!<_81Djpy{Yv7MRI-<(*9=CZY-!MkJ4CK&~2b5 zQ}!D&xX-_hgnb{L;Y(hj%07A&_&|2Q|D02g*tIn{$fsIt!A+4vC^WnvK}MfpJ%Oa{ ze5>Dm@9L6!GdmGf6uu;{caz1CSK>UE#UX#+`J&0={fK|5CAhnvoSBC+sldiY*=c7( z(<=UyPi>O#*@-kQs6n=w&tlu8eD~gM9CyTqk;J|Rpjsv*+|-?BA6)yY_N|-lF)S>$ z*!V%Gf${MKZw)oB*YQi*c(!z+Ppe*MAH39j5_D7P~ThMkG^0;T>dWKs+fG!uak{z6HM z*{Un~8K5`Be4P~KCRn`gu+ET$_%JLxO`4VW9dD8H6u3@lDck-I6XS%LPCu}`nX$B7 z3^V<8#V*Fa+=Fssmm?V0vD#Xd6jkC+s&&Zd*?0hj5_LynLnbYEbBhp%tw4!#=gVR& zJP7Z~FfWB1z;h_|jF5Jj^7v4!CP(CQz;Y_5CPP83(55OL?54aPAAH&dyTu8SM7mk|$%ObIgN_ zkfBrmsp8r%luCHqGVhlkhncE`4?_0mc`{8p#-g<+7@}coq+a3h9vI2b(DJe5TQMb) z5@zHx_ilytMwrz+)g|T8IkM-d90;Q5tF)bJ<{}{wF)toKc1H-W+}D$-MD5Z>K^hhi zd-1+aU!3Kz*zLR`;w^*(Y!|gWL_IvQ-wPwLG5l)IyO}=;+zeLw*BfXoku#R4SDFMd zX+9%awPMjj0JHhLsOdG-%dewY%9u69`P(mh~n~vjYmyg$q%NT8O$fc*!rjev`Ts5e` zdO4!2h!oR5T=IAe#JkSU`-=`Gk4%ir{yhmvn1Qn-Ed_Kiij-bralR4uF=Gxa6B>Xt zB>)i?)5niV->4{^V7TBXC+j8MeFJkE<;{{bXs@^J_8n7~v)H#6^O+e|_z>lKrGC29 z;+>l6;x47a#s4xx0K9@Eq6mC_f@y&T>#%4rg}nQ%T*?agE* z8=tcyo*+|?)Aey>3zt)>zLxmR3%R$~hcBntD1By=5`^fJaGX8m$xbg3_u<7gBW^BA|%T_@UNfer`4DhG6L+ShSM- zm#Xh~yt|X1Gb49>E=x1a^+p>4Z-Yz(Riv(ShfRJN6j`1*KO>1WhCn9X8(^+K?2BCc z4U^8>ANdG4HPuzlS5$SHi2}`ATA$ni&-eKNPeO0VC(_Kq0aMNb5jLdZ)QINGN+}Pj za2s~e3Ic3RHsyYP8!p5+b*B8d5%od;zTIY4vG$$#10pyLK5S@{X&dF`=Pl0!Pbk#% zQhp*?;~h=FG}UP*_}vFui_~%St-r`PH`3oA?BcbRZBU|}dWsSL>il;StZWpCUxopW~kqa`H zQGA8;75*!nG^$8?0rJ+uK0xv-+PX@3l9vX4&eAly^;&fxZh!0t8zAVKAzP~(8`z@> zD90^!67dmxpET3vTY+}}5Q5r^TGBK+GjBIVXQn&7Pyyl>7|vm?%=+8O#c)i)@R4MHxL$W7Y-SfC z;M^zGPvT^~QO6NtD#`D&VuJ@wuZZ|9?p#kcU(LwE^Gff`sT$4py%Ng8v2)+1uzak7 zd1xk2;s6wdON>2UElc8%UI)W^ZW#J3B3ujeBQ8hWMTpy`+mcIKo&*!91R*u?L8;!f zml>WZ|EhynH%g5|bjx+wCjG{90O{Rl6lY2jKxQ<3Jdw!1nAt`ZkyHwkZ{sGzCSkF~ zbiX~y7S0+IW^k9KoLEef8@VpqTDW$Z)4{I^U~8-(=l83AK8d;kh1xK;kAhJGB-M41 zb{ybFQNs}*kBS}rUl*@fK=iXPL&N|D4GFWHYQ0i+>5si?0iCVu_%;;1-ECd&$|D)H zX~N_BFA?y)C^TGlhW|OE6mDs6aPKBszRD7D^)vqEPwRBW1-5q0=A`)Jm%kEcluFl# z#eVZ0p9n78;VY$ld8P&pKNNsy}vCaV}1UbZ+M-lQb>$1e8uatsX1-c z+h#|O%AnCvd}WTrQ5D&_rlx$SoguI$=B+(a8tRwm1%E8EPmsq z;99lf8o!zOylHZp|Awv7N>6xS1c+1;@+m=nm6B3SZ|8C>;QM28A8ZDEYqWUQa}=Y1 z=w6)~hlK@{-6;4QSWW7_3tYhRr7OR_m|}w3j{^6SNXOh97wuDCU5NeboSYoiQo8S} z`6(7dvy6qmYi>esL@rQqTb{Rlq>x1vU3XwrbSC)84tRHRIEkQurdDBZ56K$oI!rXG z#+NzlkKsAC{$noSH{-Z13jh0qMWO`zpE8E_6u_&ApMX3BRQ_BifJh&${7kb|mzN5u zk{uc}@*}@tkrNiWu3K#@FzzdhKreXfvW#D`OQPI~Un}$-VsERQD~mxz8K% z$z>_=MCQpCB;@DG6VX=`Qz?*t5<#fvP;e_~$gNl-kG0q&%EN*`aZf;=FTubsw@ zM_c%IeXaY5L~ML_-&B(4Geu$>oqIP&+)lwa2d4%{o%XEu|y(ZCs% zt15!_iXZ8@gS1k|CH86!U)?vU{!^DR>o;lOujute@xe61F40BSX|G&0Mxc9^zP=O` z*~~Mnc19w%xK@gZ73vz)4vP7Tnpuen#Fbw=lhlO2p4}B9EDvx@Y9hL_knU~d&q4h% z@54<$^8-&}^A!zT@x{&W*22dSpC=@+g)CRB$GrunmmX5pTsf*E2$jopu@X5>LpqS^ za70GWK>IXdd1nkn{Q@8{_Ho&@9>2r{?ux(Ded7`-_(K>$C-hpD+PFtD&AqwP zYi(~Kkao|P*we;(F`SF3CB3F4-&nKNSBGbUOni2#!5tc|wkTGPZ z$1g+r3P*XrEe@|n#L{7pwrGErsr-4s=x7vb3}DSH%|`~1JGsMKW~Vsx*1JO4OtABS)n>#{)Xt z_m!4r3xz~*p{Lp~%ly7L5JAr940}XkBPe7nWL&OD@YJ~9%yp``ksCvNCda4py4EjJ ziPrx}HnG^Fr}vPy5{%qp=MkAkOW@8?=Kcg0N1(E2-Jnn8p7wJ`AS}cvU(E#x_FK>sia*M ziw6dXlP86fQ8<_SIFBXHlvDPUtk-y^zLyr@Zw1mfc1JTV_u%G%SLCV{A@L7;Sr!(F z><@!7(V~k<=}sbFX^iA?3B1)mDVb}0S(0OC0VP)OccfOUr>Edvc)~seryYy-o0Co6 znWjieNg=9!1{U+-F}n%P1dm7N{^*w&eb@S-gZE?JM<`0Js0i&Z!uNc*L9XKI-hIE3 zFaj3eExlhwzTyAU3q?T}A`*gMNhtA7U1B=wctJwC^*teBf}ku!-&qb1u2}UJn%a56 zpf%CCk*B!r4~Bkp1%Cv(0Ad>|RHq9Q(hP(C8bR3OjavHNC%rF$+e3u?ynK&mQg0tR zf7Q=ra(d69&Z`-fkg(r9pvhuV)VO^WsPPR(jImBgKHwXVn(Vh? z`*F%Pe4=Jw=#n*>8gE9f>?3~>J5&k!BM0Ml=xnBiHB&sMnTTrA08<;^JTlc@hlMwuM`hnE z$IQctZ*B@|$NtQK(L!21GNZ1)cy(dZ!>5oJ{*G15J82u9eq5=$l@G}RQ>~|ZCNqx0iT=rejn7p&Si$iXcH&3rt(Hp%1}5as z(p_ku@iu=i;a458vy9|o5zvif|5y>q1KPFM&5enw)M64d#zhQyd=Qk40qw>VKm8 z%XI4Ws`HHxQP%8(!uK;bEJf1IcGqe%;Um=rV*(UH(LP^06!sLZ2_ zErA1-nX%#By^ZhXF74|NZ`W(KB168*>pUu5ru;071G;_ccykO$0%UvM*G9mo6?wEg z`DU{!UO3mutZE#FPsh|lS2f~%%unRvhtcSukpD?$yF0yFL9PJ&scJQHbdT@~IUywz z?KT|{$k^W3QhLeh#a<-RaM`q6bH&MQGiCZww5i0@6Rrhl-CgM^GtKgp7+sgzc1>$k zU=ukNjJPDoiy;h`^fu`ets|uDR^f{$F#LA-g;#I1s#bpW5n1Mk_!X~Il{#J8Do)X@ z#x3s;*=)HfO{E7>*s=yq_u9hb>Qb+sdHH1?4&=~+9P%rG%##jeM@d)xD}_ZzCFf{Uc31`#!fZqFt97z!lx#TNxD zjpZa+N=xQUN7IriC&qWSf^v!|5V$+im31MzQ$ZFD2g`?TlT$tZDjc37%=$plMp8EU zclR5#P~`nFm;ef*q%#Vr`?;7B%!P0f?b%&$S5d%bJRHDm<K6p>15h;WUD@6>hz`*<|y{NTO0A2R<0gMci)cj-a z1qtLBH7SG9fgRSi^woq#7FI7$NDf))jpDeiD{y1n`GH4F)$6(=etse!g{T&=KRptQ zXzDG)FyZtsrm7oCFSKsP0b$%PE>?f z{yOKe_L#^&(^g`(t7om?p*Yup8jzOZc}#zv5S9hADGx4k^$budNn3Sufw+n z2Zt15_UW6a-#yk214>5Gn(7Tc9}-G4PfdZkL4*WHq6(nIYQG69#K&N44D{wU7L<1S z1PdTUL^cMWEH^o@+ z$)nyoHnECs2kWj^-k;pZvdeppl=d%jil zk&~qO{RY<#i#?aIwxoC+%hMKsQMB8u_#ZVRWYL^&riM^FjR}xcLF=yUyqLW_9+=;X zRhsOO1o#lOe;7{?5#9nGu@%xpR6!ta`l#N|IJ~a9DU@;)K9-Xlg_{Cvd=u^+QCnlf zWjW-W>QNiN9->SFjm_@}u@D+s5HK)4V+jf;Zih{q!ztz1dP&0lZgabKq>G5`)>*e_ zzhr9EjW~1*u?5Qhp-vcL47qZSC(J; zLL1-A0<^UIZ#!<6Ht`r8P%H8q_V$;4Au7cu?{RD2jZI_NWO^wHEi>IYG+~NG{`?jiSwkIHfT4!%~~>ni9rv zcR8771S0`~@pC|9=c3>MI=c$&Xur%^BGTK$+vcFw`tv*UQ!|73PU4=BwRj3xLDEP` zorg^tP&@$2SzGs+TG@Hy(y;(w5xkrJ><-j6OVoPI2R&Eo8T8rKq&)8E*^ud2VT$8u zkYeD|7QT^NzHM}c(R&YE|Qjx-MYc5Z#9 z=6UxSAQwOWJqK7X9o93fU3jTRjBI;csJ>_0@IzLAQ#y#oX~O38gvxN~gP9U%En}g3 zcUsO-?9|y3>bP8pQN-|Ecx!Fv50L-cbU8;kkzea_vz2vf82L@#B+S{_3a54aA?$pLv6n93%S^BmgHM#O;6C-xN7o;OqYl~t@Zy}81`CQ zs_?GB<1dohbIYPZ!+xWZhGx2K&j@9ht#3R}4x#(0P>il@LkkBk25pDa{1T6W`Bxz> zBp8T#1bmF$iCM2c0CjNqRM}%CLj!ADmo` znt_Y=`I=iOGWKl~$sN`OO*TQ?1Of;tlgY6;S~WcbuA+{lg-JYMjOKeLEv{LXCO`vC zQ?DahSn@xpOWqv?Opd&;Zu4isoKe_Q@1L8U27S|Y)|@`wKhsSzysd3bgi=2aQDCUv z1i5>kXK&aBh|BjX{+KRQ>P<xn<}@@@T^A{==j zRtcVt$b+MuHdK?8gN4KWk^)^B1+=5~TJ&nq$t!YQ%8<#Yr$SZzwcE**jO`6LL;{H?gv4{Q-{@lZ2^hz+tn)(f%N4Z#!Psd>?WvroSD;tu z=yGkGcCo&qVy}v23P5}6vOBSt1oLOhm6^5avANVS5-6p7xowQT9F{t4lxWCz{z;kn zu^U5wVByEr!eY;iVKVC{2`A`62&bRYD9IW2E;@?Hbhm;W!RY*+D*L(yn7;}be?yI6 zZlijy;!w<{?Iy3dl@1>Wbc?D&pq1HW%5*Brq-A$9e(Z1;%X%1>y?0*0x{NmpmAREG zRzj=D=kW>2!ToYhzA0$oDK_Ql3)EZyab18vB|F2*?x{W+y5UNRkTWWD91E|L8t*Nz z)v4qr`6RBcqzRuDyl@~L06m2k^F(|O>1^X?H@H+gM2xs<^zCCf>>QJN`!4ZSv^lH| zXLKf>dLOWFz~0pdYKI5L+J+M;(+?xe3D$%x+14o55SHPOIHRGqE;<3pe+tMH-(=47 z;CgH6?~ce2UsEYAvI^;vPzgvj#@B1%!wRYSR&Cugml(uPEhPpF))+NOjG65j?6c-L zZs%WoiPjjRjuNjTs>LbSP`cbmStz}N9u{a#&eEFj_(jfkN1re^$m14>Eqd5V3T5cZbc1{++b_yLbLHQ#0LwC7d^}366ROm z9bxn^o*#Md#RCF;UY|6YmK?iOsQfSjsj(feE;3O%Dll|z%dg0>HTN7$6Q}*4B+*nD zIRo#f&}I=Gh(u;B4A07YvX*R2ypL8Jo8?MX_mK!cQa5Fsr@#>~xg;-X6(IGhAT)Np zivEls)p@!ww-$VHnL4$N^F%G>VjZ9-hT^Z00PO8&3p;tKu+V)weTnCtrIb(IUSXKw zb(CQC#3t`{U8C2jH-j#+NC#t$8x=dUkzfWU>fg8~h_^}2ZYqkn{xzV%-8?+uto#My z8{y(%nz9iuUX8Z+Z8dIItgye{C4(VnsDZEYxfg?S-C$_?E;f54Ti@k6EQYe!GtH;Y z>^>tuCfRaD3K4rsjgfo{xR0yxhd>_E-2?M**t?)s&Dbvzc*%T^KS4y5D&=I#;YiR> zabauP25vz0ox-C@!N-MTE@dY)NM`f{73>_ z20TnE!F*h4*}EqzK39`Jl@htVoSyqM)stcE>DqaNzf)w-g%dLi2{6|O(q^fD2^)re zeFnxze-znId|gvx2Pqkbmt&H}{J+>dEKV7$+4&eKQYtEUgPbfT?iI%qz+^B31&V;v zYJ0GBY&jxP5O^{k9IScq6#3bEwP~cqXRo2db)%@kWu0ZTer__c+yg5n`}y%=mfEA{ z=&gZ|zi^amJSdf=1)ETzum#@%+gEyTLYX)2bU1;!?fwER;0z^qd?b z#CTu`jtch#e4=-kFf^odH4KlshSh~K@4#tTU%<5>`LeOAO-#VRVe03qEUA>}1Ula# zd;X2T5OF0%ZWlC3G5{KO`u^yl-^5!e2iuH}Q~Jcc=WBiFqa<6g$+zuRm32WSBQQHZ z*wvTB<-=kN0~0knx8ZFWal*z)TMK-W)Wu&V=lDSIqv>5c{?rGe^O5| zCwB;n&9^<Z!gU~9?N9$4H{kDp17cT}cz)wi3>!x{&GCU;a}?y~%ZG=+ znmZBsbkhcF!?|#GyiAUEe@ma8F7qeX9F;4nP0rMxFISKZM)?}E|IXxdt~0K<<%vma z!eAZuHZm7RpuTRna);`ml_Y$|c%x1NCQj7@@LR)bm;msIZ0xLh-Hq>n>vZwwVvh<50Z!DL4GKnt0NyNVYORA~wlwPImTpotFm-Qf_n}3tds^G)xg}r&<=F*R zE+!e$5{pJfST#}$p(6Se1!0QIYii_NAxV0$<3ogcDj z?^wxx?9GN_J+j9>tCRbYf8aBS{9Co&UO(am$nnqoJ#1DB*57)8CtW? zEpFg;Tv5~b$L%f8T^k2ycTX!ezSd(V)!>ir8agH5xac!&WzA*wk`Xv0sZ0kLZ zRvTY4*|Vp%Zo_M?N6w!6@$s&V`>u6$g?TcM6BwX|bZ)wF<+XW4qj)8h{KQ;>rF_nu zY#ja8f*F_hhNrtcx-@<*L8Fv7G(q}34@&}v$Ci&(Q58+`uRo2=ZW+L*>78yK#%@`X zbW3)h9LCpg@)h!pd&37mSFO+k+P0W?hYOfJe@FdJvc%-LTSmm>kJhV|n@1nGtoBoV z@JEKHx{Fc_L^ij7NlH~andS>l}Syoz3uvxZQ@3b{&zfu3=P02ZPwOUQy zA6Vv67Wb@7$6Pf|_8f#ggCK(@2j>n>v-uqYTnC#RaZydoDctpT%HoSJ%Buk#z2ZJY z_fI|*r(3>Zzv)T^#OAz|`!z$v({^wc#DRFR9%xs2<_BzL&hPS0236Gj?ioArY?0YE znQDz%VOf@FxQ{<@uov%^0v$7o{02cj!O|%_x;^nhUSjNhG7>&EWa6F+51lYSJ~^}S z*PQLXGNfhG7h?c`O1}!S+8~B;4yY)Z4jd%1AADoIU-75hNf)$+7I_SpOM=>MZ3ec1 zohx4V_A>+mn$-cWjU911yqs>z!*XxgtgG_RZc3Mp)=K}hI=UK{DajL&{*>EMC?uFI zu1@sTR}ZC{?ovS!Mt)3H{vFA%S!F>TTwb!`^XF=C8JZe=$TxpAbDWl&D2g*pdPrs8 zk3PiH_bnu1Q83YIlAGSLX{(bSx(V%C7i~LNHLWQoxe`eVtx!%j1Of3k#R_; zJ<$wKFn4+aNB0L9VcswL_cDYki%E5XuJKbF0D;iT?JNxUd%(gxli=`)As*DdD zd+aX^<8`Cdz0*%1!=Bre*IMu;7h=r%v2%oL-_2FgNh@V)U)HmE(KGs`PBa5eF_;1H zJe1BX4^R3|PWtnf#+uiS)-M-h=pjM!D2Ktg9&)j#b%4jHr?(Xl3wtLoS11|Lcz0G9 z=GUUzqT*57DQhV~tdFJP4%Z)bOCJY&un6~7lpnqo+4q@{E((b)9Hq5CXAeUQN7#ld zRBpD7;hnb|>*II~+Mc0MU_n{dEsi1R`%U$kfyz67n8(|q^!2>92CEb_CtcJg9m-g* z_kSOtX$I8t0fiy1A#QL^Mu(&0vlSWVU-2UpZz?vb6_(VxBu|0uU%SW?)Pg}~853@~ z;SdDk8yow`d(*Q=zCY?lTXP8}n`gnHy0~s2$$AK@6aiM98DZ^55|!!@nWHGBno>8u zhjsPDcJKO=_paUpuJOPwPEvN8IRB4N@u4k^(%7@PRokoxaasS!`f{aH4aplE)yGhGxNdXDgfs88Rh zAFdrU<1%}+e?{In=&ts<>&5Z;>yvSypN5}w?f&)MKQ=GdxWXQ^N43%ahi9V@NlDYI z3lJ0~!lfzWcYo)kI#SqrxM`E7$nvuZQ|0go+Tj5O!>o*1CXThgljzW7zIdDr3|;%V zj}KtCG*+fwC@1wEr0Vqq30Ci3i7j>3&k!E3nAT`tyTjviJ07yFT-HsI3{h{pTPN$v zvW6S>w8kXnsMeWJ{A3*j&bPWpZ#uayi6J!ZK9DmA9{RIP-&252qWg9ugP_w@Y6d0M zxGQe-EwN3MENIlflgD(EQAYz6Rsi>>_R{9E6)bq5bzb`?m7?!87wv4O;0qW&RfpgQ z%E+oAlXm&^Z_TzS7mOdw3R1+$7$=esda${{voDWBOb4@cZU$te6`V(Y#3UpTx~ z7NHGp>tUBN9@4-ucO?49mMpd~Qde?BZb7Z@p8A?PKIUx1WxV*cmLlL2Mww{2eWuZe zV9(})oaNgq%CpNqkzmt)8!l8Lv?bG?^kbGXK?_$jVHj_isf{Z1{-*sK7SM!?An)y0 z<&PF>dfk)wgWH1hLbl6NSLXoj)r@GOE|H|7#xETAy_yB@a7^ugxJvFT`C;4F!%`7N zy)m|^VOUenBRg!T6=T)LH@-ALRL$c8?q+kUZv2CI!C{&T!4s= z+qS+Y3~s{>DzDyVcJ?(cIfrC&4x&brVA73w-F01Q@uGx8 zpXKX48*+;c#wN#YPw)qiO1ymL+Ylbrg3B11ns7{h5P!;;wnKZQJcrpuRM*0lXL-5L za~^5E13Fq`zr?ioU$6iG2hf}w|3pPI;+`k^sJug&b!flBYXxLQdFjOP!`Usf^m31j z-yS?;wE;GSl{51On|mq&q)p5`BekC6LHa6$}{H$~(aIIA119Ky+E&{^8r5 z4neORO^naV`Ak@kAS88c@vJx1DKC|PG|htj3iesW3Vc#VW;RRTu&Z~C`=(+c=Fs6i zR3bg@)rqZG#kr#S$*RZ+f-un5&|DLd$N+nVV-ku-XVRE&UmSiDHynorNI_MA!lQRr z!B84$%P??ssN2M4ohu}%5_J&j0&)9N;b2eSvIFFlQyal&)bql>;yk2kThN14!RS@4 z2}D1+(>yEAdb4N495LDt-{Ks|0DyBiggIp75}17LIT;u!??!&14Zs~5ecG484V6V| zJRir5B(YfcQv?CF++9X5t=43A(%8z!Q6_^-EE`bfHIo$6vC(YC{aoN;I+jx*! zSUXv511a3~)gm-`0YrUrmF!Tbx-d+gwICZUHwnbFi{q2yA13Qmur&_0_qd8^-?$#1yKy5SaKq)jScxWP#=);2 zW@c{OurxlhyUH0orK$Ea@1EIbbP_jb`yu48F(u2X45-uVk!ZeMeZ2||bNT?wkh@n4i%y%a-L~j|3 zG#J}K>a{irJs$cE7f=B@UiImg6fPC{(Dp^af^EyTSVdN-_T^Ep9woKZhxxpNGO&K6 z7EcQCX`M7^p4StDU`f+RhgQ`UX3dRDcFG+UT%|rnft7wevUvc<87GQR}ZJScQiGU)FDQ5&kf^TvPw5 zmBr|+%U6s$G2&+=tvCbIJJ`}PgpAy3;VaF8FVQzzCQ2EylJomSb1aRutB+#};RoYq zNZ=mn4HTCh(7`ollL(cyR`qdXIX8SD@u1nq%7TsQa7WG&S2}0!bn)EvBCeveymlpa zEYC1^Ze6!Sf{8igNy@}EK*HjDhDI2$Q}L*vWc$9CVCXYxe~b0hSu3N^6;al+?yKi- z8;Yuj%VX`Zv>qyMq|%I^ZxU!WlVU087$Vd3}Ljd7A(3x$duvd2ijW=awtFCYkB)Ir6k7ek5*Wr|*)g zT;2LdO9s_h^W@EZSD=6RS{zAVFyFhjW6+jSyk8p<-MHTl00^oid$w%g6R+jXM(N=* zz-<4I^oCrgxc(JK3Z`hVxW{MT6jquKw3>+!D*`D;V|ciE7CG4}o2 KV$ma*-~R#7<1ASK diff --git a/build/icons.icns b/build/icon.icns similarity index 100% rename from build/icons.icns rename to build/icon.icns diff --git a/build/icon.ico b/build/icon.ico index 523704eaa0828040b04b3b98a86577faf83781a5..a6d2d8787e62eeb08a8b014172d2d218da2ac97d 100644 GIT binary patch literal 301768 zcmeF42Yi%O_V=G5Q~|N;s-%(LdrxL2gr0<+fDN&(-L>ng1h7K@6|rN(LQ(7m6oO@& zuj{(%y2V{t_rJQXu3|wELZ0_~?lVuAB$H&4%%pke^EtWC%w(SD-gAEU+;h)8_guqp z7{iPM4lpRgjh_!Rj8%qV9C3v8{)S#x;9rCrFFB^_x%3|=w#>?=vnC6j1{E=bMBsCrjOstJ^l-o9d`7f z!6}OhPfK6wuJ=4&esA)7)BZj6H%p$io?mJ`Uw$uiUt~qti({ro{4MG7oW1GGXv6Z- zeZPOedVaxUC$X7?MA1WdCOQc>-KSG z)~Yfyqt<1nE-WxpuFf~pt}ix=pPVN5*jrjx{UOhPiQnG?nUPb&xyKkY_M`+e{_IpU z;rw((i5Fz3`zG`I)N6{&%$rNO@3_6$cZ@%?{NvLG^IJFcnfm?gF=q5JF=ot(@n+m< zN$Ng{7i5}Am*v#+`+E7k)DK>XtnN=+;u^qjL!is~{r6EVexLRw&)-11j!jvRe-^+0 zJnbfaZ^`<1ln3)$BceQX=$L8Yv-$mFJpXl`{}Ru?HvX*Cf`s!khVpwOWkJEf)N6~b z<@tg!!J1%hgn%$=))*stZj2FC9W^le*qGrl^WulZo|T&4c>c-!257DJ#p>@z3(BGjQ(01;fAo@J}zR5=3nkh!!Lz4&RKT@7u zu&(m@q9>-kS^V_$|2bcnxr_VnLce~_{p+A(A*G|`A>2pkc&Gug`>-m}_bW4RD?2>< zuJMQFte!X-y}yS0f6o2Qq9@SZPfs_wzsdb={Vn=WbogR)_z+6_{<+*+>fH4HH<#|_ z{_khsIsV<8dnfM96TSLKx!KPB|YH z8Shq&v&P)jlNfg=nK^flS7TpFO@WzwRh}uO{J)HUV_%zVmcFXSU%7uh^a=O9%f5eP zCC``EGW zKhIXNVe!7vmxCkmtOue@FpYVSN_KWC7(UGDn%k2BhGqB~1xcPC$n3<6y zxqk}w$awBQf%~UpQyj?s9dV~8%fB|hxVPMYF!wJ4qnY#_(d{Ee*Sl_*iq0=-{9k?1 zGaN86mb|HM*C?ZAdx%kk)nt)j)cLGh2%p;j!@O^Z!`KlP(&S!pU$Mi&Ar~a`K=on* z*c<12R^{|x&4GO!Kqq3mKug^N&|Na8-uGo2S0yjZGD@DGX*ge;IiPscEQfQ`%r^d; zc}gw5g<6-~e?RC5C>a_LodR70$y`1K@_C=abrlA7h6DTfP;BEeY|Beao|}26^Tk<@ zU|-&Y{jq@Yx*R%m+>6tj*vN82xi548^bqtH=)cep&_26%nfp?7w}D;TSO<^YJP5lp zjd}bv*avU({GDRk;u|q}zGdH9^ZQ*q|4rxw?At~g+Uxn^GkG0qw6VOeGnSXWi%pb3 zY2@5LnYru4;koxsD#b2co&Rw8fAFb@ePZ%_Wn24rzHN7j?RXvYg#D<8Y74wKQkRqn z|L^mDruQ|^6(7XgS+|W_giX8%`|f3)|FyDsU+S>Txn-6^VL#-G?=ncw|A0C~cx))gkx3&5WA9$!{apLHFDb>zEsO)uG+z zQ2>+=4EMMhsc=j8O&-c_re0DPTP<4>`kk$WM;{Ty3 zW*#JSqx2-48AopWnrP39~Ch_g3qnd=REt?CeN3-4D+$*<6_l(1shh$Lir$N zPIkw5)dy`~q&zF>l5C4)Zlj)$e{xZwHGiV7me$Qt^L+O!RSozPKB7Kbpa-BuJbO0u zePbQe^CL{KpymrQmy$V@%%74jVSa{BH1VQL6IrPKLrD&wEgn@hs0McW4gSg4v`h1Ln#-j zxvKxq{}1@PAD=>5;w4!lk}tq7y{OPgt|>@LSzP$O^qp3o|10VsK0oz*yAIY|Hte`D z(;|Kc{&!jPW&8-l2K?1IF$ z5gTU>bRcB^OqKL|BatiSyobX7a-P2c{NIBvcqC?C+@0v9OL+cR@PBChS)Vn@()IBe41QW88O$?bp_8%rVgh$d~#*e8FPP`GibQTW8v0nEJ*VeK#nf5b8PBrnD%xY)UA zc8%-h+2`RGn28@Ql{xT87wh)SN87!98umIQFVcM!~}q4Sbo0;LE5aMrsxQ#J8#cSJc0r`ddC7Vy-N|O4T0fFELXR8*m{M z?%Fo9&31U|e=zm?HMGya+KS(k|M`LXPnY_8`(C{n+KYoeE*sHzN|2^nL%RlQ|7Ro2S)IF4Xy#zJ!QML9S-_5hEmmdH%Ry%9; z1cNngBj>(JgL5C4ltcW*3VcV~segmSgi(JLqt=1?+x{JiZ@9r-H)kY1m&WJW7vk%6 z-916ZT>lY--GY@R$|~nGgp-j%(`RzAY$QuMqI?S+|`pFAtvs>)L;3&B(|=L z^_O<+hOS38#DO%GgVdk;37y-#o~^y7{$|E4W9zB^2l##-r~VtM|9kk*f1v&My=Gi9wW@2g{`u4il4Jy?Hf!=j3}Pd4ZejcpLW8~!kfxq6_rI(vWK!}b3&Z3y?4fr`zw z`oJ;NbGLV0eO>o({UsLXB=7pGK47hP2!`JARcG(ddbs|Ap|$jb!BX$Yio=wzFk;eC zj!@U(L-B9jSxfB0h7l!)WA z;_^CF|EH<@6F%!tJMb5)br7}A;I(chSn{9$<;3P!nE7j1LnGEb?K&$iFZq|O>0HHn z7V&;|8${k}U5j<4HgMzp-3QeDYN#oGykszDMxtu0(}GR!@qq^tiQ-W z+7NSmtdfQBO4gn1wL^&ql|2L!(<*xzsY|Re#oZWnD&OC$S4sdaVzxa@SQ4AN%^80psfC z8fhLIl(iYz*KmKk^=Hq6TDO_Qx}ofykhL4uFl7>m~@vL)vAnA$np%&y~FytRo8l zJ5Yb6_hfC$UR$)*7yrWAN`%B!c)zH(j9qh~-7VT+<45=}^{wuWvC{ z8N{iI3@(G3>Y>*7-*fesc-U}}f%hu{3_-G9{`)2}=zaB<_^pY}>u+I5^@A$v|8-*< zTC0EO@xKfG^QWXMayJqW@i;Lpe?kB6RpXcFe~B_u;)IXg1-$DJ=o-aS^e^1g4B@TOy-5W>J z7tp7}srzE+JK1Zd#;?xlp9bO}{)zs)mAz&8i5F%KVGJ{9N8=-t7qTY5u;5_o|B{UF ze%AkGct5N;|LvPbppVpgeMQ)D)c=pvf3J#J@n3)bfc|`wy?K{Y|2W3Ekc9JOC9dTw zc~QOVpXKi% z@nMQDQ+%4@+svZwO>}6Bn|eNooDpdp4W_97Na~+L{by4D^B8|?7=ITt{$9-ZJD2+B zQ2#@)D+b7Zz>d5mrk~h~fzVF0HLpAj;#O4*B@j>`D2YdXR9l5RkU(Er{0nGu; z0nLG4%>gTRNcNe_tMg@p!`$KE_jL}l&R8I2gJFb8T+=SY7-bmSg$qNPm2A0EpW7vo zPCMlP?2=3My?oZ07td2Ko?jyucFE^;^4_c5?s>0D>O(!k3`%OhpoX%+2r;EJYetzh zw6ClDvVSjeS}v#tYK+t310AOYL-b2?KyyHIKyyHIKyyHIKyyHIKy#o?4oEDc!8{EA zE3r^6*^72GzWQ{^3g}EI7Habz9r?2Osc8nedK}~r97#N86fq&i#DvTs579jG2+kue zwu-olGS-ljSwlXQ*ouLrtiP7N+;;we*6NVDD%Z%kF3(6@F^?EuR|stz0UbrV(`eUZ z=;zQ4&?C@m&|jf1AlWA;YyTIB?>xhk_pr6+wDozx`br~zePsx_3Bt&GHH(;q6~vRg zO8fsw`@f<6yPYr0+DrTQlB-}3?cYiJKcoGBAbxWV>*l8r133m>41n5tREzICzG%rS za3LgZ+y=?szt16QW83k!%iJ4@eHcRgZHs%i^+Ca-6-SLOZiEjp#jpAoCoT2!v|si({tmL&)ch}( zm3~6(M7qE2mpJ6yhbB9SLk=S+#M#6Zyh{6bs#x9)#1fJBtP}0G`5-YM5(_vV91Qgb z3(~*AyTr9`>}2~T_T}b`TS^B~wkq;G;+Tmu8b}O95_{1X6TkBT?XQ=(ipE&ruD9Rj zgT&R|NIc#ssMR{j7qV`L{3Kp=Sr^*>6|v99XRaJOfEeP&=cV5>*2pDy9x>4S<*c4m zLi<;dgYI9nzd_=cR4%&Uv|sqJ2f7&yjA#o7qPu9f(CJ-hzvN<*{Hu$IA4;umpX4IwhV}~&euREWoK6VTD3|6Jp7y&azwIy&mJv5j z>=*4fGjA>1OZz_~Ug}-iFL?()r~P{+H=q@R-R8vmNKU*!{Qj6c7Vyolse=;8JY4_-(9N3^C3JUVa)ZGW<#wqN$GT;TSx&p=#Q1T-s0DFBlM8>1bd3U4#d;TS)eF`ONLpDqouR|K5s!X}{P=*okv|?!8hvV5w^q z?W}9Ht-f?a-)X<_;5qcbe!j*6uRTK&PvyT3>|5>sFZj=B%^slLl3yy0@*jTlpl`Kb zFmSH)0q+;FWkz^;s1aIvgd=iB#PHPXi|_2m?Ps4#_27u|up@{OOrY(h(20;|zenii zs5#NwCH_stwzt<8`kwsX#~zXx^S7W+p`FlPs7buMrbCG^iiM1C*_Jk~8PmAQ4 zX0L|iZ zqx2Fyko{JSW6j&;@B3}E^XE{@Jr3S_fIU|db1X5gvQI?mgJ%1d*mLeZ|MTDeBOfKc zAT>V{Stnn~UKQC7q0|78v=d(|YzVCo{;jGQGOpvnp8y_ZMi?`Qkdt}jvgQSGaeoc5l)_Tm$D z$^NP>)&HiQb&&XnuZ2#9CPFF9gO3U?A1(WoRyUD%d+nD!SN6Uo^n&bD5?;tYD#^7^ z>@)lE*fT}We4*593fbqDXSG-MV3FTmoiU^GF|rR!aw4*itZ^?>2iq?>G$m()j1_8s z)`R=@XW@r=toWJf2bBHh*a6O0k2gxUR(YFzvcE>?B&fyM&u3PjXfA)d{j%>#_HD`D zC-~5~cWeH>y<5bMTY3Fu50}~l#U3tlF{*uN_CBaCwqNZF5&O)0UzdGd>;444Zid+O zzFydVvPUGIwu&zBtpnO?KW$ezFWF1jxOZ(nd)H2Gx_?cbZ6JHV0^NSj6l!O0%;NNA zWAX8}E2hsjbP*V)_kM{qQw#(k5<|;tF_uA_yegK&d@8d!Dw|_78&llK#@3SBBUF^UA zk~g}ch5f5+4Dux_{oiK)7yN$@wbtYY$ld?V@V+z{G-3hn=fy@4uMcqiJwGXM4o z>I{L#oBOy>JSYzxLHid$->?t6asH$1|K|2z=j@;QgmcsXOdf*ku>VsNF3231a6yKT z+E^dSp46n8LOE;l4%Pn7$^U6=gdtF?&#}Mo>{k`L=s4Q{KJ&i@J7G_2ez^ z-~LP4iT(E)_V2muV~t=B>wwnwvD$U9OWH2^va@ObXEOiqg#6!R{5#Os7-&DkyQJ+# z=y>u7RE9;7>-sv{|5xN+---7BNdAVuVE^CA+<7wXKd|uP7$f1V_V>Yh*C%xmd8!u` z4W<20x6^)!)sdJTiQSPH9*O0Vn4XJh`v`yAZ$F!M8~6bSP)5@JlcQ!uKE(X*5A2)$ zjQP(_=01Cv4>yoYWH0vrZuZW8!+BT##QxvL{@La1|D8$uLur3VY_qek>}U8>;&YHZ z;c`~iMV|KWV*dLD`tPsU|F3~-X`{qw{Tz~*Es5Pa8htl1wbm7K!jtD2@z>}3^C+MH z6E$ayIx944cH}_LNBg06nE$Ymz^=~u>GzT;XGzT;XGzT;XGzT;X zGza=Q2dsPnLHxTT%xo~i%w5n9avf|pMv=(DAti|%j0M|`A-gD@e7Bu4Oyy}Hqe8QC zi08ffXZ|lle&kg;>aF*UrRRI=)2{ywtFi9kY*vQVS)VtS+pYJb?6O%qMoGPf)ET3s zzF{<8F=2->#H@iiQu3W*)-Gd#xocDq1!LV>@ahC4UUKAb!RBiMsH(7kDv;odx}6Hg1?Pm} zdbgJ6sH633>;F@3a2ZM0l^CgVhTT%v0ZxI$14-bxp+$9#%T}2|38vfU`O%O)A!20 zVs#!Z=h?%56aK4nEL9E;Iop17m6eCW+G}mX{~zJG?77|yU4b03$WNehFqUpb^)mN|$)5~`9cqdzoIuECb2=T$^GDc5&1=G3)WV? z5ASz3<{XtXj03@c-{777Pt91W2~L4@bbXpU-4h^*}P0X(<8}iVx&XN~KH4rnbGp?5o*U&DLhKeoKe!ydRXcpv{IpYLvR`mE1fS(ZmGnIQ$YOfgb! za~kCIHF8#sH?r=UFqGV6(VXW#pL|9e$?y9){5KnO9QSViiwww(T)minFxXc<%;r4z zeh=S82OSN)2L+4&R!*f`%RWH{>#}YecNuw==4ahL{$ylub@rVTHjrEC@9=-Om0y?~ z%YBRgB7+^s;MlUQ$N9|3>dkZSYc&UuGly&4Pjv(TP54j#J(bt0p1jue@ZW_0X13&Z zzQ@k*+$Z@jGLU?bNgdHcqJJ_ZuMoLax|#nb{D=4bivP%<`d)O3bJ=9eH+xo{F|NWHzb9P`0RZ4zzfBS)F9u^1xw+E~b{B-#*dgyuj!2wXK zxcC0T;|G$wM$c*flLu7Jg7NKt5Z?Mja%RXZ$giPNE zeAmh3!%*YEQdbc&_+LQ!fad=f=${hl1OB|Mao8niC)H{GcUk{H1gzdz%EhyQYZ*?pS- ze%U$g+Ct0&mKJY220N(zaX@^K;*(}RPzL|M?2-&L{%zU3PCq!Py>a-+io=bGd2@}U z^A8>ncSiDI>9J&bcW+BR^mg#2Ff) z^C_=}R!5YFZi<-~_kSuUd}ncl=LR{SRKeSL680$lw5Y|GwY+7ug_#n3EF74P4Ukb(!A4f6jH0_#cT! zk+X1QJx$I4l5;dzS2l?kQn6Ta29i1lXK&3jIG3-YQ zRa6dW@?ZT@YdzgQn8(AJIX9M^?AEK?XKyqi#iZsdV?Y|7Vga4eJ zRRF&w_R7Y3+I2;ozXZ?a+#xx4O7UOL-SV8h)SUm4gPJ_tGR8@qs5*x{@cb8f+=`9q zg8yxw)8tDI@L%OGM+W2wRBH#ybVfxpHV|GN6w2jG7={O`mVZ1X=tonI#T`jrysxhE z+Sl*DjGYlK=fhkJ`8Nl!|Ia=VB@j6MLoNe!n$~_~*}O6080_ z^cnPLNX~3~7`hJoN6sjO|Dm%ecXdbxKKL)^*EODDz}aQ7rzR<0D7%h+EPaC5Lv@yY zhT^@4|M1ci|FbXt;V$BSRQ%6G6$2zTV{N^Q>YTZ5;6HWEL*I!VBxh2xM@j9SQFA!#Er~^yI59aF zkyx_d5SJP`?(Gu>mb_49IA3miPX@jp@d3#g@O%p%+q%YA>4X1G@Gt!LKF5##5GCii z9LHI9^Ek&(&ajiS`_4%AoLgs|-4}n3b&j2!X(#9Uaju1Rz8~-7o1Ae6_Pde)(r>fr zlUb|ERNRuhZyev$nSgRm5|~-)-pL-VIeceuenz{?yx9K+XQ0X$a79r0Z=ate<+Zg94X z8pqYymJ0hl&wpjt$vj7J?wjxS=U);(<(3#Ke_oaj3Ox|sZ`J(woWaFhrtusm^nc@7 zWd8AA%4Dill@9sm}ex{}E|JT6(hQ|1Z!1BKyU)+fu(f@WGr6e9yNaD0sK>OBc zdJq5iaL)L9tPd>YtnuW;3$q3x1MeoZdY#O<+sQSG!nuA!)+JQ@NnrUeV?YgSPvmNI zwOW_9zJTwdkM^gOSlq85EB0Y3YrtOXk8S$@1MmO*9{>OAtbd&Y|HG5cPaBYUetKKY z@cCU5=fAVY!};F@vxvv~Hc0$moxao=(pmmX#nn0){t4tT7yiFT>`4P>$9FIPW$o*% z)GzS=Kap@wS~dJXG~pM?hQH^``xF2lf_tG+@c;QB@&845KfE(zfOnl`Ob(rVw47U? z0RL}?|6g1#Rr9KO>JicX>2qt1X2jQ_`; z7yJqz#3BCrA=+w4MCE7$zKaZoP?o~~`-y+}H?a?UTde51WSHu5>@c$v=A6|~08}s|KW=3GaXIUcr^EkZ_NOr6w7Bpx z`2RKj=YO#N^+wwDCF|JpQ_I@#Iq-ja`Vwaj`{BaD^?~qtP%^n>B^PaPdX1S&znB|t z!2f~pe+2wLoY;r(sAFSdqK}J-i#a|vI{Jjz(b4nb4}$+gVor*8#LSN~kVB6(BL)7a zFb2>Ej!e0xD4#f^DENO6ydTV72M5$+b<+>l9MBxl9MBxl9MBxl9MBxl9MBxl9MBxl z9MBxl9MBxl9MBxl9MBxl9MBxl9MBxl9Ox??F#GMReiTisHx@_(4Y{r}hVZvW{x%>U z)7)jq^$xC`p6fcUN6B>vzu`5+y5rq~xk5Z4felVn!>k!ZL<-c0LuCs2!Ux(NKJNA8SI2!+>8!l?Rp5b*JvhUiv znjr|yemPpXHY|}?|JLfYNZIpR;C-z`Ykjf6>)PohM{n8L*CKAGB^QSjPK&ogq;Ogl z4U;0ws*r$>Yk2_3+Ai1f08pu}rJx;J2%e`Dcd&FaBrE_7n|6jI;US>Vx(WdSy4+}A>>Zok36b}a2%RPD%Z{GImFi%e9c}S(Lw^Tmfx>B){&5 z&==76&|b*SCoN|wKbgL4?1=PU*#8Tjm}WqZ!i`f$K=DOSPMeMVuP=Uj`qRZv&v*~{ z{}=gxU-InC`jY2nn#kWo{wA_l z6`ZL&fisnl;(8#|)8bXnPrTl3WZmW@@3CtDeRmjr_+ZK?a`qNb&P0aiLCc`^(Cd)o zQuZxlZ+SPrUgrJ_vXAa9^3UH;VdOnt;V9Tpc|hUgm3c*vPrZoqnV&@dA0q#q#ZOLe zKo6M6-$efE{AT2D`jWrXTmCOsnQkG@eU>xmwNm~4EpprysxF7OMYz0MgA8^a+AxMjB+N|zJA=<>t*hp z8Ous%i~KpmJCIHC`(B0XD~*EpPBjYGRtzgxUy)X@zVa7^8>YU1{69th^>SvqoY9T^ zP2_L-EB_|_zjgWVJBxkW9696uOXvk~a3a_^qV)Ay2G@SKrL+Htj76Ux3_XEdr5^`Q z#%*DP^Vu_&m)@4PymV0d^6s?(3fE3S=932$JXZd*g0&S@1#2tU6t1h-4j%RtuAgca zK0eh%{$@AI-x~|xgM%%|ey)34_5NHNu5GhBE8cd0=aK*Z$o<8D^y{`{?)@F|NAB-J zQQal~yhqB7yobvN=RZ=OT<~bcWd)B_{0jMhhy2aLb+q{Tt>!<;OKz7HRVR}qm>5bi2R4kUC94dnGt>osJYcLh5^rFBzSO3~4!fV}%B8u|B4bmToS=_q7BKkvcGFXlZo%xF!Nxog7UoVzDP??>+aSN?*5AF&5+goZ;c zc+}Aklnt=dH5A!D+{5xWGjARH6>?t>9iMqySyJYzvcoc0joUx#_Hm=K?i~NK>^sM2 zWZyO6`0TsJ---PHi2T3Lxp#t@yLuvo?0*{a7YyvcPjvcNH8<=U29UXtgdNCS@T#7d ze;F8nR+jycb=$b@S*ynVCiC`jo3m~o|8n*n z8UID@-t>2TM8%>5@DX&h+c*Ay8fP3TKfqEKYdFgP*LDA{x39<7^*;Mw>3)y?w`6b0 z-$ec<@;B-G(0CKsduW20tz^GX{%!XE{wsg5Q2h*cz~NoB1w;qn`%k6(xLb5Ucgny2 z*#F*r-@X=G;3D^{Rrm-yuLC?bz`@AAPRqYX{r|RH{Vwqd{Dpa88e|l8avTsJK-v=b zKxBW5mVe)pzt{xG{#MqFhjexvU~S*B0czbRApc!K$AH%Ve)sQYHeYMM`#MAXZLVmX z-}!qXHek}_>9QX5OQ<2J7|{K{D{^k_w++bty3$vxLpq}a4lO=f#bSYj5@av&UcvJN zX!*A$!>)e*2Yf;iosqxj348!TG7sFM<=<`be_fTi_wRqe7kHw`U*>}yeTfZ_aV@d@ zOWju>|E4k9fz$`O|9i_Upx5{V)`Efk&;uP6zxsdAJRlqS|0`%ZK+8X%GH*6V+|E2O zwX?neWG*(~e$b;@{@oJ)9cV1<#tu9~-qP{{4IXr%~q3#()pNKory|`KK=@F7U=e(E}0} z`a{5VfR=x2atqYw-+_l2(*MVH&<>0!4>ckxLLEnDj2f7DNmgvyjm|f<{DZpxD^N0T zcAx5No!hD%zUBepQ^Jg}$zeuBdDx)H^01MS6`@B$snGbyim>^V3nD7Q?ga}k#+{b* zS=vp`!1{u8|8FKM-{W{Qo!+6}p!=W4{!@F%kmE>X{WD~mOy3@deCKg}HL|}Oc|Q-m z4gCxH8u}4xfJ~t=(<98J%X75+{oMcCiT$4)l4}Pr@gaVoSn&lR>!*soRQTvYm+lK*eIB>!^8ftitJ(iORV zPyT_L|2>TjNbUzk78gqXmagHTJNti^x)hHF)2KhJU7E6_fJpuf06$d?7%~i{X%F@moZQoX2zVHV5VMQ(*NZz zxj!~eRr`cwy*pz z!R+(i_a-*9I)T1>0l{;br_W1u_b?~nZ_xj&G({5Rn53qkhF0xJJ$5z03x{=w)I;?(#k?euG{peN-2u$BKKkG?K@N0pAh zD$h*3ILl1DC=1y`mj*-rCFm7&0MB%h2hfxMFPMG4$-R;Po5&p>Q0OU?ySsz|?Egp^ z|E2$X$zL!KRUKs}oSUZRMeSmsyX4Q4!w|1C0?aXtN}5^Oidb&>fmGR(vaAi1XBOaBkP{Luk7lqfr+8|1$SJjwd+f1p3n z|2Nb3Wli^JWH0MHt^4}h`_5PYx8;w2FiL0^R25~$oRpw=D{~>`H%8`-dcl_ea+UkV z&i~>6{%_g;e~kY}r~iu%h??yo z#)O!8@usXDh+QqVaGKZ%B7c$n3P0t4hrRcovN87q@|WBX;6QQ%$UH0UhGI2OlfEru zQ3B6Z<$1{d{EQxzznUj4cdMMi$j3JZUgdKk`JORC>_wS3kW2a-^u}v^{wTDB@6M*2 z#@bG<#QWppIgsn2?yYkM_=@|s`hU3SfL|d0`c7k@z5eele{_K80kI3Bh43B6%ui5$ z0~sHrZ#KaLSP&Vi{2#ZKwaovZ@<5Oag73s;&tN=FV}6}{6?&aM9*?}mClLq5pKZ$? zxhvWC4*5$Q1v!S1@!S?Nmh~g@imQ2o%++jm6Bv zlCNOy&3K)ReJ*|%(H+TrF5im|7kv_UW{Mg2bD?B29zR6-+-3b7YMXfM|_DNEdvm%T%BxBnR*5H?`w5y=17 zQ0HubK*;|XFo67{kBc>96vde_#23gMG8)@a?8n#>;}teyu_0u=K`8d*L^JMG2)qcz zo=({)`#vK78=a=;03}<-K{Xay^0nmL_8yyeiN}qR`0UQSSOYX7r-Tkf_BZz``5%wW zk-f-0M&zytdC!NCzsNoI6y$yi^2XPsi@C-#0CsQ_MMvtYWa6){m1hEGww6@ld+#zYD@ojUj94qBb9>#_Goq-16Kd_9F5-XMSMKv!gE#{lsKj42N#CMfh3E&uNI z{{}$+OaI?V|F4o<4V{?_hz$@mWsIx`os0ZCwjQMWe{bmjY79tS;vUplUx1nmmWM_o z|37v}2Wa{C7Ww}U{r|Jhj{(XK7=Y|+puK)$K+C_k$p3%HzEsA5h}wb<+kx@}O9zA{ zAp1XQ`3HObKVb7e(fvY_o9Cj8W$e@M#5_RcFaDs2%CG^HzeN82#fIzt-&^{>U_kP- z$T_?s&Q85N{-6jj;NSirE&tvm|39GrN6Q${*_X&axjasM0vqQhE&tvme>tyJ zay52V{OWheT;#t$bf1=gkm5fB=l`|Ge<|g>zEeg1o$&?RpouO&!m8iZc zeLjF&)|LfZ}_kXefryJz|41IrOSNgw=11m-_Y%qSoOOU_sy@LHu{td(weGWa% z-j7ogFU^Wcyfk}AtMd%kT_+gH3-S+4UQlof`#=BIWdEo4{=e>! zf35o+=6|C*I|poRnCC*)2B7`X2en{8a)dNpAL>8yuO~+IL*l%YPTK-)|*c zka;EYPf55aYjDCvnMUG8XZw_MTOYC)+(^G6%Sf&%oSwX}@Kd$#yZhz;9q}O3#1EXl zByeY_dtwDyBMe&(?QGNoeO3PFrGHEO_f}#@&tUIIc>Dz!0}?LCXiL0)eTVFgkz2AZX+5g==`oA9g|Lm^L0em&q;~yRc7Op`4|5X_1OY&DS!0De82mClO z;MK_gu*3^99ALm#b36SRIY5l$MFnG!|64sEf93iKR)CCo5g=OkN*vL{9kH4@!x-kRwbO9J{I}!pKy7Ck#JsGYt8J^ z=c$Vdjnsv?4&;9k^54^#|Dk*Ozsv{MF#j9U)j42mOhEQVXnB|e`6na$d!VnH?EmaN z^8b$b|6fB_Ap4Z~b5aK9Ap5`cfc!Tx{*UVHTCjIJTDv}K zx+iwHGHe9$pNaf8vH$lw+4n2^KGptDwfE0!|5xMwpJ4X?4XK8TWTWUm*95&>_K;zs$4qhe1_c0hKudbA`jo&m)n{}26l%>Enccka(e~O8kDL)@piwCCH6`qkqcxL(zuKEzXzI_ttPhNus=8|wWIU?lG; z)%zOWJ595JLf%VhjIv6H^>6A6`CQ)D$@kpAey`pd3ry4cxZZm2wB9c;w_ESS?DsX+ zdmbPcPW3b{sG+RxY{{mH0r61%I&y!6Xk3+1Qn05sld$y-5n^w&hcq%9=rH0$^zK%jPi~U}4 zjL+2)ALM+wYCqR2RUytdsvOQORh_7X z{z+RLNUsIowQfiHQrE!LTIbNzrLIxn`)Kf;!u5D)KG#=5ck=l&(C?ssKwp6U`m|d2 zD`~Z*KZDwOOuzol`P4MS{nS)P(Ua2#7Ct?Fc+peSk1Be4MrQFd)2Eg^GyNR!e?#%J zGwuib&lEpDmLV2z&RblR})%%xjtsYdmb&jKS%bb4A->x=J>2RgT-67z7KlJvY z;5h=Fo}RYUIiBlze0BwRzK!drER4H8;`&Rjzo*;{HE?a(#C=TuA9DW%?B@vn3vT*p z^a1zAX-3}0N~3sV<-npRrXEtXaavN*Q&XoEJvHqLu>TPBYw-V1@c%WmtN7XJ_2AzG z|0ei1!9O(91pg-3_s}d8>|3;na`Ws)0{`{UF0lU%*#9^5mV0Z}2JpYAw61z~XV&W*l!J+o}(9 zy*hh*Jio#FKSTe9 zz6Q6u1=kjC6?Q#X-iL1+=WUiA{CoOK1NdK(vAlFBWuMg@zAB!-zQV|RtlU94tYAY$ zWWk2Ync)BC!pEn+0ro$Eegyv}xHpS7f_2K`0OQ}e8O*nie-q4`=zNRns(%3gAA$d8 zpmW`IRmr7WtA>@<&2%t6_-bOW`>bGz%g9*nbY#@J27uRL;P~M5rOq(0odUUee++a9 zbTjlg^egB?=yPZ%I9IlcV7!Sw_tN2QV%wkpYl?p}eVKc6#xi#(_cbz?kL`6l?MQ_R z*J0aim~0fRs~nQQzA^%uTCl$I7O?;S3O7{l0RMZ79-nH0eT#Yp{^x*ysBVr4{!Oqi zL|>@>6a8ZaQ$-vs}P1ph@(OzVC4mp%7^CmQL`lsbymP99wF=#(Dv{RRJx{XmTe_1H%5sQJOR>LXme%wHt6 z*S_$-tn^EC|4i44QX{#S&V%zFDL3*SEqCNTTz*8}!&7GP{%-ofhXs#T>;e0x5c(hL zr}+2u18aUT=NrmL7!L|vTdM{!CiIGN0NpS8AODV zHf0mNjc@2g{6r&qgO5n?Z{Yu-JQn}YcYOl?%Sugr|JXq8f2FT*PszXsl)l2%qkSOv z!O4PoBj>@%`{h0~IW=$1jn27mQWe;L4D5djHRL@w*~A8dH2!^J-u4SM zmTDXjKk3s@>bO75a`ePnfrWqPf$0B-px);LZ4>{@16Gtaq~Bcn6cm?+FDUbtz}rFD zt0x-S_f8y~vwC7&&V3Wlqz^m?{{IL5O|Wm~Jt(B{?;q~>jRR`^xUPB+_}|EUIKlmL zb+_9>vIa){!eGj4q2A{MY6Jh+Jc54{?Ejc?bLk^cT+wYAM#jxu?*p0lPBb#^nJ^&h z-iae}?wyzqEe8L;1^3@D4w#f??)~U`jsK?Wz>WHSAI{tD7j@OU=>v~KVc0}L8M|A% zsojn$sBkh zw$Q(O-5kJw{7WBb$hc+fpTPc=nJdeZp&^+o+aC+Sx{-C)_(9osjUSzJ*Z4``{~A8q zmVM8JFTuYF{>|Lg=zAfJ|E}wMAALgB$*})-;1|7&HL~IK1taODS%HLltM`&Q0QgUW z{@Cm00RG}1J1FyJ)&_22EV#Ao`;1%1zLl|ZY;ERkWiz0}jN8f%%Um^X|BO}RhEopD zx_#UMS$B*-D(lX1S(L|S-8p_K_}>ct{|)x{KqmM%HU1mp|0TXHDA?a;AE|NRW3WHF zY+Ln!?ivTcyx{*3=sAUd!CY_feYWHO*=PTQc@O@X|C*V%l+g$HY~|Q`u)hQPE3_?h zRoN3@e@*7?;~oM3&t%;(?ziCoW3c~i)}0gT!M_Rq%^a|==$?uG;a|-GnEyVg{XhG# z+&LS`GbjEX<3Kvps?HAN7pd4k5c{}PoPY0{19wpW3;xmnHvUa;Z)U9=r%Lc|f_+6` z-^_-v-QP+5 z?+gD~^n<4OAFuGA9Vq;Z|5NM#fZ0dj|4Xp{^U_zVyJerT%!9$ci}Ev#{|?$e+W#Lg z+`2jE}U##XYAZ2w@} zK`It*iE||Qe^}#R>wh2lAG*Q+({#>E%(V1@PsuG&K6%?*qbP{$0^r_AyGiAGxP+LS z`d(uLY5m_f_W%0u>D#tUS4!|Nec%alu>6cNkZzwQ_maH;)*L|P@98~r0FD2jHvX+K z;D6XZC%Rv+8W1cyC{^tRmRJZ^4E^A@Q14g+(D?sJ!foMWD={Cijtb0O)Y&d5wRKf3N(v-R}Ri?H{}J*gK%__u5zSrfj7 zoQgw&l}}FQ!R(1SoYKk*+LN)+8vh#qP4O?j&^MR|M~e+qS~t6i{T_%n3ja%-gVL9{ ze#snQPmkI_8vh#qUiepYVb0;;Os2Udb@Ls;m;Q{~G@-@h@Y* zJ&XY(f`NY-L%_Vyq0m~5f4%>g^N)Jm|I_FPvgQFF5EGObtau3WK^SqhMGmlkI`nmq z*+5$VYyIC$|I67ktOb8ZpFGL^>TCz`(Sb1gTiip%#4U9vkQ@EY9?Os37x1t5{|0^i z%hvsNiQUrxu}896<%(zl-T-{y!N2SamfTo9GY{7I*ZRM?{X)|2FUs?tg$zAr@$W^ns4PA}hj-$ciXO zWO?Yo$SI>oP#zvx5jrNKJTxn!eDq|>lc5C>Q$p{KoEH8{;)R*tvPVGUU*|vX_BpRF zdkf5qA7~{stgSh4_>|EGe0K-sQ{ewslz)T1fPUcr z8YoSnsAHndl*NS>{<~w3q}Kmh|F@<8SqlUEb*zUSVduySFAp6SJ|%P%bTrqg&;+nM zAG!*<3wj1j{}%cy*PlY)LVF@Az&OO1;FI_tGomugj6XZo#1877{lOal8vkwJAI!^I z@IQ%z$h6PV1E(vYr=Z_KA3w?~(Q@p232^aFIeZ_GFE3)n&CnAu~@q+jM* z_z(6Npz*Kq-xmJmJBfv;t3HNtz;K(@1~~r@1imeO-j+^pj_>x~%YB7n=Es|<*A>$T zf}AHp*8@$)mx63F@dOw;+oEYta-l+cS@zckx)32owf^K1`Q znXZ>-n{J_3xZY9?b!YznrupA|+55ge1NYXRn5|VIF7l&*&$j}JdG9`9<3Dn0xEX(b zx+!yESr=w)AUO6=U%-E_ivI!gjrgAl{=G0SxR*ZA-|%nEf!EOw$PT@BD|Sm^qx;#F=NxE={|s#7w=RSdm<(FLRk$w~aM(R!=Ys)>W7# z&tV&h{nO|1uk5Ce@P!s*9~sP1&jX)3?fGqcSnk~S);vJ`L9stihR5*NKCdE>`-L_B zTk3zoJG#6O%;#~&eAew{_@kX>>NSOCa!rAme04sQXC^P8T)=zzY@tQ0VJiQ%^ovaT zLc!W{Yfga8FSdVQwEtyJfZZdxfsU0m0DL*qp#KCF|JXmQ6IlMz=@Hgk0H3JXK>?i$ zX#89F-#FDQd=h#BJ^$zw&T1NGrY|W`xK6q%&lE})QrH*V=bI@tLV|nx#UgO8sF2b_ ztmCBKSYmSCrCIz8V?p1>|8DZ6U(VT)A?W^G?4Lh%POtmt2NmCv;9s60bB!^xBhAE1 zvX~DCxDWgk@xLCNZ@_NHeiyr@@QG<=!TJhy)_mqIrDp22g$nQDgHB@pC1hbg&rA{A zqw`hS3jR~ES5pQ1P|7t$X3DiiYAh&vYTCXrpbzGEJ{_Q@%yrCHXsSE7)CI6>|e`NzbO2I&MJ5 z1#kRUhO2eqNah03#787uK_3vmXdrB%zJ&j-o`0u&HB*_JR$|vrHnUcZWsRi>{SMaA zD~iB=vckPxitW=i{HLP-WeiARJx9(1EMbknjo-ho`2Q9DtvLYardB6LN{r8x&>O*j zLqM?ZYiwu*|FSM1F+yq_@Yq5sUbM4w;-3)y3)W)e+&_tP?A^*%PehL-UX~3B_Q5;v z750OLfBJyc8Uya*mlknmO?3v%vq(ZpS}kK;%?xp}F({nGe`; zLb5g>)X{#>m+=2k$IrhmSX*fpJc^BT?*ucW*2%mz&%*qr;9dyqi!SLl{L=^0m${XH zsW0h&5B~oL{^zj%#TwY?a>`G;8~8QPxyZn+&@x|jWf~AytP#M z;gx-Jkq7tSKS>DOCt>$=KmM_Qqz^#kK*sMh)x@7@l4q)q;Gg}#Tj$)4Us7Tq4u>{D z!I=ZMV*ii9_7VJ#0smvB(+5}^h@2T|#+($7uOe5?iyQZkE%n15>a+NtV&=0pmH%+L znfJ&PwN90Dx5vg|Z7Knr$6uIXCR~(hCW8N@i@|#@!hh=Zi~-nWvL?`n@Gm~lXCo`H z|0_lh0sFVn7lJbf_7neO1ph)aBGjB9ftWe*w<+JK;9pT2<3V4=Kd}h1HY@YltW{-Z zn)q=p&o&bT^A|uDW-9C_Tx{dtqx*Y-{!g>VfaPu#PlQjgPw0P%0|NhVi~b)|`7`!< zg`NZL3W^QX0sM~v`*t6Yn7Npf6Vx0}#Y`xCdu$@PZf+O#IsAip;z6_T8qa*zrPg4@ zrk8n;BCyXMQbnTsdo%t;K4P!+X8Yfh14828Om$sX{h90m2KVfD3@xMl+~2(|9qK0? z#Xo&O`oS1%At6~Slei&Sw@JHE){H&aw@bSp^h*3sG;#U=aD55$^YNx@^Q>N=|IzKD-^I_b%Idvb|H$>X==}dc z9}xRf2d%O3j}J5g{Qtp@Q|J)Befj*oKkF#|v4OntKV}yF0E#*$#*CvM$Xce%yIQOn z_ZIx$JITyl4T1X{Y#JeTP3(-!Wz(>iW!+C~oA~q6EfVZQ7VgpceF^`xN9F+OVgo%r zP4-w>)Qa!Lmp`WSpYbdUJiJjw9~3%*@0N&%Aw{BGGHv_#S1w zGwaUr&;(_(g9ua-i^U<#4ujc|EvBkI(r(`q{hC7V!TFn68B`g62Y{P%{5> z6y-?1A6UBW7zgzcxVLykP6;)jf#CmgDDZm$0)T(%15twiDyt7jDeGo2C&rm^XQe1V zxa69!>?76>z`er%a{2)H7tH&_|1Eyt|Mq?O7d$uOAAN3PKbtK17tl|Z0wHW-(!=j{v&%SCBEAE(yZOY z7`=n;mOWd`pbH_vxC`tjL80LLAif`pP9K0y=bWRC<@Uk$F~Y`#)Rk-GFQ#IYl1ZnFeV7rRo`OIh{OylzYVra9Cv`fgK%pNz@Uu75Bj^lfqyVB z_!koV&xy8(F+uf(<71WYNahO(=clRlQi%r#TXfi%XpTIT}o5<=H zVjDqXBk`TGq0s4R^e2famY8{E!{e8UKQGO~`5DP(oFXuPh6nqN_!pa}pW|P63O^+_ z8rwtsi&ktL7?-{DvTs1v$s~43V)kTtn(e#1nxiJd=(g$R|9DOXG9ZPv! ztlEDmxhP^zNl^0#rJKbjITu{oz8B`C%J1&+y^Bvq@GaO?`W$?VFG}Vgv8N@PF;bqM zq~_&<{dgfTAActL9#Xnr>HnVw{!`RWBN58;+QvE~v$VmwnvHl=y5V0pGnz5%qr+P@?-@<FE8R zgL!oRPagk_0WuG^N%TeiF>@BPd-0>eyp)3fSi!!Hf8s9`{yo@N_y_xOU_TC>9|!go zq4!1iYy9Jj#`ae>rPzmx=mWA=1NPHBdcH%kT+RDHt@~?q|MBTJxgC;cKNv5ufuO^o z7i5oC!1_RM#y|ce8~?HM(evp3SnwY!`rpRC*h@a}Z((2KU)D2P;9tf7FZ^>pbjM;D zo8Z53>{yTObTAYQ_!9>N{wu;lm;+x0?d~u5kHP+FRsU=Jx3mAZ>Hf!k`@gLCPg(m7 zKK`woY1lvif+os&qs$wE)CY)#s0ej~|G@1B(E1<$XaAr7HnD#Ks{ip_Gai8bdT0rA z;r*bX;UD`S8z^)$c2Hn!AdP>G|1Q}-9{kI`s9M)=p*XRDSYr%$A3*QRet<#X{|fNG zCm`_C{{&l`ik53elXcOkAak3oQlzAIcb@^}iMWtm8k4ee0(9H*edg@p`HI2V$a6Nv?Gd2-dzB8C2L8 z28E7b9=sgt`2KjU|F!-Pu>QCE0JvWX4GWh3w~Z>!2%ry)&H(@Kc6bcX_}BOk68?#S zsDlmolzul=9>&;P0PKYJ(9``d|w$PBvvS1~~< zE-sw)VDjd6U>?xJ_}A-S{T2Ue4*V_tpSgnn(x+y4tL%VZgL`7*A|yVpoa>MLj*IAF z{A>N+Pw}tTf!%ws{}+RQaznTRj``*{BqoS8fziXUgBC(R_%#k_{P&psZ=L(-IRmmE z#DCiJUb_VIVgo%!9NhlI#5IR&P~J(y;shB@67q9Js$s$&bP5|&jFbG z{+j*35#6Exr9**vBYbkQ>=Q1b54_Xv9vO}Qpx~b~!1jXs&!AsJE5ZMK@Sm4>dG6@M zD{>D2|HHxmaPYrB*grh+s=O5NKL`A;1pn`G{`;=vcF(`=9sA##VBWhAkno4fyV#0VE@g;OS6_GT$()-8k2BY_Rz%3 zvYLyj#rveI^Ni%Ha)*KctfZ^+Zy=B3N0Q6YIs?9d{E*~!B#)`&GEG_Jg?%{#zBlau z^2WY>z0^f4oO7=1hwLsJNEj=25Hu3{CH>%=R&61T|3Kiso-<%R<@~P=od0za_>WJ# zG;_cBOWVhMi%!4?oSkYUEyx=V_A8(_puH(IeG~ua{U4!A$PLFju*+9-gZ7#90p`O8 zQ?8&7?DV-drt#lt{FBT2d+3i~e+4uS{2vJZL!d6pG-*M;k+d+&K|jb!uE~EPxu&4L zFY13VFE-F^sY~3$Q-hQrv^8d{+|hD=QpM=e;Qwy$-|`GGjsFheU!8gPi;Qn5>%jhH z2^VIiCtjE}EdJs&BlC=jt%>6Qw|6G+RBiqL-^X#x^Gq3!d7jC12qDQ>hR`w3bD@NT z2$4`SByNKSiclhPj45Lw%6JJWW63=H*U@;NfBk;XeV*UF&%M9j@#@=N`+L@2d+qoB z?6uckd-(oKeh{Mol86w20qx5H!*1&zd?Wks)c*nF|2X~M1@8hd|B>&*{0uPnUM_G= zyb}V?NZ?{9Nd|F>r( z@cRFu{=dXO684c^1K(Ny6?}vJGSI&<&_5HEZp0}R|B_+sGwnf+YAz_Sy;kpB?> z8W;cfOZ?L>@$bIG|N0XD=v(}kpMU@VAHRS8SG)hat$SSTFK@|J5dW)N$Vd7t(7rY> z8fa?>iuwZdPn?QHDnsBJ09+3!aRU99{+;yy`98oD(7!(T#x(dYocfN+Y-V)&;wuYRbuQUappEM-wEB#xT zfAXAYq!I*A5QTy9Pb;ARcYmAlPuw_Yg8DKr2dM-#*dOs-#NWFs!1XZh9x(|x228*) z&;X8s?Qcl@U(>%3F80f(_+Ohq`)`3g0I?t4K@2cH5O;l2cK=+V% zgc1v|qHX)syzLB>0doxA^}DD zpBMxEp5KqsxOa$o_H%*Q8k`~^9m8YD`3hYBt|1Nox9ER6_TvhOfj0=^>fHqTw+Grs z3V4bU3A;+cz%lS6EPqKK&^+h^sSpGG$4W%1Y)IgqefXsxv{f;wS?Ca0*um6JMKbs)_*IN*0 z^${=(&_4?3pN`*M5+>mO_tE_K`w^#qiD+;g5UH#WZ1O*%fACxzZd?ba>rYc$dV78Y z-0xZdHUX>~{Eh{76Ie2M56li|p8}-6-<-c(8uWJ{q_!BuW5`X#W5lfj^nV)oo&nu2 z@|bXM@qF$F{T20(i+KuSpRNO&1-gF<> zbqUbkbAkI_^uSLF^iLp}2)>E?2gQi|Jq-Vuyg=^|(u5O+G~y-!CIsf)d5n3Az%eig z#{ZXa`bU}~w~(Oi#~JSd5bOPG{P#a`{2#=@1M%;cLG05}U^PJdiNK73_PKzO@VSV= z!1SNlpZ9D0cU=5yT-@tVhKql( z9rGF&`}({1zx-&ybrAn_8N~jb1F^4%K>X7NetV%@p!-062N44h_gWaV{qzD(;&1_H zAxOYc;qQR(->xGnZy(UU5+o6&qzLri_y6l(bxR^fbrXF5YE|Nt>Y~IcwHcuQArSlb zDX?M?`}6|P{&C58wZlOFdw~9>z_<(#=%e7SPr-AV;C7UA{TIWX z1HduB2BuZOHpEY=Op8aW3<7%!tOV#k18DyQFgu|CJwX5B;&Ey_#bZ&_pzS9G`X>bX zhk@zeAI4v73y>B_h|`=C2DA?c?LHaMJw2Z#A3K=x0sV^sljS|cr^si`rv&t`1avPC zOp4EjUl8b@6X>3S&sLC(_pl(G--Zj~MgQ;Z%lxamPV6LjCMZgYNGwX(2&BD${tp6E z1KJk=?*TIc{gX(YQiDlE|2gj*{;S)8Uk*%*o3~U zcO8PlzofS|p|5^$c*DN>F<<@5xWgXx`3EdWf0u-aKh5CWp9=-06dSQ02liu_b1e!vxR@F zCHNhb^V!e&T`}8ue>4B3DAd>dUp$|tKl5|`BtO{vZ&bc3>Sulc;)nTv<_93Y!}VhnAOoIlP_{bQAbW@GqA>jg*A5BM`Df6*NNzGiak=glPM+va>rh5w{E1b*zdT;EctpZkZu<@%Na`G4mB;f?|Mf4E~f zfA0U`4gmRo2<{*KoS)YQ{J%Nxd|4U@@%!@y(7~r|!}+n_HWMt4*`CAshrjv5zvROC zzilv($LCx)|F;ePmJ65qwqYnR_i1S$^ei?Sh;=xbx1n>m@Bm!|p`*kSE*vP=)OsS`)qZm8Kk*{DKxqmnj>^tR|5%nZewm& zx!?BUT-`lpf3ND&_1ibRZs&%&-@bR>-Q$qVqJ|i=50=-6hJ-HiTvlYcItk1_%X&Pp zZACSFD!{qz^`(|wE;%w2OJP#HyIk4_JqjQ7_!K^R@ya7Apl#R0#sAEI=9CP91hs*0 z<*qmKc1Ou!GWqz?vKa-mU4jK1$y)JIJZN1uI*QB!P6uj}LdTHkz{rnmQ>kx47PG2L zi3rJwALoxBjs%p3A-pM-v;aA{WTB5E#9pxExZf~XulH2%oN*2I-g zvd+G+(IY(#zSmtneSa|O-WAe0c=U-P?P-(I-^%__+&kmYbJ<&9dP!7cnwv=Hv)+zU&7o4RZp<3Xv0dOE z&L^X)otu|V+^Id5BvbAnK*ak_u2(1+(HmcCS@aA|{#@SCr>Sel6N|&`0`g{|ls^50 zm@^{Em$hUypYOu@M>)lI5}HQb*fZ^Bq)W{S?eWiJfvF=z(tJ%VUQZlXQ@^=VVxuaC5S4lE5}3*z0rBAeP1)rE9H@=y^Je; z5u(J4PFW*_C)sl-R6)g(@o~{DIM!{}-JJijC009Tkozu$+nog7;{F<{!1=2L&`Pas zJVaB#X&H9Yb{J8Q)TM5ka)}k&`jFI49i83Y?YwfGc|YTNeaFiNGN@*Dygg%m620QH z*5X-MPt_rUmauzuvX^jCx`?urzBfvG!^3<1SOejyTNKdrY-SI}f+tvEWEy>)HD1VE z`n>YxI>eb&3W)DE>@{k~u9_G_-Q3E& zr;%1v8X0+{qGdmE*yDP*%i-`wcbS=x_p_HmRi|E`Ke5!XBHc!*%lMuEqvUv?u#JtKF2)^o24Zhvf6v!J(|GJV-d8qnV zpB#3>Q8K28LDoQ?rwx%ITjq}|F6mk*cf9CMZgNC&5>`3cE;nns6RT15ldfJUK}lD8 z%}j>qMA0-Qu%R#i3Pc@TnA-; zSes7!GIkedHcEBMEPG)v_X9jRjS+*Ikg)Hnr9wu6nKB{|x| zd~IKp1WAZt>yd6V6%AjGi&<+c8v$wSZv(|tOZr+aS#34A2rn9s<+nZDSNQ5hK3~Nx z9xKK~?#_eg7I^j3K=O`P-BLRioc5WA{90&6P=63O64ismO+BmUV^}Xm;)12eeGv~;EqaUqVaDJ_DIC-#EYK={G zXUMW8W}QH1r)hgr3AEz1a~#ah>R(X^n**~$%vTfwL85N**_-K|>!R4?=h>XRw`wJ* zF3d!|M{Y$^JuNhzEZ6Q*QYRj@;j2ct+H?=v z`{pMET|fp{&%Y*nN*Hw@QXlc|LceUd-1C7a`(B$D^W4C)EKUHz7iGA&}0X!)7CY)D^9R=ai8>v5T8s}0-53G)3l zQ{*f?FW%n1+OkNH6@T|m3Ig+@xo^|L3#W~l?12k?1LeN^C!d-_|; z1+3Qw=ZaB>i=fdQ%o6PgOIk-<4=D#RM@dRQL1|#Nc=4nM4QHzEIfWqWn`0F;Fn+i> zfeki5UoC8$S|f-wBX4iG++nX=N6N$ns7AcJ^YXo^mm{?<`_$i_E9gWk%=JGvytop3Rfq3VLoni*h}1%p%a#DS zZyU3OvHjykmSTn)(YEX4Hjc&m>Zfz>SFD^7PM3U>aZe#Ml1TrTD#o(Isa#ow#Ayl{wr?HRJD_~N zOKLKmQ_);)WM1)LSDdwB6%p6LCJV;EOXn{1K-R8AH7_<^=Z#cxEnKaD^;IabMZ7yJ z7o9D_H#RnKfNbdLAt?D}LlY`@HVW7hxCWAo^Zm^#0zL#s>$9 zhIc#XeRN*GW%dqr2UlAMx;F#w>4vRevN&T^J$wd@7G|m|N6Da=G*V^dDGJh@A^Hc! z$Jt-LGVvZx_rmQ+dn{uvTkznPMJ2)Or+P`GVa89zc9sxvxiVI^N`$qYPfkAXx0IQ6 z>5a&k^O;d5tdf++htoL$V-EKD8iqH^0=gj3I9`%m*nhRSa!=*^V{%RBPoc$xZQg|s z8uvlGuWH2SLJm(neH^KWsw!K|qtv`M_`(>DsnNz#NNgUvM1O}O;W~!6`R+|55$65@ zcG6*!NQDZ;iKp7DVOooOcF7+-Cl7g0-r8y__m_l9Zr4@~1vvO!-&9IL5<{JI9W6yN z*NTIYxgy!j6va zK5?Zdjw4*Az?VbA@{ZNxx%Ei?vtvxOR|aD|EM{!V#ZSne*hxul8)_HW(R})JSi$j@ zsb~H(V|H*%eFnDDpZ_WkyR6U+#uMmhms;Nl=J?mPsXV{Lo>fmyb~-SpOmw!Dm~`y$ zmh8IC%*7pgr$xwRG>xB0szzVtQBLQUK|972JIWAc^h*^Z4|5-hoP8=)0;e0Y2>B3` za%Nq*H~H3bvwGs#K3#2Tk##u9{sdh!EeD=Vk}#fml4lQM8?|})84%j!1ekN=WQcrz zb9%|T;^M^~ zYcu;5(U&!%8Q@>UaJ#3tqD5m-LAI|iO@Gqe`~7Rjba5@%C0WI4c|(yaxdm5rjcz#T z(dM6~Gt`dl){cziq$Yror8S>#Odh#Wi#osMa8hvDb0O-5#!4F^W*-g1bGYU6jT%GW z=d3ULVvhWZ6kn>_{Y2&ZcFQRaBsQ&h-q6rZJ3z4N8#FC~^Ol z;wkZntIF=n+`Dh>+Iv}OuP7^PRYjfeQp=5y4=0?@7u=v6LdHh2(01+hH^1x{aE^%F zn_W7}l4!|^rT>E64GGP_xm*zg%AM`@k}?dm^Nn|dFk?}Qk4dOvSDppGK4d;r{hqI5 zPm8=>rF~=mZe`jK^PokFH2ZL!>9K_TaXok-2ajc~3YCEdBFB}1j?&nK-r;KIm3ot8 zO`b4cKJf>~&G&LY6%guCWKYzI<>%pLb4X{+&~R`KkEscD1GUhlejTZy7HigW#w^d3 zXLn^)DI8561(zguNV~d@;3rqg%{}C+JomQSLt;?$?n^ZNTuRZj^Q*+(KGm3ENnxm- zxP+8`BB7eTKBjQ-uH(tBdX|r=4!mqvYR+$VG>BX;;@lD^sEK3Lj|&#wZKHp2>a5fQ zRGqpH4TUuPWz>vDzL$=^#6eEJ6vdUL@k{4wUpaU9bj5a&v_#fg39v@WN2y{x(1!{w zANrT*Wf5jc^^tihxLrUGy=}X6Ma}4lk*bbqgu;cOcKs(Yg()ip&pPOk2bp*M>YeGH z%4tet5L@ARvFj?!%U^PxJE{d*hX-XdG(_I?aSW~aouDA4YxQGzHdk({7s*7Nsct}5 zqA_8_va>!6txyv}Xj?wMdH#@k7WO`iXY!<+P?et5$>ZS=0-BH{0v6ulc=Y(>nY_RXJ%{~3q{+%@;6|wH&)8;erOo?%;LVlTfk9CIH z$H>DHv)|M`Vo0kth^5OvZPJs%HE`jV@Ff~}$n&dfB@B!4T?|pdnh6%STDrH2jrMgU zxDwri=}Y$Q+6h^iAJw90yECroO_Us~Ymo3>Sb9 z+JzJw8{J%2)ms_d!%!O5W2k4Ou&b>jf+AG8lVXaMC)-1D=L{A5DT-JDByVPZ;VLR7 zd(i4Z*>w_+{Ja!8Gq1EV$C+8aUm5MaNn|gjRi!N{aq;$6~$-d+kVL=~w z#F~@IA~0xVS~5fl%W{AM!a}_XJ;UU7V%NFS%mNagu3ISj2Yx*T$qLs4!@mR)~yuPJI*+v_t7 z^A*W!auRD}QvDe`w1r7@g-OOJxf<*Y_i7-O)DbQjmB$*_h+m(0a4Rc?>HDH=> zvWkY7X>3RGAv)QMDP(QeGEYM>!_nP7(|0XEuYmB)jna*Fg^n)6Gg9TqvF=S_S?Q-m zzA75_!74RI-YPY^FwyC|tqMHXt>|R$y_nc@`i1o*aVHm{1V^HtEEG_?zw=kn+?KX9 zD=Z)Twa^OTQ~(w}9-dZZ6GbtlNBn`|^|%cc!;-~>%j)f%%&TsJ@w(P>eMdcOw2+4& zdo+DS1~Tgm$I4lC;#79nA0R%IFQGMhuK`r;5d^lS8Un$HQYhl@3V~ zze>L^yIy7?ytgia;iD;iUHfWJQ4fhT8&8ZIQHP08bWZ==px(5Q$qKQIFrU|*CjYv` zRAc+jD_w@990nY3*zI!_3@Rj)Pn?!q)fU#-#qFOIHPN1-tFn9GHQ~|Dl=^p97zW?> zxKo_%weKLODal(vA5_9ti1#>MM->Cu%76j#nMzpR;+F1SC% zE|=`LIbt*?pO?%Q=9HvHWjs?rU=Kep>Dq2W*7kc1bS+=|Jx)EV&-J)J(DnT~XesWB^ZHX4{u7?PH`JWm2z;DFnkVIPC;I7TvIFLda_ zxpppo96t356cd)4Gn~lNK8Es{&Ad+WlJ^E_dZZhXJyVCXq`5N~y2j)+6_6Seo7mMI zcE4=Cku9=|Ra(`nsAO(b${@08{tj~@m*nfHx{{SytHN{v=`@1Oh$mQzsDlaR>K>Ki z$DKbE)YIwFRuu*VYt)A4qfpdia)O-`3N461^79I$aRH;L@}`mml7&+U-?1UlG(_~)LQzS5Ioo^Q zH;GXw(Je+rFE4a;!vmJ2acenAdX=t$V~1CVeV(#G2gAlGVCGNO-_BaIP7{VK_#Qqd z2U*y-vyD8uQHrF<4!EL1zWyF~?{Sfd%UI9^dMlbMQ*>xbPpkHqIgvvmJ~sU%)*`Qy z)}w3A%mpb_v2L(Xp9s-zw@W&{;tmymz=~5SqugI8hV1NRKjiIQ&z!94ch%{sG!?qR z>+}_@4`g8H5+87HH&G0SR%Iag#SC6lPBcrRta&k?k0=UjSfLyutz(sET?Spiv{K^S zQW6A799|JALj(ntUVf^+2(_u6a%pKA)m-zW`(~5m*ZlY!kJ-7L3bvqE`qD8mL;Ya-dofc7kY}nc?(xZPXL)acHqO8Kai>9bxD(uhTm;E-c?0 z0`*v>tazv#LUhJuJ_P|qb@DRBWOKH4rwcgthgXtc5QUm7_DHhc2)MJerMRi;5wc`0 zJu&k zXK)PV4GxR9QQ;RwsAV2OC-T>BtG=Y)7@+GXxWU-Ty1gfAD3g8TeYJUJ$cKw)VR_^qDYufr|w<$<`?Q&h!c| z2={s?glW|$5XIfBbtaHe7gP5e`sGa_QGVF-4Rl%P^%9pNi+oYr@JD{a_9;2mh^vnx zA4h~xgrpB^Qz}cntDdNM+_};qzVh^WY$U-Dbdlg9l_;W3!H=o&NP7>P%YE%Psrlvw zFAuhKGl@Yg7vqG)QO2;o(?!W%Voh@a~H6NGmpYT!|$dnoGHw{Krnc6%H)>=u>llpy#ABT#%g-<@5@iR zy+(^HshW73ADBB9Hbkk1c-Q2V_&%#?dadT2n&ZpJqZ24j+oh)3yvP%+*Tj~sPu)3` z)~7s1tzT0SaQcStsXbMk_q@$~ML#q%7OdqSIaR|&xh^+%bB5>O#)o(lxTG2N3*%9R z3!2z!sH{I^V>Oi{^B6B`v!fzxSa0}A^X5urVMMmX1F{9GT)C<2AU-satK8hm3}b`D zy3tjL%QL>Fz<=BznpM3&X0mW*ZEiF~|IuB}P~QRX;l~$3M=L{|DoLlvqVgGz)G?LK zcSQ3DuC3l}QM-G*p?A+3yTM&|sN|%9komY7mEBpU6UK8HYijR<5AQ15yh2^jOjF9N z^14>GsM~q!N17{vc9V1zud&}r?Kg}Q6z)Flhl76#lXSs>n$&D<#@MA-# znhz~gFV+p&lx>`6E*sDN!|5P?=hA_jf(INI7Xr;o8-?lPNGGR<_*7St$ zP>GyuKdx3$6*T1`a)xuGtzrZFXm)-4`5L8|h(Jj@>ucnouxBoNo~} zx2Y2}xKX9E#px^N%h!t{w?%{-6RN)~%S$NTDWlUd)ckuhGdFVStL64S_6N5HhAP?`Z*g0B8SVq4P z{6MPY0w!t4;=}Vs%XSHJnDb@gOh)>%&#!dd&Ltm} zH4AZ2Ypl)XoT3^A&7CR=+^C9f3?%2$CnzCbOL=^k!q=r;Cr9uVeOUK!n+L}XF^6qn z&(WmPslGYB;c2W7MjYZlnO(Kl`79qx_fj|_s9?sr1O+aRJomw{kwZgbrHl@d8mc_f z9GVd|^2612`*kchW>!Ps^6;%A$Cje=X(!VC5WcLvZkseFusY0j+N}i7qd^my=5_m@ zCnww`!ov3T&>n$b+C69Cp3mx4Yo#Gmlb6vYS`gONk?-!H!tZ9<`{V{;ko87qC>D-| zUkG8!Em>X$7NQ&>VCbEi5 zHzwDNpzKSUG)CVWp6M1jZcDlrytA;Fxx6ea>?Y4%0X`3T2Wek2*E2=svE}LG>57PS z;R4p(!B6Kppd#|g=a+W8FgJtmzgDrnNd8W;Rr3g$xQ3FsWV0jfFK?+KqNe9D@&rqm zfr!apXBbr(KN$7S-#X_Z4vAD38981Ns>?iU6=~@&x5GiaxIA|k%XP?fpDg_7l|V3F zdFL)GBcxtLHCYVSF-xYLbgPxIOu~?-l`*g?u8b^=r6sk?!T`pl@Ychq2r+s+Hiu=A zhSqB`Oy96Oklfr1Qp_w1^-C_cye26}-+!=$aGbJ{ZUR~F2jR(8kL{l_P$D4}rb zXYWG1*Dbp_-t3*bGb^6NWgwL9MXfdm~0- zZ%AhBnRyX#PhRE;p=FV%J$o$_B>`=A<>2#`)`+ioEC^R+!&mCs9T{wd*Iw zT(R_fHxio*^W=Fh#8MKK=INoM)Q!G`zTjx1s^C30d2jdonTJY9o3KXcwWZ zUM7?#Efhi9-fEnJAW9~}z-t$|7vYa|LrzX3rUhyvX00pbONssdLyzQaKME97xrwR~ Xs4>e|%bN$!DnWYM`?c=uMo0cXwx2IA literal 18212 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 (n&J87E; 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 diff --git a/electron-builder.config.cjs b/electron-builder.config.cjs index 89841c218..8768fcd3d 100644 --- a/electron-builder.config.cjs +++ b/electron-builder.config.cjs @@ -3,6 +3,8 @@ const pkg = require("./package.json"); const fs = require("fs"); const path = require("path"); +const windowsShouldSign = !!process.env.SM_CODE_SIGNING_CERT_SHA1_HASH; + /** * @type {import('electron-builder').Configuration} * @see https://www.electron.build/configuration/configuration @@ -47,7 +49,6 @@ const config = { arch: ["universal", "arm64", "x64"], }, ], - icon: "build/icons.icns", category: "public.app-category.developer-tools", minimumSystemVersion: "10.15.0", mergeASARs: true, @@ -57,7 +58,6 @@ const config = { artifactName: "${name}-${platform}-${arch}-${version}.${ext}", category: "TerminalEmulator", executableName: pkg.name, - icon: "build/icons.icns", target: ["zip", "deb", "rpm", "AppImage", "pacman"], synopsis: pkg.description, description: null, @@ -73,12 +73,13 @@ const config = { afterInstall: "build/deb-postinstall.tpl", }, win: { - icon: "build/icons.icns", - publisherName: "Command Line Inc", target: ["nsis", "msi", "zip"], - certificateSubjectName: "Command Line Inc", - certificateSha1: process.env.SM_CODE_SIGNING_CERT_SHA1_HASH, - signingHashAlgorithms: ["sha256"], + signtoolOptions: windowsShouldSign && { + signingHashAlgorithms: ["sha256"], + publisherName: "Command Line Inc", + certificateSubjectName: "Command Line Inc", + certificateSha1: process.env.SM_CODE_SIGNING_CERT_SHA1_HASH, + }, }, appImage: { license: "LICENSE", From a5999aa02ae5e118e5f6c1b27747741defbd9bc7 Mon Sep 17 00:00:00 2001 From: Sylvie Crowe <107814465+oneirocosm@users.noreply.github.com> Date: Thu, 17 Oct 2024 15:19:13 -0700 Subject: [PATCH 11/34] Plot Sysinfo (#1054) Expands the cpuplot with memory plots and individual cpu plots. Also improves the styling and handling of multiple plots. --- frontend/app/block/block.tsx | 12 +- frontend/app/theme.less | 3 + frontend/app/view/cpuplot/cpuplot.less | 9 - frontend/app/view/cpuplot/cpuplot.tsx | 302 ----------- frontend/app/view/sysinfo/sysinfo.less | 33 ++ frontend/app/view/sysinfo/sysinfo.tsx | 502 ++++++++++++++++++ frontend/types/custom.d.ts | 9 + frontend/types/gotypes.d.ts | 1 + pkg/waveobj/metaconsts.go | 2 + pkg/waveobj/wtypemeta.go | 2 + pkg/wconfig/defaultconfig/defaultwidgets.json | 6 +- pkg/wlayout/wlayout.go | 2 +- pkg/wshrpc/wshremote/sysinfo.go | 10 +- pkg/wshrpc/wshserver/wshserver.go | 4 +- 14 files changed, 571 insertions(+), 326 deletions(-) delete mode 100644 frontend/app/view/cpuplot/cpuplot.less delete mode 100644 frontend/app/view/cpuplot/cpuplot.tsx create mode 100644 frontend/app/view/sysinfo/sysinfo.less create mode 100644 frontend/app/view/sysinfo/sysinfo.tsx diff --git a/frontend/app/block/block.tsx b/frontend/app/block/block.tsx index 3b5129039..98120959c 100644 --- a/frontend/app/block/block.tsx +++ b/frontend/app/block/block.tsx @@ -4,6 +4,7 @@ import { BlockComponentModel2, BlockProps } from "@/app/block/blocktypes"; import { PlotView } from "@/app/view/plotview/plotview"; import { PreviewModel, PreviewView, makePreviewModel } from "@/app/view/preview/preview"; +import { SysinfoView, SysinfoViewModel, makeSysinfoViewModel } from "@/app/view/sysinfo/sysinfo"; import { ErrorBoundary } from "@/element/errorboundary"; import { CenteredDiv } from "@/element/quickelems"; import { NodeModel, useDebouncedNodeInnerRect } from "@/layout/index"; @@ -16,7 +17,6 @@ import { import { getWaveObjectAtom, makeORef, useWaveObjectValue } from "@/store/wos"; import { focusedBlockId, getElemAsStr } from "@/util/focusutil"; import { isBlank } from "@/util/util"; -import { CpuPlotView, CpuPlotViewModel, makeCpuPlotViewModel } from "@/view/cpuplot/cpuplot"; import { HelpView, HelpViewModel, makeHelpViewModel } from "@/view/helpview/helpview"; import { QuickTipsView, QuickTipsViewModel } from "@/view/quicktipsview/quicktipsview"; import { TermViewModel, TerminalView, makeTerminalModel } from "@/view/term/term"; @@ -47,8 +47,9 @@ function makeViewModel(blockId: string, blockView: string, nodeModel: NodeModel) if (blockView === "waveai") { return makeWaveAiViewModel(blockId); } - if (blockView === "cpuplot") { - return makeCpuPlotViewModel(blockId); + if (blockView === "cpuplot" || blockView == "sysinfo") { + // "cpuplot" is for backwards compatibility with already-opened widgets + return makeSysinfoViewModel(blockId, blockView); } if (blockView === "help") { return makeHelpViewModel(blockId, nodeModel); @@ -89,8 +90,9 @@ function getViewElem( if (blockView === "waveai") { return ; } - if (blockView === "cpuplot") { - return ; + if (blockView === "cpuplot" || blockView === "sysinfo") { + // "cpuplot" is for backwards compatibility with already opened widgets + return ; } if (blockView == "help") { return ; diff --git a/frontend/app/theme.less b/frontend/app/theme.less index 4c33e6c3a..1904523a7 100644 --- a/frontend/app/theme.less +++ b/frontend/app/theme.less @@ -106,6 +106,9 @@ --conn-icon-color-7: #dbde52; --conn-icon-color-8: #58c142; + --sysinfo-cpu-color: #58c142; + --sysinfo-mem-color: #53b4ea; + --bulb-color: rgb(255, 221, 51); // term colors (16 + 6) form the base terminal theme diff --git a/frontend/app/view/cpuplot/cpuplot.less b/frontend/app/view/cpuplot/cpuplot.less deleted file mode 100644 index 4f950dc63..000000000 --- a/frontend/app/view/cpuplot/cpuplot.less +++ /dev/null @@ -1,9 +0,0 @@ -// Copyright 2024, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -.plot-view { - display: flex; - justify-content: center; - align-items: stretch; - width: 100%; -} diff --git a/frontend/app/view/cpuplot/cpuplot.tsx b/frontend/app/view/cpuplot/cpuplot.tsx deleted file mode 100644 index e773f9a3a..000000000 --- a/frontend/app/view/cpuplot/cpuplot.tsx +++ /dev/null @@ -1,302 +0,0 @@ -// Copyright 2024, Command Line Inc. -// SPDX-License-Identifier: Apache-2.0 - -import { getConnStatusAtom, globalStore, WOS } from "@/store/global"; -import * as util from "@/util/util"; -import * as Plot from "@observablehq/plot"; -import dayjs from "dayjs"; -import * as htl from "htl"; -import * as jotai from "jotai"; -import * as React from "react"; - -import { useDimensionsWithExistingRef } from "@/app/hook/useDimensions"; -import { waveEventSubscribe } from "@/app/store/wps"; -import { RpcApi } from "@/app/store/wshclientapi"; -import { WindowRpcClient } from "@/app/store/wshrpcutil"; -import "./cpuplot.less"; - -const DefaultNumPoints = 120; - -type DataItem = { - ts: number; - [k: string]: number; -}; - -const SysInfoMetricNames = { - cpu: "CPU %", - "mem:total": "Memory Total", - "mem:used": "Memory Used", - "mem:free": "Memory Free", - "mem:available": "Memory Available", -}; -for (let i = 0; i < 32; i++) { - SysInfoMetricNames[`cpu:${i}`] = `CPU[${i}] %`; -} - -function convertWaveEventToDataItem(event: WaveEvent): DataItem { - const eventData: TimeSeriesData = event.data; - if (eventData == null || eventData.ts == null || eventData.values == null) { - return null; - } - const dataItem = { ts: eventData.ts }; - for (const key in eventData.values) { - dataItem[key] = eventData.values[key]; - } - return dataItem; -} - -class CpuPlotViewModel { - viewType: string; - blockAtom: jotai.Atom; - termMode: jotai.Atom; - htmlElemFocusRef: React.RefObject; - blockId: string; - viewIcon: jotai.Atom; - viewText: jotai.Atom; - viewName: jotai.Atom; - dataAtom: jotai.PrimitiveAtom>; - addDataAtom: jotai.WritableAtom; - incrementCount: jotai.WritableAtom>; - loadingAtom: jotai.PrimitiveAtom; - numPoints: jotai.Atom; - metrics: jotai.Atom; - connection: jotai.Atom; - manageConnection: jotai.Atom; - connStatus: jotai.Atom; - - constructor(blockId: string) { - this.viewType = "cpuplot"; - this.blockId = blockId; - this.blockAtom = WOS.getWaveObjectAtom(`block:${blockId}`); - this.addDataAtom = jotai.atom(null, (get, set, points) => { - const targetLen = get(this.numPoints) + 1; - let data = get(this.dataAtom); - try { - if (data.length > targetLen) { - data = data.slice(data.length - targetLen); - } - if (data.length < targetLen) { - const defaultData = this.getDefaultData(); - data = [...defaultData.slice(defaultData.length - targetLen + data.length), ...data]; - } - const newData = [...data.slice(points.length), ...points]; - set(this.dataAtom, newData); - } catch (e) { - console.log("Error adding data to cpuplot", e); - } - }); - this.manageConnection = jotai.atom(true); - this.loadingAtom = jotai.atom(true); - this.numPoints = jotai.atom((get) => { - const blockData = get(this.blockAtom); - const metaNumPoints = blockData?.meta?.["graph:numpoints"]; - if (metaNumPoints == null || metaNumPoints <= 0) { - return DefaultNumPoints; - } - return metaNumPoints; - }); - this.metrics = jotai.atom((get) => { - const blockData = get(this.blockAtom); - const metrics = blockData?.meta?.["graph:metrics"]; - if (metrics == null || !Array.isArray(metrics)) { - return ["cpu"]; - } - return metrics; - }); - this.viewIcon = jotai.atom((get) => { - return "chart-line"; // should not be hardcoded - }); - this.viewName = jotai.atom((get) => { - return "CPU %"; // should not be hardcoded - }); - this.incrementCount = jotai.atom(null, async (get, set) => { - const meta = get(this.blockAtom).meta; - const count = meta.count ?? 0; - await RpcApi.SetMetaCommand(WindowRpcClient, { - oref: WOS.makeORef("block", this.blockId), - meta: { count: count + 1 }, - }); - }); - this.connection = jotai.atom((get) => { - const blockData = get(this.blockAtom); - const connValue = blockData?.meta?.connection; - if (util.isBlank(connValue)) { - return "local"; - } - return connValue; - }); - this.dataAtom = jotai.atom(this.getDefaultData()); - this.loadInitialData(); - this.connStatus = jotai.atom((get) => { - const blockData = get(this.blockAtom); - const connName = blockData?.meta?.connection; - const connAtom = getConnStatusAtom(connName); - return get(connAtom); - }); - } - - async loadInitialData() { - globalStore.set(this.loadingAtom, true); - try { - const numPoints = globalStore.get(this.numPoints); - const connName = globalStore.get(this.connection); - const initialData = await RpcApi.EventReadHistoryCommand(WindowRpcClient, { - event: "sysinfo", - scope: connName, - maxitems: numPoints, - }); - if (initialData == null) { - return; - } - const newData = this.getDefaultData(); - const initialDataItems: DataItem[] = initialData.map(convertWaveEventToDataItem); - // splice the initial data into the default data (replacing the newest points) - newData.splice(newData.length - initialDataItems.length, initialDataItems.length, ...initialDataItems); - globalStore.set(this.addDataAtom, newData); - } catch (e) { - console.log("Error loading initial data for cpuplot", e); - } finally { - globalStore.set(this.loadingAtom, false); - } - } - - getDefaultData(): DataItem[] { - // set it back one to avoid backwards line being possible - const numPoints = globalStore.get(this.numPoints); - const currentTime = Date.now() - 1000; - const points: DataItem[] = []; - for (let i = numPoints; i > -1; i--) { - points.push({ ts: currentTime - i * 1000 }); - } - return points; - } -} - -function makeCpuPlotViewModel(blockId: string): CpuPlotViewModel { - const cpuPlotViewModel = new CpuPlotViewModel(blockId); - return cpuPlotViewModel; -} - -const plotColors = ["#58C142", "#FFC107", "#FF5722", "#2196F3", "#9C27B0", "#00BCD4", "#FFEB3B", "#795548"]; - -type CpuPlotViewProps = { - blockId: string; - model: CpuPlotViewModel; -}; - -function CpuPlotView({ model, blockId }: CpuPlotViewProps) { - const connName = jotai.useAtomValue(model.connection); - const lastConnName = React.useRef(connName); - const connStatus = jotai.useAtomValue(model.connStatus); - const addPlotData = jotai.useSetAtom(model.addDataAtom); - const loading = jotai.useAtomValue(model.loadingAtom); - - React.useEffect(() => { - if (connStatus?.status != "connected") { - return; - } - if (lastConnName.current !== connName) { - lastConnName.current = connName; - model.loadInitialData(); - } - }, [connStatus.status, connName]); - React.useEffect(() => { - const unsubFn = waveEventSubscribe({ - eventType: "sysinfo", - scope: connName, - handler: (event) => { - const loading = globalStore.get(model.loadingAtom); - if (loading) { - return; - } - const dataItem = convertWaveEventToDataItem(event); - addPlotData([dataItem]); - }, - }); - console.log("subscribe to sysinfo", connName); - return () => { - unsubFn(); - }; - }, [connName]); - if (connStatus?.status != "connected") { - return null; - } - if (loading) { - return null; - } - return ; -} - -const CpuPlotViewInner = React.memo(({ model }: CpuPlotViewProps) => { - const containerRef = React.useRef(); - const plotData = jotai.useAtomValue(model.dataAtom); - const domRect = useDimensionsWithExistingRef(containerRef, 30); - const parentHeight = domRect?.height ?? 0; - const parentWidth = domRect?.width ?? 0; - const yvals = jotai.useAtomValue(model.metrics); - - React.useEffect(() => { - const marks: Plot.Markish[] = []; - marks.push( - () => htl.svg` - - - - - ` - ); - if (yvals.length == 0) { - // nothing - } else if (yvals.length == 1) { - marks.push( - Plot.lineY(plotData, { - stroke: plotColors[0], - strokeWidth: 2, - x: "ts", - y: yvals[0], - }) - ); - marks.push( - Plot.areaY(plotData, { - fill: "url(#gradient)", - x: "ts", - y: yvals[0], - }) - ); - } else { - let idx = 0; - for (const yval of yvals) { - marks.push( - Plot.lineY(plotData, { - stroke: plotColors[idx % plotColors.length], - strokeWidth: 1, - x: "ts", - y: yval, - }) - ); - idx++; - } - } - const plot = Plot.plot({ - x: { grid: true, label: "time", tickFormat: (d) => `${dayjs.unix(d / 1000).format("HH:mm:ss")}` }, - y: { label: "%", domain: [0, 100] }, - width: parentWidth, - height: parentHeight, - marks: marks, - }); - - if (plot !== undefined) { - containerRef.current.append(plot); - } - - return () => { - if (plot !== undefined) { - plot.remove(); - } - }; - }, [plotData, parentHeight, parentWidth]); - - return
; -}); - -export { CpuPlotView, CpuPlotViewModel, makeCpuPlotViewModel }; diff --git a/frontend/app/view/sysinfo/sysinfo.less b/frontend/app/view/sysinfo/sysinfo.less new file mode 100644 index 000000000..2f36f915f --- /dev/null +++ b/frontend/app/view/sysinfo/sysinfo.less @@ -0,0 +1,33 @@ +// Copyright 2024, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +.scrollable { + flex-flow: column nowrap; + flex-grow: 1; + margin-bottom: 0; + overflow-y: auto; + .sysinfo-view { + width: 100%; + height: 100%; + display: grid; + grid-template-rows: repeat(auto-fit, minmax(100px, 1fr)); + gap: 10px; + + &.two-columns { + grid-template-columns: 1fr 1fr; + } + + .sysinfo-plot-content { + min-height: 100px; + svg { + [aria-label="tip"] { + g { + path { + color: var(--border-color); + } + } + } + } + } + } +} diff --git a/frontend/app/view/sysinfo/sysinfo.tsx b/frontend/app/view/sysinfo/sysinfo.tsx new file mode 100644 index 000000000..6c15cff47 --- /dev/null +++ b/frontend/app/view/sysinfo/sysinfo.tsx @@ -0,0 +1,502 @@ +// Copyright 2024, Command Line Inc. +// SPDX-License-Identifier: Apache-2.0 + +import { getConnStatusAtom, globalStore, WOS } from "@/store/global"; +import * as util from "@/util/util"; +import * as Plot from "@observablehq/plot"; +import clsx from "clsx"; +import dayjs from "dayjs"; +import * as htl from "htl"; +import * as jotai from "jotai"; +import * as React from "react"; + +import { useDimensionsWithExistingRef } from "@/app/hook/useDimensions"; +import { waveEventSubscribe } from "@/app/store/wps"; +import { RpcApi } from "@/app/store/wshclientapi"; +import { WindowRpcClient } from "@/app/store/wshrpcutil"; +import { atoms } from "@/store/global"; +import { OverlayScrollbarsComponent, OverlayScrollbarsComponentRef } from "overlayscrollbars-react"; +import "./sysinfo.less"; + +const DefaultNumPoints = 120; + +type DataItem = { + ts: number; + [k: string]: number; +}; + +function defaultCpuMeta(name: string): TimeSeriesMeta { + return { + name: name, + label: "%", + miny: 0, + maxy: 100, + color: "var(--sysinfo-cpu-color)", + decimalPlaces: 0, + }; +} + +function defaultMemMeta(name: string, maxY: string): TimeSeriesMeta { + return { + name: name, + label: "GB", + miny: 0, + maxy: maxY, + color: "var(--sysinfo-mem-color)", + decimalPlaces: 1, + }; +} + +const PlotTypes: Object = { + CPU: function (dataItem: DataItem): Array { + return ["cpu"]; + }, + Mem: function (dataItem: DataItem): Array { + return ["mem:used"]; + }, + "CPU + Mem": function (dataItem: DataItem): Array { + return ["cpu", "mem:used"]; + }, + "All CPU": function (dataItem: DataItem): Array { + return Object.keys(dataItem) + .filter((item) => item.startsWith("cpu") && item != "cpu") + .sort((a, b) => { + const valA = parseInt(a.replace("cpu:", "")); + const valB = parseInt(b.replace("cpu:", "")); + return valA - valB; + }); + }, +}; + +const DefaultPlotMeta = { + cpu: defaultCpuMeta("CPU %"), + "mem:total": defaultMemMeta("Memory Total", "mem:total"), + "mem:used": defaultMemMeta("Memory Used", "mem:total"), + "mem:free": defaultMemMeta("Memory Free", "mem:total"), + "mem:available": defaultMemMeta("Memory Available", "mem:total"), +}; +for (let i = 0; i < 32; i++) { + DefaultPlotMeta[`cpu:${i}`] = defaultCpuMeta(`Core ${i}`); +} + +function convertWaveEventToDataItem(event: WaveEvent): DataItem { + const eventData: TimeSeriesData = event.data; + if (eventData == null || eventData.ts == null || eventData.values == null) { + return null; + } + const dataItem = { ts: eventData.ts }; + for (const key in eventData.values) { + dataItem[key] = eventData.values[key]; + } + return dataItem; +} + +class SysinfoViewModel { + viewType: string; + blockAtom: jotai.Atom; + termMode: jotai.Atom; + htmlElemFocusRef: React.RefObject; + blockId: string; + viewIcon: jotai.Atom; + viewText: jotai.Atom; + viewName: jotai.Atom; + dataAtom: jotai.PrimitiveAtom>; + addDataAtom: jotai.WritableAtom; + incrementCount: jotai.WritableAtom>; + loadingAtom: jotai.PrimitiveAtom; + numPoints: jotai.Atom; + metrics: jotai.Atom; + connection: jotai.Atom; + manageConnection: jotai.Atom; + connStatus: jotai.Atom; + plotMetaAtom: jotai.PrimitiveAtom>; + endIconButtons: jotai.Atom; + plotTypeSelectedAtom: jotai.Atom; + + constructor(blockId: string, viewType: string) { + this.viewType = viewType; + this.blockId = blockId; + this.blockAtom = WOS.getWaveObjectAtom(`block:${blockId}`); + this.addDataAtom = jotai.atom(null, (get, set, points) => { + const targetLen = get(this.numPoints) + 1; + let data = get(this.dataAtom); + try { + if (data.length > targetLen) { + data = data.slice(data.length - targetLen); + } + if (data.length < targetLen) { + const defaultData = this.getDefaultData(); + data = [...defaultData.slice(defaultData.length - targetLen + data.length), ...data]; + } + const newData = [...data.slice(points.length), ...points]; + set(this.dataAtom, newData); + } catch (e) { + console.log("Error adding data to sysinfo", e); + } + }); + this.plotMetaAtom = jotai.atom(new Map(Object.entries(DefaultPlotMeta))); + this.manageConnection = jotai.atom(true); + this.loadingAtom = jotai.atom(true); + this.numPoints = jotai.atom((get) => { + const blockData = get(this.blockAtom); + const metaNumPoints = blockData?.meta?.["graph:numpoints"]; + if (metaNumPoints == null || metaNumPoints <= 0) { + return DefaultNumPoints; + } + return metaNumPoints; + }); + this.metrics = jotai.atom((get) => { + let plotType = get(this.plotTypeSelectedAtom); + const plotData = get(this.dataAtom); + try { + const metrics = PlotTypes[plotType](plotData[plotData.length - 1]); + if (metrics == null || !Array.isArray(metrics)) { + return ["cpu"]; + } + return metrics; + } catch (e) { + return ["cpu"]; + } + }); + this.plotTypeSelectedAtom = jotai.atom((get) => { + const blockData = get(this.blockAtom); + const plotType = blockData?.meta?.["sysinfo:type"]; + if (plotType == null || typeof plotType != "string") { + return "CPU"; + } + return plotType; + }); + this.viewIcon = jotai.atom((get) => { + return "chart-line"; // should not be hardcoded + }); + this.viewName = jotai.atom((get) => { + return get(this.plotTypeSelectedAtom); + }); + this.incrementCount = jotai.atom(null, async (get, set) => { + const meta = get(this.blockAtom).meta; + const count = meta.count ?? 0; + await RpcApi.SetMetaCommand(WindowRpcClient, { + oref: WOS.makeORef("block", this.blockId), + meta: { count: count + 1 }, + }); + }); + this.connection = jotai.atom((get) => { + const blockData = get(this.blockAtom); + const connValue = blockData?.meta?.connection; + if (util.isBlank(connValue)) { + return "local"; + } + return connValue; + }); + this.dataAtom = jotai.atom(this.getDefaultData()); + this.loadInitialData(); + this.connStatus = jotai.atom((get) => { + const blockData = get(this.blockAtom); + const connName = blockData?.meta?.connection; + const connAtom = getConnStatusAtom(connName); + return get(connAtom); + }); + } + + async loadInitialData() { + globalStore.set(this.loadingAtom, true); + try { + const numPoints = globalStore.get(this.numPoints); + const connName = globalStore.get(this.connection); + const initialData = await RpcApi.EventReadHistoryCommand(WindowRpcClient, { + event: "sysinfo", + scope: connName, + maxitems: numPoints, + }); + if (initialData == null) { + return; + } + const newData = this.getDefaultData(); + const initialDataItems: DataItem[] = initialData.map(convertWaveEventToDataItem); + // splice the initial data into the default data (replacing the newest points) + newData.splice(newData.length - initialDataItems.length, initialDataItems.length, ...initialDataItems); + globalStore.set(this.addDataAtom, newData); + } catch (e) { + console.log("Error loading initial data for sysinfo", e); + } finally { + globalStore.set(this.loadingAtom, false); + } + } + + getSettingsMenuItems(): ContextMenuItem[] { + const fullConfig = globalStore.get(atoms.fullConfigAtom); + const termThemes = fullConfig?.termthemes ?? {}; + const termThemeKeys = Object.keys(termThemes); + const plotData = globalStore.get(this.dataAtom); + + termThemeKeys.sort((a, b) => { + return termThemes[a]["display:order"] - termThemes[b]["display:order"]; + }); + const fullMenu: ContextMenuItem[] = []; + let submenu: ContextMenuItem[]; + if (plotData.length == 0) { + submenu = []; + } else { + submenu = Object.keys(PlotTypes).map((plotType) => { + const dataTypes = PlotTypes[plotType](plotData[plotData.length - 1]); + const currentlySelected = globalStore.get(this.plotTypeSelectedAtom); + const menuItem: ContextMenuItem = { + label: plotType, + type: "radio", + checked: currentlySelected == plotType, + click: async () => { + await RpcApi.SetMetaCommand(WindowRpcClient, { + oref: WOS.makeORef("block", this.blockId), + meta: { "graph:metrics": dataTypes, "sysinfo:type": plotType }, + }); + }, + }; + return menuItem; + }); + } + + fullMenu.push({ + label: "Plot Type", + submenu: submenu, + }); + fullMenu.push({ type: "separator" }); + return fullMenu; + } + + getDefaultData(): DataItem[] { + // set it back one to avoid backwards line being possible + const numPoints = globalStore.get(this.numPoints); + const currentTime = Date.now() - 1000; + const points: DataItem[] = []; + for (let i = numPoints; i > -1; i--) { + points.push({ ts: currentTime - i * 1000 }); + } + return points; + } +} + +function makeSysinfoViewModel(blockId: string, viewType: string): SysinfoViewModel { + const sysinfoViewModel = new SysinfoViewModel(blockId, viewType); + return sysinfoViewModel; +} + +const plotColors = ["#58C142", "#FFC107", "#FF5722", "#2196F3", "#9C27B0", "#00BCD4", "#FFEB3B", "#795548"]; + +type SysinfoViewProps = { + blockId: string; + model: SysinfoViewModel; +}; + +function resolveDomainBound(value: number | string, dataItem: DataItem): number | undefined { + if (typeof value == "number") { + return value; + } else if (typeof value == "string") { + return dataItem?.[value]; + } else { + return undefined; + } +} + +function SysinfoView({ model, blockId }: SysinfoViewProps) { + const connName = jotai.useAtomValue(model.connection); + const lastConnName = React.useRef(connName); + const connStatus = jotai.useAtomValue(model.connStatus); + const addPlotData = jotai.useSetAtom(model.addDataAtom); + const loading = jotai.useAtomValue(model.loadingAtom); + + React.useEffect(() => { + if (connStatus?.status != "connected") { + return; + } + if (lastConnName.current !== connName) { + lastConnName.current = connName; + model.loadInitialData(); + } + }, [connStatus.status, connName]); + React.useEffect(() => { + const unsubFn = waveEventSubscribe({ + eventType: "sysinfo", + scope: connName, + handler: (event) => { + const loading = globalStore.get(model.loadingAtom); + if (loading) { + return; + } + const dataItem = convertWaveEventToDataItem(event); + addPlotData([dataItem]); + }, + }); + console.log("subscribe to sysinfo", connName); + return () => { + unsubFn(); + }; + }, [connName]); + if (connStatus?.status != "connected") { + return null; + } + if (loading) { + return null; + } + return ; +} + +type SingleLinePlotProps = { + plotData: Array; + yval: string; + yvalMeta: TimeSeriesMeta; + blockId: string; + defaultColor: string; + title?: boolean; + sparkline?: boolean; +}; + +function SingleLinePlot({ + plotData, + yval, + yvalMeta, + blockId, + defaultColor, + title = false, + sparkline = false, +}: SingleLinePlotProps) { + const containerRef = React.useRef(); + const domRect = useDimensionsWithExistingRef(containerRef, 300); + const plotHeight = domRect?.height ?? 0; + const plotWidth = domRect?.width ?? 0; + const marks: Plot.Markish[] = []; + let decimalPlaces = yvalMeta?.decimalPlaces ?? 0; + let color = yvalMeta?.color; + if (!color) { + color = defaultColor; + } + marks.push( + () => htl.svg` + + + + + ` + ); + + marks.push( + Plot.lineY(plotData, { + stroke: color, + strokeWidth: 2, + x: "ts", + y: yval, + }) + ); + + // only add the gradient for single items + marks.push( + Plot.areaY(plotData, { + fill: `url(#gradient-${blockId}-${yval})`, + x: "ts", + y: yval, + }) + ); + if (title) { + marks.push( + Plot.text([yvalMeta.name], { + frameAnchor: "top-left", + dx: 4, + fill: "var(--grey-text-color)", + }) + ); + } + const labelY = yvalMeta?.label ?? "?"; + marks.push( + Plot.ruleX( + plotData, + Plot.pointerX({ x: "ts", py: yval, stroke: "var(--grey-text-color)", strokeWidth: 1, strokeDasharray: 2 }) + ) + ); + marks.push( + Plot.ruleY( + plotData, + Plot.pointerX({ px: "ts", y: yval, stroke: "var(--grey-text-color)", strokeWidth: 1, strokeDasharray: 2 }) + ) + ); + marks.push( + Plot.tip( + plotData, + Plot.pointerX({ + x: "ts", + y: yval, + fill: "var(--main-bg-color)", + anchor: "middle", + dy: -30, + title: (d) => + `${dayjs.unix(d.ts / 1000).format("HH:mm:ss")} ${Number(d[yval]).toFixed(decimalPlaces)}${labelY}`, + textPadding: 3, + }) + ) + ); + marks.push( + Plot.dot( + plotData, + Plot.pointerX({ x: "ts", y: yval, fill: color, r: 3, stroke: "var(--main-text-color)", strokeWidth: 1 }) + ) + ); + let maxY = resolveDomainBound(yvalMeta?.maxy, plotData[plotData.length - 1]) ?? 100; + let minY = resolveDomainBound(yvalMeta?.miny, plotData[plotData.length - 1]) ?? 0; + const plot = Plot.plot({ + axis: !sparkline, + x: { + grid: true, + label: "time", + tickFormat: (d) => `${dayjs.unix(d / 1000).format("HH:mm:ss")}`, + }, + y: { label: labelY, domain: [minY, maxY] }, + width: plotWidth, + height: plotHeight, + marks: marks, + }); + + React.useEffect(() => { + containerRef.current.append(plot); + + return () => { + plot.remove(); + }; + }, [plot, plotWidth, plotHeight]); + + return
; +} + +const SysinfoViewInner = React.memo(({ model }: SysinfoViewProps) => { + const plotData = jotai.useAtomValue(model.dataAtom); + const yvals = jotai.useAtomValue(model.metrics); + const plotMeta = jotai.useAtomValue(model.plotMetaAtom); + const osRef = React.useRef(); + let title = false; + let cols2 = false; + if (yvals.length > 1) { + title = true; + } + if (yvals.length > 2) { + cols2 = true; + } + + return ( + +
+ {yvals.map((yval, idx) => { + return ( + + ); + })} +
+
+ ); +}); + +export { makeSysinfoViewModel, SysinfoView, SysinfoViewModel }; diff --git a/frontend/types/custom.d.ts b/frontend/types/custom.d.ts index eee4dae5c..a33feb5fb 100644 --- a/frontend/types/custom.d.ts +++ b/frontend/types/custom.d.ts @@ -332,6 +332,15 @@ declare global { command: string; msgFn: (msg: RpcMessage) => void; }; + + type TimeSeriesMeta = { + name?: string; + color?: string; + label?: string; + maxy?: string | number; + miny?: string | number; + decimalPlaces?: number; + }; } export {}; diff --git a/frontend/types/gotypes.d.ts b/frontend/types/gotypes.d.ts index a3e6eba1b..fcbe84680 100644 --- a/frontend/types/gotypes.d.ts +++ b/frontend/types/gotypes.d.ts @@ -306,6 +306,7 @@ declare global { "graph:*"?: boolean; "graph:numpoints"?: number; "graph:metrics"?: string[]; + "sysinfo:type"?: string; "bg:*"?: boolean; bg?: string; "bg:opacity"?: number; diff --git a/pkg/waveobj/metaconsts.go b/pkg/waveobj/metaconsts.go index 41fdce4dd..e904c3def 100644 --- a/pkg/waveobj/metaconsts.go +++ b/pkg/waveobj/metaconsts.go @@ -64,6 +64,8 @@ const ( MetaKey_GraphNumPoints = "graph:numpoints" MetaKey_GraphMetrics = "graph:metrics" + MetaKey_SysinfoType = "sysinfo:type" + MetaKey_BgClear = "bg:*" MetaKey_Bg = "bg" MetaKey_BgOpacity = "bg:opacity" diff --git a/pkg/waveobj/wtypemeta.go b/pkg/waveobj/wtypemeta.go index 2b52e897a..93c1919f0 100644 --- a/pkg/waveobj/wtypemeta.go +++ b/pkg/waveobj/wtypemeta.go @@ -64,6 +64,8 @@ type MetaTSType struct { GraphNumPoints int `json:"graph:numpoints,omitempty"` GraphMetrics []string `json:"graph:metrics,omitempty"` + SysinfoType string `json:"sysinfo:type,omitempty"` + // for tabs BgClear bool `json:"bg:*,omitempty"` Bg string `json:"bg,omitempty"` diff --git a/pkg/wconfig/defaultconfig/defaultwidgets.json b/pkg/wconfig/defaultconfig/defaultwidgets.json index 5711e1f7b..b59e5c59a 100644 --- a/pkg/wconfig/defaultconfig/defaultwidgets.json +++ b/pkg/wconfig/defaultconfig/defaultwidgets.json @@ -41,13 +41,13 @@ } } }, - "defwidget@cpuplot": { + "defwidget@sysinfo": { "display:order": 5, "icon": "chart-line", - "label": "cpu", + "label": "sysinfo", "blockdef": { "meta": { - "view": "cpuplot" + "view": "sysinfo" } } } diff --git a/pkg/wlayout/wlayout.go b/pkg/wlayout/wlayout.go index 3f8bfdbd1..96885d17b 100644 --- a/pkg/wlayout/wlayout.go +++ b/pkg/wlayout/wlayout.go @@ -38,7 +38,7 @@ func GetStarterLayout() PortableLayout { }, Focused: true}, {IndexArr: []int{1}, BlockDef: &waveobj.BlockDef{ Meta: waveobj.MetaMapType{ - waveobj.MetaKey_View: "cpuplot", + waveobj.MetaKey_View: "sysinfo", }, }}, {IndexArr: []int{1, 1}, BlockDef: &waveobj.BlockDef{ diff --git a/pkg/wshrpc/wshremote/sysinfo.go b/pkg/wshrpc/wshremote/sysinfo.go index eba8290fb..045e5b5d1 100644 --- a/pkg/wshrpc/wshremote/sysinfo.go +++ b/pkg/wshrpc/wshremote/sysinfo.go @@ -16,6 +16,8 @@ import ( "github.com/wavetermdev/waveterm/pkg/wshutil" ) +const BYTES_PER_GB = 1073741824 + func getCpuData(values map[string]float64) { percentArr, err := cpu.Percent(0, false) if err != nil { @@ -38,10 +40,10 @@ func getMemData(values map[string]float64) { if err != nil { return } - values["mem:total"] = float64(memData.Total) - values["mem:available"] = float64(memData.Available) - values["mem:used"] = float64(memData.Used) - values["mem:free"] = float64(memData.Free) + values["mem:total"] = float64(memData.Total) / BYTES_PER_GB + values["mem:available"] = float64(memData.Available) / BYTES_PER_GB + values["mem:used"] = float64(memData.Used) / BYTES_PER_GB + values["mem:free"] = float64(memData.Free) / BYTES_PER_GB } func generateSingleServerData(client *wshutil.WshRpc, connName string) { diff --git a/pkg/wshrpc/wshserver/wshserver.go b/pkg/wshrpc/wshserver/wshserver.go index baed1bd3e..fe093250f 100644 --- a/pkg/wshrpc/wshserver/wshserver.go +++ b/pkg/wshrpc/wshserver/wshserver.go @@ -83,7 +83,7 @@ func MakePlotData(ctx context.Context, blockId string) error { return err } viewName := block.Meta.GetString(waveobj.MetaKey_View, "") - if viewName != "cpuplot" { + if viewName != "cpuplot" && viewName != "sysinfo" { return fmt.Errorf("invalid view type: %s", viewName) } return filestore.WFS.MakeFile(ctx, blockId, "cpuplotdata", nil, filestore.FileOptsType{}) @@ -95,7 +95,7 @@ func SavePlotData(ctx context.Context, blockId string, history string) error { return err } viewName := block.Meta.GetString(waveobj.MetaKey_View, "") - if viewName != "cpuplot" { + if viewName != "cpuplot" && viewName != "sysinfo" { return fmt.Errorf("invalid view type: %s", viewName) } // todo: interpret the data being passed From f77b42d70cf0f19d3fcfeabe3b1021d0ec67303c Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 17 Oct 2024 15:38:42 -0700 Subject: [PATCH 12/34] Fix bug where helpview fails to load sub-pages after idle (#1056) closes #1048 --- frontend/app/view/helpview/helpview.tsx | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/app/view/helpview/helpview.tsx b/frontend/app/view/helpview/helpview.tsx index ae4176101..b7f0e6146 100644 --- a/frontend/app/view/helpview/helpview.tsx +++ b/frontend/app/view/helpview/helpview.tsx @@ -50,12 +50,16 @@ function makeHelpViewModel(blockId: string, nodeModel: NodeModel) { function HelpView({ model }: { model: HelpViewModel }) { const homepageUrl = useAtomValue(model.homepageUrl); + const url = useAtomValue(model.url); + + // Effect to update the docsite base url when the app restarts, since the webserver port is dynamic useEffect( () => fireAndForget(async () => { const curDocsiteUrl = getApi().getDocsiteUrl(); if (curDocsiteUrl !== homepageUrl) { await model.setHomepageUrl(curDocsiteUrl, "block"); + model.loadUrl(url.replace(homepageUrl, curDocsiteUrl), "new-base-url"); } }), [] From 5d8070b9d8695c40aef868f1b0bfa10ee1c0a78b Mon Sep 17 00:00:00 2001 From: "wave-builder[bot]" <181805596+wave-builder[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 22:39:28 +0000 Subject: [PATCH 13/34] chore: bump package version to 0.8.12-beta.1 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 1eaded3c8..3cf865f1d 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "productName": "Wave", "description": "Open-Source AI-Native Terminal Built for Seamless Workflows", "license": "Apache-2.0", - "version": "0.8.12-beta.0", + "version": "0.8.12-beta.1", "homepage": "https://waveterm.dev", "build": { "appId": "dev.commandline.waveterm" From 70811cb73000f74d8cc48b0d7783e9ff144ceb2a Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Thu, 17 Oct 2024 16:03:17 -0700 Subject: [PATCH 14/34] Add helpview callback to resolve failed webview loads (#1057) --- frontend/app/view/helpview/helpview.tsx | 30 ++++++++++++++++--------- frontend/app/view/webview/webview.tsx | 7 +++++- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/frontend/app/view/helpview/helpview.tsx b/frontend/app/view/helpview/helpview.tsx index b7f0e6146..5f45c45b7 100644 --- a/frontend/app/view/helpview/helpview.tsx +++ b/frontend/app/view/helpview/helpview.tsx @@ -6,7 +6,7 @@ import { WebView, WebViewModel } from "@/app/view/webview/webview"; import { NodeModel } from "@/layout/index"; import { fireAndForget } from "@/util/util"; import { atom, useAtomValue } from "jotai"; -import { useEffect } from "react"; +import { useCallback } from "react"; import "./helpview.less"; class HelpViewModel extends WebViewModel { @@ -48,25 +48,35 @@ function makeHelpViewModel(blockId: string, nodeModel: NodeModel) { return new HelpViewModel(blockId, nodeModel); } +const baseUrlRegex = /http[s]?:\/\/([^:\/])+(:\d+)?/; + function HelpView({ model }: { model: HelpViewModel }) { const homepageUrl = useAtomValue(model.homepageUrl); - const url = useAtomValue(model.url); // Effect to update the docsite base url when the app restarts, since the webserver port is dynamic - useEffect( - () => + const onFailLoad = useCallback( + (url: string) => fireAndForget(async () => { - const curDocsiteUrl = getApi().getDocsiteUrl(); - if (curDocsiteUrl !== homepageUrl) { - await model.setHomepageUrl(curDocsiteUrl, "block"); - model.loadUrl(url.replace(homepageUrl, curDocsiteUrl), "new-base-url"); + const newDocsiteUrl = getApi().getDocsiteUrl(); + + // Correct the homepage URL, if necessary + if (newDocsiteUrl !== homepageUrl) { + await model.setHomepageUrl(newDocsiteUrl, "block"); + } + + // Correct the base URL of the current page, if necessary + const newBaseUrl = baseUrlRegex.exec(newDocsiteUrl)?.[0]; + const curBaseUrl = baseUrlRegex.exec(url)?.[0]; + console.log("fix-docsite-url", url, newDocsiteUrl, homepageUrl, curBaseUrl, newBaseUrl); + if (curBaseUrl && newBaseUrl && curBaseUrl !== newBaseUrl) { + model.loadUrl(url.replace(curBaseUrl, newBaseUrl), "fix-fail-load"); } }), - [] + [homepageUrl] ); return (
- +
); } diff --git a/frontend/app/view/webview/webview.tsx b/frontend/app/view/webview/webview.tsx index ed3cb33e2..caa345e4d 100644 --- a/frontend/app/view/webview/webview.tsx +++ b/frontend/app/view/webview/webview.tsx @@ -468,9 +468,10 @@ function makeWebViewModel(blockId: string, nodeModel: NodeModel): WebViewModel { interface WebViewProps { blockId: string; model: WebViewModel; + onFailLoad?: (url: string) => void; } -const WebView = memo(({ model }: WebViewProps) => { +const WebView = memo(({ model, onFailLoad }: WebViewProps) => { const blockData = useAtomValue(model.blockAtom); const defaultUrl = useAtomValue(model.homepageUrl); const defaultSearchAtom = getSettingsKeyAtom("web:defaultsearch"); @@ -555,6 +556,10 @@ const WebView = memo(({ model }: WebViewProps) => { console.warn("Suppressed ERR_ABORTED error", e); } else { console.error(`Failed to load ${e.validatedURL}: ${e.errorDescription}`); + if (onFailLoad) { + const curUrl = model.webviewRef?.current.getURL(); + onFailLoad(curUrl); + } } }; const webviewFocus = () => { From 19883a91593990409a1e7f63931d9bc63a3207ae Mon Sep 17 00:00:00 2001 From: "wave-builder[bot]" <181805596+wave-builder[bot]@users.noreply.github.com> Date: Thu, 17 Oct 2024 23:10:46 +0000 Subject: [PATCH 15/34] chore: bump package version to 0.8.12-beta.2 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 3cf865f1d..30d58210b 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "productName": "Wave", "description": "Open-Source AI-Native Terminal Built for Seamless Workflows", "license": "Apache-2.0", - "version": "0.8.12-beta.1", + "version": "0.8.12-beta.2", "homepage": "https://waveterm.dev", "build": { "appId": "dev.commandline.waveterm" From 123b6276403051a4c74dd31dd9bd1ed0fd729c3e Mon Sep 17 00:00:00 2001 From: Ian Jennings Date: Thu, 17 Oct 2024 19:09:41 -0500 Subject: [PATCH 16/34] TestDriver v4 (#865) This PR upgrades the TestDriver tests to v4. Some relevant updates on `v4` for y'all: - Our AI will pick up the job within ~2 minutes - Tests are 40% faster (with room for more improvement through turbo mode) and significantly more accurate - New `/generate` features enable the AI to create it's own tests - Smarter `/explore` features, this is how we generated your onboarding test - New `key:` config in our `action` allows you to post videos to your own account - New `createPR:` config in our `action` will automatically create PRs from test output - New [documentation](https://docs.testdriver.ai/reference/yml-schema). - VMs are now on Windows - Our best practice have been updated so we don't act as a build server anymore. Now,[ we download your artifact from GitHub](https://github.com/wavetermdev/waveterm/actions/runs/11276657325/workflow?pr=865#L96-L179) and test that. I cloned your "build and upload exe" action to do this, but we can link them together in the future. [![wavetermdev/waveterm/refs/pull/865/merge](https://replayable-api-production.herokuapp.com/replay/6707f12167f936f4742af056/gif?shareKey=ecw0VAHvh6k2gCJDqFQew)](https://app.dashcam.io/replay/6707f12167f936f4742af056?share=ecw0VAHvh6k2gCJDqFQew) Watch [wavetermdev/waveterm/refs/pull/865/merge](https://app.dashcam.io/replay/6707f12167f936f4742af056?share=ecw0VAHvh6k2gCJDqFQew) on Dashcam --------- Co-authored-by: Evan Simkowitz --- .github/workflows/testdriver.yml | 156 +++++++++++++++++++++++++++++++ testdriver/onboarding.yml | 12 +++ 2 files changed, 168 insertions(+) create mode 100644 .github/workflows/testdriver.yml create mode 100644 testdriver/onboarding.yml diff --git a/.github/workflows/testdriver.yml b/.github/workflows/testdriver.yml new file mode 100644 index 000000000..2b42fbf3d --- /dev/null +++ b/.github/workflows/testdriver.yml @@ -0,0 +1,156 @@ +name: TestDriver.ai + +on: + push: + branches: + - main + tags: + - "v[0-9]+.[0-9]+.[0-9]+*" + pull_request: + branches: + - main + schedule: + - cron: 0 21 * * * + workflow_dispatch: null + +env: + GO_VERSION: "1.22" + NODE_VERSION: "20" + +permissions: + contents: read # To allow the action to read repository contents + pull-requests: write # To allow the action to create/update pull request comments + +jobs: + build_and_upload: + name: Test Onboarding + runs-on: windows-latest + steps: + - uses: actions/checkout@v4 + + # General build dependencies + - uses: actions/setup-go@v5 + with: + go-version: ${{env.GO_VERSION}} + cache-dependency-path: | + go.sum + - uses: actions/setup-node@v4 + with: + node-version: ${{env.NODE_VERSION}} + - name: Install Yarn + run: | + corepack enable + yarn install + - name: Install Task + uses: arduino/setup-task@v2 + with: + version: 3.x + repo-token: ${{ secrets.GITHUB_TOKEN }} + + - name: Build + run: task package + env: + USE_SYSTEM_FPM: true # Ensure that the installed version of FPM is used rather than the bundled one. + CSC_IDENTITY_AUTO_DISCOVERY: false # disable codesign + shell: powershell # electron-builder's Windows code signing package has some compatibility issues with pwsh, so we need to use Windows Powershell + + # Upload .exe as an artifact + - name: Upload .exe artifact + id: upload + uses: actions/upload-artifact@v4 + with: + name: windows-exe + path: make/*.exe + + - uses: testdriverai/action@main + id: testdriver + env: + FORCE_COLOR: "3" + with: + key: ${{ secrets.DASHCAM_API }} + prerun: | + $headers = @{ + Authorization = "token ${{ secrets.GITHUB_TOKEN }}" + } + + $downloadFolder = "./download" + $artifactFileName = "waveterm.exe" + $artifactFilePath = "$downloadFolder/$artifactFileName" + + Write-Host "Starting the artifact download process..." + + # Create the download directory if it doesn't exist + if (-not (Test-Path -Path $downloadFolder)) { + Write-Host "Creating download folder..." + mkdir $downloadFolder + } else { + Write-Host "Download folder already exists." + } + + # Fetch the artifact upload URL + Write-Host "Fetching the artifact upload URL..." + $artifactUrl = (Invoke-RestMethod -Uri "https://api.github.com/repos/${{ github.repository }}/actions/runs/${{ github.run_id }}/artifacts" -Headers $headers).artifacts[0].archive_download_url + + if ($artifactUrl) { + Write-Host "Artifact URL successfully fetched: $artifactUrl" + } else { + Write-Error "Failed to fetch the artifact URL." + exit 1 + } + + # Download the artifact (zipped file) + Write-Host "Starting artifact download..." + $artifactZipPath = "$env:TEMP\artifact.zip" + try { + Invoke-WebRequest -Uri $artifactUrl ` + -Headers $headers ` + -OutFile $artifactZipPath ` + -MaximumRedirection 5 + + Write-Host "Artifact downloaded successfully to $artifactZipPath" + } catch { + Write-Error "Error downloading artifact: $_" + exit 1 + } + + # Unzip the artifact + $artifactUnzipPath = "$env:TEMP\artifact" + Write-Host "Unzipping the artifact to $artifactUnzipPath..." + try { + Expand-Archive -Path $artifactZipPath -DestinationPath $artifactUnzipPath -Force + Write-Host "Artifact unzipped successfully to $artifactUnzipPath" + } catch { + Write-Error "Failed to unzip the artifact: $_" + exit 1 + } + + # Find the installer or app executable + $artifactInstallerPath = Get-ChildItem -Path $artifactUnzipPath -Filter *.exe -Recurse | Select-Object -First 1 + + if ($artifactInstallerPath) { + Write-Host "Executable file found: $($artifactInstallerPath.FullName)" + } else { + Write-Error "Executable file not found. Exiting." + exit 1 + } + + # Run the installer and log the result + Write-Host "Running the installer: $($artifactInstallerPath.FullName)..." + try { + Start-Process -FilePath $artifactInstallerPath.FullName -Wait + Write-Host "Installer ran successfully." + } catch { + Write-Error "Failed to run the installer: $_" + exit 1 + } + + # Optional: If the app executable is different from the installer, find and launch it + $wavePath = Join-Path $env:USERPROFILE "AppData\Local\Programs\waveterm\Wave.exe" + + Write-Host "Launching the application: $($wavePath)" + Start-Process -FilePath $wavePath + Write-Host "Application launched." + + prompt: | + 1. /run testdriver/onboarding.yml + 2. /generate desktop 20 diff --git a/testdriver/onboarding.yml b/testdriver/onboarding.yml new file mode 100644 index 000000000..841d46226 --- /dev/null +++ b/testdriver/onboarding.yml @@ -0,0 +1,12 @@ +version: 4.0.65 +steps: + - prompt: complete the onboarding of wave terminal + commands: + - command: hover-text + text: Continue + description: button to complete onboarding + action: click + - command: hover-text + text: Get Started + description: button to complete onboarding + action: click From dc70ab4014ef56700af1f75c2534d4e7dd2538d2 Mon Sep 17 00:00:00 2001 From: Mike Sawka Date: Thu, 17 Oct 2024 23:42:55 -0700 Subject: [PATCH 17/34] ws reconnection bug + clean up logging (#1058) --- emain/docsite.ts | 5 +++- emain/emain.ts | 2 +- frontend/app/store/ws.ts | 32 +++++++++++++++++--------- frontend/app/view/webview/webview.tsx | 1 - pkg/blockcontroller/blockcontroller.go | 1 - pkg/web/ws.go | 31 +++++++++++++------------ pkg/wshrpc/wshserver/wshserver.go | 1 - 7 files changed, 42 insertions(+), 31 deletions(-) diff --git a/emain/docsite.ts b/emain/docsite.ts index ccdcc602b..ddf9d21b8 100644 --- a/emain/docsite.ts +++ b/emain/docsite.ts @@ -17,7 +17,10 @@ export async function initDocsite() { console.log("Embedded docsite is running, using embedded version for help view"); docsiteUrl = docsiteEmbeddedUrl; } else { - console.log("Embedded docsite is not running, using web version for help view", response); + console.log( + "Embedded docsite is not running, using web version for help view", + "status: " + response?.status + ); docsiteUrl = docsiteWebUrl; } } catch (error) { diff --git a/emain/emain.ts b/emain/emain.ts index de447b415..4713f45e6 100644 --- a/emain/emain.ts +++ b/emain/emain.ts @@ -1075,7 +1075,7 @@ async function relaunchBrowserWindows(): Promise { } for (const win of wins) { await win.readyPromise; - console.log("show", win.waveWindowId); + console.log("show window", win.waveWindowId); win.show(); } } diff --git a/frontend/app/store/ws.ts b/frontend/app/store/ws.ts index 1b11ab326..bbf5477b1 100644 --- a/frontend/app/store/ws.ts +++ b/frontend/app/store/ws.ts @@ -12,6 +12,7 @@ const dlog = debug("wave:ws"); const WarnWebSocketSendSize = 1024 * 1024; // 1MB const MaxWebSocketSendSize = 5 * 1024 * 1024; // 5MB const reconnectHandlers: (() => void)[] = []; +const StableConnTime = 2000; function addWSReconnectHandler(handler: () => void) { reconnectHandlers.push(handler); @@ -45,6 +46,7 @@ class WSControl { lastReconnectTime: number = 0; eoOpts: ElectronOverrideOpts; noReconnect: boolean = false; + onOpenTimeoutId: NodeJS.Timeout = null; constructor( baseHostPort: string, @@ -80,9 +82,15 @@ class WSControl { } : null ); - this.wsConn.onopen = this.onopen.bind(this); - this.wsConn.onmessage = this.onmessage.bind(this); - this.wsConn.onclose = this.onclose.bind(this); + this.wsConn.onopen = (e: Event) => { + this.onopen(e); + }; + this.wsConn.onmessage = (e: MessageEvent) => { + this.onmessage(e); + }; + this.wsConn.onclose = (e: CloseEvent) => { + this.onclose(e); + }; // turns out onerror is not necessary (onclose always follows onerror) // this.wsConn.onerror = this.onerror; } @@ -118,8 +126,11 @@ class WSControl { }, timeout * 1000); } - onclose(event: any) { + onclose(event: CloseEvent) { // console.log("close", event); + if (this.onOpenTimeoutId) { + clearTimeout(this.onOpenTimeoutId); + } if (event.wasClean) { dlog("connection closed"); } else { @@ -132,15 +143,18 @@ class WSControl { } } - onopen() { + onopen(e: Event) { dlog("connection open"); this.open = true; this.opening = false; + this.onOpenTimeoutId = setTimeout(() => { + this.reconnectTimes = 0; + dlog("clear reconnect times"); + }, StableConnTime); for (let handler of reconnectHandlers) { handler(); } this.runMsgQueue(); - // reconnectTimes is reset in onmessage:hello } runMsgQueue() { @@ -157,7 +171,7 @@ class WSControl { }, 100); } - onmessage(event: any) { + onmessage(event: MessageEvent) { let eventData = null; if (event.data != null) { eventData = JSON.parse(event.data); @@ -173,10 +187,6 @@ class WSControl { // nothing return; } - if (eventData.type == "hello") { - this.reconnectTimes = 0; - return; - } if (this.messageCallback) { try { this.messageCallback(eventData); diff --git a/frontend/app/view/webview/webview.tsx b/frontend/app/view/webview/webview.tsx index caa345e4d..376e8e9c5 100644 --- a/frontend/app/view/webview/webview.tsx +++ b/frontend/app/view/webview/webview.tsx @@ -60,7 +60,6 @@ export class WebViewModel implements ViewModel { this.homepageUrl = atom((get) => { const defaultUrl = get(defaultUrlAtom); const pinnedUrl = get(this.blockAtom).meta.pinnedurl; - console.log("homepageUrl", pinnedUrl, defaultUrl); return pinnedUrl ?? defaultUrl; }); this.urlWrapperClassName = atom(""); diff --git a/pkg/blockcontroller/blockcontroller.go b/pkg/blockcontroller/blockcontroller.go index bd55082a3..4e9bc4886 100644 --- a/pkg/blockcontroller/blockcontroller.go +++ b/pkg/blockcontroller/blockcontroller.go @@ -369,7 +369,6 @@ func (bc *BlockController) DoRunShellCommand(rc *RunShellOpts, blockMeta waveobj bc.ShellProc.Cmd.Write(ic.InputData) } if ic.TermSize != nil { - log.Printf("SETTERMSIZE: %dx%d\n", ic.TermSize.Rows, ic.TermSize.Cols) err = setTermSize(ctx, bc.BlockId, *ic.TermSize) if err != nil { log.Printf("error setting pty size: %v\n", err) diff --git a/pkg/web/ws.go b/pkg/web/ws.go index 4c605fa27..bde3ec167 100644 --- a/pkg/web/ws.go +++ b/pkg/web/ws.go @@ -40,10 +40,10 @@ func RunWebSocketServer(listener net.Listener) { Handler: gr, } server.SetKeepAlivesEnabled(false) - log.Printf("Running websocket server on %s\n", listener.Addr()) + log.Printf("[websocket] running websocket server on %s\n", listener.Addr()) err := server.Serve(listener) if err != nil { - log.Printf("[error] trying to run websocket server: %v\n", err) + log.Printf("[websocket] error trying to run websocket server: %v\n", err) } } @@ -81,7 +81,7 @@ func processWSCommand(jmsg map[string]any, outputCh chan any, rpcInputCh chan [] r := recover() if r != nil { rtnErr = fmt.Errorf("panic: %v", r) - log.Printf("panic in processMessage: %v\n", r) + log.Printf("[websocket] panic in processMessage: %v\n", r) debug.PrintStack() } if rtnErr == nil { @@ -108,7 +108,7 @@ func processWSCommand(jmsg map[string]any, outputCh chan any, rpcInputCh chan [] msgBytes, err := json.Marshal(rpcMsg) if err != nil { // this really should never fail since we just unmarshalled this value - log.Printf("error marshalling rpc message: %v\n", err) + log.Printf("[websocket] error marshalling rpc message: %v\n", err) return } rpcInputCh <- msgBytes @@ -125,7 +125,7 @@ func processWSCommand(jmsg map[string]any, outputCh chan any, rpcInputCh chan [] msgBytes, err := json.Marshal(rpcMsg) if err != nil { // this really should never fail since we just unmarshalled this value - log.Printf("error marshalling rpc message: %v\n", err) + log.Printf("[websocket] error marshalling rpc message: %v\n", err) return } rpcInputCh <- msgBytes @@ -152,7 +152,7 @@ func processMessage(jmsg map[string]any, outputCh chan any, rpcInputCh chan []by processWSCommand(jmsg, outputCh, rpcInputCh) } -func ReadLoop(conn *websocket.Conn, outputCh chan any, closeCh chan any, rpcInputCh chan []byte) { +func ReadLoop(conn *websocket.Conn, outputCh chan any, closeCh chan any, rpcInputCh chan []byte, routeId string) { readWait := wsReadWaitTimeout conn.SetReadLimit(64 * 1024) conn.SetReadDeadline(time.Now().Add(readWait)) @@ -160,13 +160,13 @@ func ReadLoop(conn *websocket.Conn, outputCh chan any, closeCh chan any, rpcInpu for { _, message, err := conn.ReadMessage() if err != nil { - log.Printf("ReadPump error: %v\n", err) + log.Printf("[websocket] ReadPump error (%s): %v\n", routeId, err) break } jmsg := map[string]any{} err = json.Unmarshal(message, &jmsg) if err != nil { - log.Printf("Error unmarshalling json: %v\n", err) + log.Printf("[websocket] error unmarshalling json: %v\n", err) break } conn.SetReadDeadline(time.Now().Add(readWait)) @@ -197,7 +197,7 @@ func WritePing(conn *websocket.Conn) error { return nil } -func WriteLoop(conn *websocket.Conn, outputCh chan any, closeCh chan any) { +func WriteLoop(conn *websocket.Conn, outputCh chan any, closeCh chan any, routeId string) { ticker := time.NewTicker(wsInitialPingTime) defer ticker.Stop() initialPing := true @@ -211,7 +211,7 @@ func WriteLoop(conn *websocket.Conn, outputCh chan any, closeCh chan any) { } else { barr, err = json.Marshal(msg) if err != nil { - log.Printf("cannot marshal websocket message: %v\n", err) + log.Printf("[websocket] cannot marshal websocket message: %v\n", err) // just loop again break } @@ -219,14 +219,14 @@ func WriteLoop(conn *websocket.Conn, outputCh chan any, closeCh chan any) { err = conn.WriteMessage(websocket.TextMessage, barr) if err != nil { conn.Close() - log.Printf("WritePump error: %v\n", err) + log.Printf("[websocket] WritePump error (%s): %v\n", routeId, err) return } case <-ticker.C: err := WritePing(conn) if err != nil { - log.Printf("WritePump error: %v\n", err) + log.Printf("[websocket] WritePump error (%s): %v\n", routeId, err) return } if initialPing { @@ -250,6 +250,7 @@ func HandleWsInternal(w http.ResponseWriter, r *http.Request) error { if err != nil { w.WriteHeader(http.StatusUnauthorized) w.Write([]byte(fmt.Sprintf("error validating authkey: %v", err))) + log.Printf("[websocket] error validating authkey: %v\n", err) return err } conn, err := WebSocketUpgrader.Upgrade(w, r, nil) @@ -258,7 +259,6 @@ func HandleWsInternal(w http.ResponseWriter, r *http.Request) error { } defer conn.Close() wsConnId := uuid.New().String() - log.Printf("New websocket connection: windowid:%s connid:%s\n", windowId, wsConnId) outputCh := make(chan any, 100) closeCh := make(chan any) eventbus.RegisterWSChannel(wsConnId, windowId, outputCh) @@ -269,6 +269,7 @@ func HandleWsInternal(w http.ResponseWriter, r *http.Request) error { routeId = wshutil.MakeWindowRouteId(windowId) } defer eventbus.UnregisterWSChannel(wsConnId) + log.Printf("[websocket] new connection: windowid:%s connid:%s routeid:%s\n", windowId, wsConnId, routeId) // we create a wshproxy to handle rpc messages to/from the window wproxy := wshutil.MakeRpcProxy() wshutil.DefaultRouter.RegisterRoute(routeId, wproxy) @@ -293,12 +294,12 @@ func HandleWsInternal(w http.ResponseWriter, r *http.Request) error { go func() { // read loop defer wg.Done() - ReadLoop(conn, outputCh, closeCh, wproxy.FromRemoteCh) + ReadLoop(conn, outputCh, closeCh, wproxy.FromRemoteCh, routeId) }() go func() { // write loop defer wg.Done() - WriteLoop(conn, outputCh, closeCh) + WriteLoop(conn, outputCh, closeCh, routeId) }() wg.Wait() close(wproxy.FromRemoteCh) diff --git a/pkg/wshrpc/wshserver/wshserver.go b/pkg/wshrpc/wshserver/wshserver.go index fe093250f..91facb368 100644 --- a/pkg/wshrpc/wshserver/wshserver.go +++ b/pkg/wshrpc/wshserver/wshserver.go @@ -422,7 +422,6 @@ func (ws *WshServer) EventPublishCommand(ctx context.Context, data wps.WaveEvent } func (ws *WshServer) EventSubCommand(ctx context.Context, data wps.SubscriptionRequest) error { - log.Printf("EventSubCommand: %v\n", data) rpcSource := wshutil.GetRpcSourceFromContext(ctx) if rpcSource == "" { return fmt.Errorf("no rpc source set") From 455d45f1b92e80048026d58d89258154322d9efd Mon Sep 17 00:00:00 2001 From: "wave-builder[bot]" <181805596+wave-builder[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 06:43:45 +0000 Subject: [PATCH 18/34] chore: bump package version to 0.8.12-beta.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 30d58210b..f6528d407 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "productName": "Wave", "description": "Open-Source AI-Native Terminal Built for Seamless Workflows", "license": "Apache-2.0", - "version": "0.8.12-beta.2", + "version": "0.8.12-beta.3", "homepage": "https://waveterm.dev", "build": { "appId": "dev.commandline.waveterm" From 62a1149a8d2f84058a4bd3cff9ff2707987b4771 Mon Sep 17 00:00:00 2001 From: Mike Sawka Date: Fri, 18 Oct 2024 12:05:20 -0700 Subject: [PATCH 19/34] fix websocket reconnect error (#1064) --- pkg/web/ws.go | 44 +++++++++++++++++++++++++++++++--------- pkg/wshutil/wshrouter.go | 6 +++++- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/pkg/web/ws.go b/pkg/web/ws.go index bde3ec167..5ef0c0344 100644 --- a/pkg/web/ws.go +++ b/pkg/web/ws.go @@ -30,6 +30,9 @@ const wsInitialPingTime = 1 * time.Second const DefaultCommandTimeout = 2 * time.Second +var GlobalLock = &sync.Mutex{} +var RouteToConnMap = map[string]string{} // routeid => connid + func RunWebSocketServer(listener net.Listener) { gr := mux.NewRouter() gr.HandleFunc("/ws", HandleWs) @@ -240,6 +243,31 @@ func WriteLoop(conn *websocket.Conn, outputCh chan any, closeCh chan any, routeI } } +func registerConn(wsConnId string, routeId string, wproxy *wshutil.WshRpcProxy) { + GlobalLock.Lock() + defer GlobalLock.Unlock() + curConnId := RouteToConnMap[routeId] + if curConnId != "" { + log.Printf("[websocket] warning: replacing existing connection for route %q\n", routeId) + wshutil.DefaultRouter.UnregisterRoute(routeId) + } + RouteToConnMap[routeId] = wsConnId + wshutil.DefaultRouter.RegisterRoute(routeId, wproxy) +} + +func unregisterConn(wsConnId string, routeId string) { + GlobalLock.Lock() + defer GlobalLock.Unlock() + curConnId := RouteToConnMap[routeId] + if curConnId != wsConnId { + // only unregister if we are the current connection (otherwise we were already removed) + log.Printf("[websocket] warning: trying to unregister connection %q for route %q but it is not the current connection (ignoring)\n", wsConnId, routeId) + return + } + delete(RouteToConnMap, routeId) + wshutil.DefaultRouter.UnregisterRoute(routeId) +} + func HandleWsInternal(w http.ResponseWriter, r *http.Request) error { windowId := r.URL.Query().Get("windowid") if windowId == "" { @@ -261,23 +289,19 @@ func HandleWsInternal(w http.ResponseWriter, r *http.Request) error { wsConnId := uuid.New().String() outputCh := make(chan any, 100) closeCh := make(chan any) - eventbus.RegisterWSChannel(wsConnId, windowId, outputCh) var routeId string if windowId == wshutil.ElectronRoute { routeId = wshutil.ElectronRoute } else { routeId = wshutil.MakeWindowRouteId(windowId) } - defer eventbus.UnregisterWSChannel(wsConnId) log.Printf("[websocket] new connection: windowid:%s connid:%s routeid:%s\n", windowId, wsConnId, routeId) - // we create a wshproxy to handle rpc messages to/from the window - wproxy := wshutil.MakeRpcProxy() - wshutil.DefaultRouter.RegisterRoute(routeId, wproxy) - defer func() { - wshutil.DefaultRouter.UnregisterRoute(routeId) - close(wproxy.ToRemoteCh) - }() - // WshServerFactoryFn(rpcInputCh, rpcOutputCh, wshrpc.RpcContext{}) + eventbus.RegisterWSChannel(wsConnId, windowId, outputCh) + defer eventbus.UnregisterWSChannel(wsConnId) + wproxy := wshutil.MakeRpcProxy() // we create a wshproxy to handle rpc messages to/from the window + defer close(wproxy.ToRemoteCh) + registerConn(wsConnId, routeId, wproxy) + defer unregisterConn(wsConnId, routeId) wg := &sync.WaitGroup{} wg.Add(2) go func() { diff --git a/pkg/wshutil/wshrouter.go b/pkg/wshutil/wshrouter.go index 26fdb8a39..6389e3d99 100644 --- a/pkg/wshutil/wshrouter.go +++ b/pkg/wshutil/wshrouter.go @@ -274,10 +274,14 @@ func (router *WshRouter) RegisterRoute(routeId string, rpc AbstractRpcClient) { log.Printf("[router] registering wsh route %q\n", routeId) router.Lock.Lock() defer router.Lock.Unlock() + alreadyExists := router.RouteMap[routeId] != nil + if alreadyExists { + log.Printf("[router] warning: route %q already exists (replacing)\n", routeId) + } router.RouteMap[routeId] = rpc go func() { // announce - if router.GetUpstreamClient() != nil { + if !alreadyExists && router.GetUpstreamClient() != nil { announceMsg := RpcMessage{Command: wshrpc.Command_RouteAnnounce, Source: routeId} announceBytes, _ := json.Marshal(announceMsg) router.GetUpstreamClient().SendRpcMessage(announceBytes) From dac0cbb5f261f2328c09509e1a7793a7873fed6e Mon Sep 17 00:00:00 2001 From: "wave-builder[bot]" <181805596+wave-builder[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 19:06:07 +0000 Subject: [PATCH 20/34] chore: bump package version to 0.8.12-beta.4 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index f6528d407..09fa14c81 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "productName": "Wave", "description": "Open-Source AI-Native Terminal Built for Seamless Workflows", "license": "Apache-2.0", - "version": "0.8.12-beta.3", + "version": "0.8.12-beta.4", "homepage": "https://waveterm.dev", "build": { "appId": "dev.commandline.waveterm" From de004a3cdf3f30b6bfb352f8cdbba0435aab2273 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Fri, 18 Oct 2024 12:33:08 -0700 Subject: [PATCH 21/34] Remove ollama AI preset (#1068) I added this as an example, but it fails if the user doesn't have ollama and/or llama:3.1 so I'm removing it --- pkg/wconfig/defaultconfig/presets.json | 7 ------- 1 file changed, 7 deletions(-) diff --git a/pkg/wconfig/defaultconfig/presets.json b/pkg/wconfig/defaultconfig/presets.json index 78da237fe..38d16d494 100644 --- a/pkg/wconfig/defaultconfig/presets.json +++ b/pkg/wconfig/defaultconfig/presets.json @@ -107,12 +107,5 @@ "ai:model": "gpt-4o-mini", "ai:maxtokens": 2048, "ai:timeoutms": 60000 - }, - "ai@ollama-llama3.1": { - "display:name": "ollama - llama3.1", - "display:order": 0, - "ai:*": true, - "ai:baseurl": "http://localhost:11434/v1", - "ai:model": "llama3.1:latest" } } From 954b42e52896a80e930d35c2ed7d617cf09fab9e Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:33:30 -0700 Subject: [PATCH 22/34] Bump the storybook group with 9 updates (#1061) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the storybook group with 9 updates: | Package | From | To | | --- | --- | --- | | [@storybook/addon-essentials](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/essentials) | `8.3.5` | `8.3.6` | | [@storybook/addon-interactions](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/interactions) | `8.3.5` | `8.3.6` | | [@storybook/addon-links](https://github.com/storybookjs/storybook/tree/HEAD/code/addons/links) | `8.3.5` | `8.3.6` | | [@storybook/blocks](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/blocks) | `8.3.5` | `8.3.6` | | [@storybook/react](https://github.com/storybookjs/storybook/tree/HEAD/code/renderers/react) | `8.3.5` | `8.3.6` | | [@storybook/react-vite](https://github.com/storybookjs/storybook/tree/HEAD/code/frameworks/react-vite) | `8.3.5` | `8.3.6` | | [@storybook/test](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/test) | `8.3.5` | `8.3.6` | | [@storybook/theming](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/theming) | `8.3.5` | `8.3.6` | | [storybook](https://github.com/storybookjs/storybook/tree/HEAD/code/lib/cli) | `8.3.5` | `8.3.6` | Updates `@storybook/addon-essentials` from 8.3.5 to 8.3.6
Release notes

Sourced from @​storybook/addon-essentials's releases.

v8.3.6

8.3.6

Changelog

Sourced from @​storybook/addon-essentials's changelog.

8.3.6

Commits

Updates `@storybook/addon-interactions` from 8.3.5 to 8.3.6
Release notes

Sourced from @​storybook/addon-interactions's releases.

v8.3.6

8.3.6

Changelog

Sourced from @​storybook/addon-interactions's changelog.

8.3.6

Commits

Updates `@storybook/addon-links` from 8.3.5 to 8.3.6
Release notes

Sourced from @​storybook/addon-links's releases.

v8.3.6

8.3.6

Changelog

Sourced from @​storybook/addon-links's changelog.

8.3.6

Commits

Updates `@storybook/blocks` from 8.3.5 to 8.3.6
Release notes

Sourced from @​storybook/blocks's releases.

v8.3.6

8.3.6

Changelog

Sourced from @​storybook/blocks's changelog.

8.3.6

Commits

Updates `@storybook/react` from 8.3.5 to 8.3.6
Release notes

Sourced from @​storybook/react's releases.

v8.3.6

8.3.6

Changelog

Sourced from @​storybook/react's changelog.

8.3.6

Commits

Updates `@storybook/react-vite` from 8.3.5 to 8.3.6
Release notes

Sourced from @​storybook/react-vite's releases.

v8.3.6

8.3.6

Changelog

Sourced from @​storybook/react-vite's changelog.

8.3.6

Commits

Updates `@storybook/test` from 8.3.5 to 8.3.6
Release notes

Sourced from @​storybook/test's releases.

v8.3.6

8.3.6

Changelog

Sourced from @​storybook/test's changelog.

8.3.6

Commits

Updates `@storybook/theming` from 8.3.5 to 8.3.6
Release notes

Sourced from @​storybook/theming's releases.

v8.3.6

8.3.6

Commits

Updates `storybook` from 8.3.5 to 8.3.6
Release notes

Sourced from storybook's releases.

v8.3.6

8.3.6

Changelog

Sourced from storybook's changelog.

8.3.6

Commits

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 18 +-- yarn.lock | 324 +++++++++++++++++++++++++-------------------------- 2 files changed, 171 insertions(+), 171 deletions(-) diff --git a/package.json b/package.json index 09fa14c81..9d2e150c6 100644 --- a/package.json +++ b/package.json @@ -30,14 +30,14 @@ "@chromatic-com/storybook": "^2.0.2", "@eslint/js": "^9.12.0", "@rollup/plugin-node-resolve": "^15.3.0", - "@storybook/addon-essentials": "^8.3.5", - "@storybook/addon-interactions": "^8.3.5", - "@storybook/addon-links": "^8.3.5", - "@storybook/blocks": "^8.3.5", - "@storybook/react": "^8.3.5", - "@storybook/react-vite": "^8.3.5", - "@storybook/test": "^8.3.5", - "@storybook/theming": "^8.3.5", + "@storybook/addon-essentials": "^8.3.6", + "@storybook/addon-interactions": "^8.3.6", + "@storybook/addon-links": "^8.3.6", + "@storybook/blocks": "^8.3.6", + "@storybook/react": "^8.3.6", + "@storybook/react-vite": "^8.3.6", + "@storybook/test": "^8.3.6", + "@storybook/theming": "^8.3.6", "@types/css-tree": "^2", "@types/debug": "^4", "@types/electron": "^1.6.10", @@ -66,7 +66,7 @@ "prettier-plugin-organize-imports": "^4.1.0", "rollup-plugin-flow": "^1.1.1", "semver": "^7.6.3", - "storybook": "^8.3.5", + "storybook": "^8.3.6", "storybook-dark-mode": "^4.0.2", "ts-node": "^10.9.2", "tslib": "^2.6.3", diff --git a/yarn.lock b/yarn.lock index c6fda30e3..5bc38825f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1527,9 +1527,9 @@ __metadata: languageName: node linkType: hard -"@storybook/addon-actions@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/addon-actions@npm:8.3.5" +"@storybook/addon-actions@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/addon-actions@npm:8.3.6" dependencies: "@storybook/global": "npm:^5.0.0" "@types/uuid": "npm:^9.0.1" @@ -1537,47 +1537,47 @@ __metadata: polished: "npm:^4.2.2" uuid: "npm:^9.0.0" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/c9872d9d41b33ae26be36dfb25ccb10e7c832d4677cffe4f3e8a42f2748d8c54e681810662b88e10d1e72223096ad1861e389ee7134974e9f3e2869958300e08 + storybook: ^8.3.6 + checksum: 10c0/77959b8f0b3e4748051411bb0cd8041cff68360aa3dc98745153bbfd48aa330f2228ac9b9a42c1f3fd40c003bab5b425ed2b1ff540a985d3a00869989e547b8e languageName: node linkType: hard -"@storybook/addon-backgrounds@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/addon-backgrounds@npm:8.3.5" +"@storybook/addon-backgrounds@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/addon-backgrounds@npm:8.3.6" dependencies: "@storybook/global": "npm:^5.0.0" memoizerific: "npm:^1.11.3" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/6a2ce804bd96827a0601b53ea1f15bec382e1099cf957a0ac3c9452da1a58702fb5cea4b76c564a78a3a4f66431eaf3d826ad400d3bd579fec94ec266f06e211 + storybook: ^8.3.6 + checksum: 10c0/7d05c94ce351d162a5f55378a7779ce26e84dadbe540c5d68abd470501e097e7b006434fbb057b9d86c19e595254187d2f9f5e9ee847190ae29bcc2e46fa55a1 languageName: node linkType: hard -"@storybook/addon-controls@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/addon-controls@npm:8.3.5" +"@storybook/addon-controls@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/addon-controls@npm:8.3.6" dependencies: "@storybook/global": "npm:^5.0.0" dequal: "npm:^2.0.2" lodash: "npm:^4.17.21" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/f0bf85a8f401649734ae63ece9b64fe77b10a290cd1e83f54d83da4ae58f5a3a9e3876497f8cb3e9ac12dd1814fe7d16cee88bd6985877422823965b20607385 + storybook: ^8.3.6 + checksum: 10c0/d7222232caaee1f3e914c08987891b511b79127635cc352a20dd529c4518573844847f7b5da91f62ce27c6809e9303c95878db6f1dea4b8d88769cbff64fbce4 languageName: node linkType: hard -"@storybook/addon-docs@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/addon-docs@npm:8.3.5" +"@storybook/addon-docs@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/addon-docs@npm:8.3.6" dependencies: "@mdx-js/react": "npm:^3.0.0" - "@storybook/blocks": "npm:8.3.5" - "@storybook/csf-plugin": "npm:8.3.5" + "@storybook/blocks": "npm:8.3.6" + "@storybook/csf-plugin": "npm:8.3.6" "@storybook/global": "npm:^5.0.0" - "@storybook/react-dom-shim": "npm:8.3.5" + "@storybook/react-dom-shim": "npm:8.3.6" "@types/react": "npm:^16.8.0 || ^17.0.0 || ^18.0.0" fs-extra: "npm:^11.1.0" react: "npm:^16.8.0 || ^17.0.0 || ^18.0.0" @@ -1586,121 +1586,121 @@ __metadata: rehype-slug: "npm:^6.0.0" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/51f277079397ecc0e5fef721307a618e3aa4727069dba2b331cb4de2e6e318f4de338132e1ea886c0e9ee0824a10cbc9a0887e0f09f341221a31a09111ce4836 + storybook: ^8.3.6 + checksum: 10c0/c2d03904b6e465add7b3a56ed3ee965c098ea7252d0fe431cc581b7774fe99803a4891062b064033578f78c7ab77465e2179cfb66f4333a4d5edcd01af62c421 languageName: node linkType: hard -"@storybook/addon-essentials@npm:^8.3.5": - version: 8.3.5 - resolution: "@storybook/addon-essentials@npm:8.3.5" +"@storybook/addon-essentials@npm:^8.3.6": + version: 8.3.6 + resolution: "@storybook/addon-essentials@npm:8.3.6" dependencies: - "@storybook/addon-actions": "npm:8.3.5" - "@storybook/addon-backgrounds": "npm:8.3.5" - "@storybook/addon-controls": "npm:8.3.5" - "@storybook/addon-docs": "npm:8.3.5" - "@storybook/addon-highlight": "npm:8.3.5" - "@storybook/addon-measure": "npm:8.3.5" - "@storybook/addon-outline": "npm:8.3.5" - "@storybook/addon-toolbars": "npm:8.3.5" - "@storybook/addon-viewport": "npm:8.3.5" + "@storybook/addon-actions": "npm:8.3.6" + "@storybook/addon-backgrounds": "npm:8.3.6" + "@storybook/addon-controls": "npm:8.3.6" + "@storybook/addon-docs": "npm:8.3.6" + "@storybook/addon-highlight": "npm:8.3.6" + "@storybook/addon-measure": "npm:8.3.6" + "@storybook/addon-outline": "npm:8.3.6" + "@storybook/addon-toolbars": "npm:8.3.6" + "@storybook/addon-viewport": "npm:8.3.6" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/dad5ec31342abafe93eefa10178278f2f3cb8f849824050cf9248ff976188fda9bdc167750a57c57f0f821a56dd46daef92e70816a62b3cba435484f263fb703 + storybook: ^8.3.6 + checksum: 10c0/5f0a53ee42792fb76afdc54485fa907981363138786306dbcf2dea990b5809843a60da1148cd60141844951f462ec021c06befa0b98fea796abead95ca54716b languageName: node linkType: hard -"@storybook/addon-highlight@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/addon-highlight@npm:8.3.5" +"@storybook/addon-highlight@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/addon-highlight@npm:8.3.6" dependencies: "@storybook/global": "npm:^5.0.0" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/9bd4d29d10d612aa6baf2a3c470fd571f32edd4d456e3c4eb0dfe416be7891b075f06a7f46da35274c58261db8be5e97d974edec3c11b477f1cc397b357a42ca + storybook: ^8.3.6 + checksum: 10c0/6e0fe4b28e956af5bd534af2bfd4299be075e22b2fa4cbbe661da2901929e5a44f50cb65ed9869c1afee603f711e023e000556823ba534e1f61390b0c1989136 languageName: node linkType: hard -"@storybook/addon-interactions@npm:^8.3.5": - version: 8.3.5 - resolution: "@storybook/addon-interactions@npm:8.3.5" +"@storybook/addon-interactions@npm:^8.3.6": + version: 8.3.6 + resolution: "@storybook/addon-interactions@npm:8.3.6" dependencies: "@storybook/global": "npm:^5.0.0" - "@storybook/instrumenter": "npm:8.3.5" - "@storybook/test": "npm:8.3.5" + "@storybook/instrumenter": "npm:8.3.6" + "@storybook/test": "npm:8.3.6" polished: "npm:^4.2.2" ts-dedent: "npm:^2.2.0" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/66aef03bdaee184911db0ddd212ef5c87f30d985d363b65085a88d19aa0304feb2753f342338f7b675463405ddfd0f6c7938ec62acdad5bbcd43af3173738932 + storybook: ^8.3.6 + checksum: 10c0/cccde56641ce455a319d68fb9d2aadf1df9404566199e4225bfacf6e8381d118b1fea41dce5ff36946dd7aac3a9ff6a4a6f17763064ce2e14dfdab6df743a3de languageName: node linkType: hard -"@storybook/addon-links@npm:^8.3.5": - version: 8.3.5 - resolution: "@storybook/addon-links@npm:8.3.5" +"@storybook/addon-links@npm:^8.3.6": + version: 8.3.6 + resolution: "@storybook/addon-links@npm:8.3.6" dependencies: "@storybook/csf": "npm:^0.1.11" "@storybook/global": "npm:^5.0.0" ts-dedent: "npm:^2.0.0" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.3.5 + storybook: ^8.3.6 peerDependenciesMeta: react: optional: true - checksum: 10c0/ac431b420196fea7f9aa2a62356d2221c75065515ba82e4a0bbcddaa66a9a61d93f186e6efde87ca43ddfd043f3503f4459449d0f3f76935707276b87698f0d3 + checksum: 10c0/28d837680ef9c51aa1a4f43fb8c461dce90281264b2a259bf4ca7929d734bbda9a8ca54bf04d328ca4436c6d64b9cdb5b594717f8840d6d9693d0e637bdd8909 languageName: node linkType: hard -"@storybook/addon-measure@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/addon-measure@npm:8.3.5" +"@storybook/addon-measure@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/addon-measure@npm:8.3.6" dependencies: "@storybook/global": "npm:^5.0.0" tiny-invariant: "npm:^1.3.1" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/49a8f2fac76a65fc2b4fdf6c90a4996e58cccf4a3db56a7f32a17eff2a34ebeccf7ad8042a3bd3b1e8deba1d9ba95ce95f8ee57f11a98de51ce6fc29b2a127b4 + storybook: ^8.3.6 + checksum: 10c0/0ca83d45cf0268a9b2ac24a5fabb76ac23fb1036c75f6ac16ea847266ccd3c1676469289c1c41f73b89cdf38a8ebddafdedf82669c3fe9f81464fd0ce5ee9fe8 languageName: node linkType: hard -"@storybook/addon-outline@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/addon-outline@npm:8.3.5" +"@storybook/addon-outline@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/addon-outline@npm:8.3.6" dependencies: "@storybook/global": "npm:^5.0.0" ts-dedent: "npm:^2.0.0" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/d1d4d734e1770aa4af8fba2d789ad5c570ae0eb66301d8c5444a92a07428f66cde4a32e48fc1ea8627801c7d5c99ae40563554eef7f1a5ad14e4144ee74f9726 + storybook: ^8.3.6 + checksum: 10c0/52fa8cecd40f0b9ccd96053b7b1207c7cafe7f2ed6808e04e5f0d6503ab5266aeb0710bbace4b787ac3af38ea9cd6e671fc8aa8eee993f4cb64811057c5e3b55 languageName: node linkType: hard -"@storybook/addon-toolbars@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/addon-toolbars@npm:8.3.5" +"@storybook/addon-toolbars@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/addon-toolbars@npm:8.3.6" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/1e198ab1c87204f3ed69493484e94e6ad6bd4ed3c5a164ceeb0719cf2ddf96159d0fc481584c413d0bf3ff3943196ca123888ac67b0dbf967195d024387de84e + storybook: ^8.3.6 + checksum: 10c0/58ee542f1530dc71956fa15578320b8aa31b47406d011e40447dba80c62269c867af548fe1e72ddd95606118fbd51a444c86c0ea6f580b497390122a17ab65a7 languageName: node linkType: hard -"@storybook/addon-viewport@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/addon-viewport@npm:8.3.5" +"@storybook/addon-viewport@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/addon-viewport@npm:8.3.6" dependencies: memoizerific: "npm:^1.11.3" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/26e02754694d3422c19383ca330eb541394e54151e6c3d86865cbedcf49a323820b649e837e47ef94ea310c80ca47b9baa56fadee3a02db31bce5eaae6f43674 + storybook: ^8.3.6 + checksum: 10c0/95b91e415cb803898334e28890394884c612f1bcffdef5256e2b6ec373815fcefb43da8698bfa739eaf211315c49de056d107c1de61a9ab20c594e16da3f741e languageName: node linkType: hard -"@storybook/blocks@npm:8.3.5, @storybook/blocks@npm:^8.3.5": - version: 8.3.5 - resolution: "@storybook/blocks@npm:8.3.5" +"@storybook/blocks@npm:8.3.6, @storybook/blocks@npm:^8.3.6": + version: 8.3.6 + resolution: "@storybook/blocks@npm:8.3.6" dependencies: "@storybook/csf": "npm:^0.1.11" "@storybook/global": "npm:^5.0.0" @@ -1719,21 +1719,21 @@ __metadata: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.3.5 + storybook: ^8.3.6 peerDependenciesMeta: react: optional: true react-dom: optional: true - checksum: 10c0/8b4d4b7761ff32de02c231231ef49457f96438916c9f5e2af6eebd90842a7de1f26781a768f5f2b080abd26c8da66c1fca60d304a87f530216eb01d6434e7ff9 + checksum: 10c0/28522998923a62a5a365f60200b8fe3bd6df42e81a61b58d75440fde04916f402281622ffb68c321dab8ca148490f942abe753c98102e278ca9b620ce1ecc1d1 languageName: node linkType: hard -"@storybook/builder-vite@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/builder-vite@npm:8.3.5" +"@storybook/builder-vite@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/builder-vite@npm:8.3.6" dependencies: - "@storybook/csf-plugin": "npm:8.3.5" + "@storybook/csf-plugin": "npm:8.3.6" "@types/find-cache-dir": "npm:^3.2.1" browser-assert: "npm:^1.2.1" es-module-lexer: "npm:^1.5.0" @@ -1744,7 +1744,7 @@ __metadata: ts-dedent: "npm:^2.0.0" peerDependencies: "@preact/preset-vite": "*" - storybook: ^8.3.5 + storybook: ^8.3.6 typescript: ">= 4.3.x" vite: ^4.0.0 || ^5.0.0 vite-plugin-glimmerx: "*" @@ -1755,7 +1755,7 @@ __metadata: optional: true vite-plugin-glimmerx: optional: true - checksum: 10c0/7f597c1f0ae252e408863b34011f9210dc4247f96c4790836efb004081d426131ff9bfa23d4b69da7479a4ec8cb81f430b9538ce62b87621747ffd389741c296 + checksum: 10c0/d8fe2f548bc18ecb9844bc57736de32f1954e14f4697905b99f8fe7f89727a04f0acf6f6b94dacd6f41750605ac89f4ca2bdd5f36d180d831d8bbc7ec6a8d154 languageName: node linkType: hard @@ -1768,12 +1768,12 @@ __metadata: languageName: node linkType: hard -"@storybook/components@npm:^8.3.5": - version: 8.3.5 - resolution: "@storybook/components@npm:8.3.5" +"@storybook/components@npm:^8.3.6": + version: 8.3.6 + resolution: "@storybook/components@npm:8.3.6" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/20b3217f1a0a48ab5a40c08960d966be1fc6842dd40fc9951328d9bdc76411e3d3820865fd93895eeccec718ef8c8512f19d1fcad9bdd2cb6a792f92ca4d73ce + storybook: ^8.3.6 + checksum: 10c0/65badbad5143c6585c94b08d7f3496dad42de256cb077c60dade0ca3b0fa03eb4dc5917fe4c3df03df35b7cf39001b8898794747951ac4b7594ed278ea01e4b0 languageName: node linkType: hard @@ -1786,9 +1786,9 @@ __metadata: languageName: node linkType: hard -"@storybook/core@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/core@npm:8.3.5" +"@storybook/core@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/core@npm:8.3.6" dependencies: "@storybook/csf": "npm:^0.1.11" "@types/express": "npm:^4.17.21" @@ -1803,18 +1803,18 @@ __metadata: semver: "npm:^7.6.2" util: "npm:^0.12.5" ws: "npm:^8.2.3" - checksum: 10c0/f01d13c2309af518f1d029d27a3dd1ce80ea7423c9d4927d1096634a84887051c3581404971499ab81e5b28acca517bf1b31a3281fe7fdb0b418f0c45767f16f + checksum: 10c0/75635195335f9f296e830b51e4d71d8f2db833ad1d6b279f9da349dd312307d07c036351cfb421aea2b69c39f11a95343d9d5518432c7d49923237a82c694388 languageName: node linkType: hard -"@storybook/csf-plugin@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/csf-plugin@npm:8.3.5" +"@storybook/csf-plugin@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/csf-plugin@npm:8.3.6" dependencies: unplugin: "npm:^1.3.1" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/528af7509500afe1baf446fb8d52978c71d18df0abafd27a81ab821977cfb211bb02190f5a7d09005c4c10dac5e91ef978e35c74ee477ed7d6e45583ebc8412d + storybook: ^8.3.6 + checksum: 10c0/977998f7a908b2832dd293ea14171f6fdf9c3a25d4035b5c868a8be54630d73983eb3ff4867e488408283d1bcb64fc51c001460610b0143b050b11db953dcb26 languageName: node linkType: hard @@ -1854,16 +1854,16 @@ __metadata: languageName: node linkType: hard -"@storybook/instrumenter@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/instrumenter@npm:8.3.5" +"@storybook/instrumenter@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/instrumenter@npm:8.3.6" dependencies: "@storybook/global": "npm:^5.0.0" "@vitest/utils": "npm:^2.0.5" util: "npm:^0.12.4" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/9dd4e9080591200aa410ae9f7c132b466173a4fc882ad78e06fdbe8d795b04cee3afc5b1385ecb3ff5b9fb314abc3da2ac1494a8bf815e1113c3e8a241c5b7b7 + storybook: ^8.3.6 + checksum: 10c0/e071fcdb9fdb87c215412351bba765beed43f3bb487e51e837a85e6eb12575edf89d77ca1ab9edb7a70ad01fd498bb3aa3b35bbdb318ef9246e43d1310734f87 languageName: node linkType: hard @@ -1876,43 +1876,43 @@ __metadata: languageName: node linkType: hard -"@storybook/manager-api@npm:^8.3.5": - version: 8.3.5 - resolution: "@storybook/manager-api@npm:8.3.5" +"@storybook/manager-api@npm:^8.3.6": + version: 8.3.6 + resolution: "@storybook/manager-api@npm:8.3.6" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/4983af0e3a05abec0114acfa8bfe9d5df816b91f76614eb3c37dd654a0d4fdf5379d4d0cffc1676c6681d6142acd44e81abcb7c4f6de6108c8d26158cca9820d + storybook: ^8.3.6 + checksum: 10c0/9193d0f2d7bffdc461083f3ec5acf31badeb935d4a2d76a7ab39d2bb261105e3b60695811802113d03ac2fed7562e5c1377e1a090243c2d56b5cede0c8bc5fdd languageName: node linkType: hard -"@storybook/preview-api@npm:^8.3.5": - version: 8.3.5 - resolution: "@storybook/preview-api@npm:8.3.5" +"@storybook/preview-api@npm:^8.3.6": + version: 8.3.6 + resolution: "@storybook/preview-api@npm:8.3.6" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/12d81d57c0931983428b8621311de79a3846ec0f1c51ab94c5a9e7795a1e4bade74aa62de3693c488001630403c98a5372caca4be613f6f806e7265afb22e3d7 + storybook: ^8.3.6 + checksum: 10c0/f0413c36765c3518503d8dc67752356106a8d90fbc8f1db14ab0b454458a41ff1e8ce012911e59fa4432dde4260495c93c6265273024dcb1e8bb4d4d6e13cedb languageName: node linkType: hard -"@storybook/react-dom-shim@npm:8.3.5": - version: 8.3.5 - resolution: "@storybook/react-dom-shim@npm:8.3.5" +"@storybook/react-dom-shim@npm:8.3.6": + version: 8.3.6 + resolution: "@storybook/react-dom-shim@npm:8.3.6" peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.3.5 - checksum: 10c0/a765dc358ae2b1775197aa540024ff8f999c4d1673e76f632b74edd62bb609c8405f4ddfd392923ee6190bf0a1506a473cf41202323d8bda77b20681dc5a1594 + storybook: ^8.3.6 + checksum: 10c0/efc7917f8bc0d522ab075fd604c1aef9519f5ac534db56a37b03f7958eb1e0e954a7efde2c29ad6c553fb482cdaead7c9a78102e6dd172c3515bbf3d0062c774 languageName: node linkType: hard -"@storybook/react-vite@npm:^8.3.5": - version: 8.3.5 - resolution: "@storybook/react-vite@npm:8.3.5" +"@storybook/react-vite@npm:^8.3.6": + version: 8.3.6 + resolution: "@storybook/react-vite@npm:8.3.6" dependencies: "@joshwooding/vite-plugin-react-docgen-typescript": "npm:0.3.0" "@rollup/pluginutils": "npm:^5.0.2" - "@storybook/builder-vite": "npm:8.3.5" - "@storybook/react": "npm:8.3.5" + "@storybook/builder-vite": "npm:8.3.6" + "@storybook/react": "npm:8.3.6" find-up: "npm:^5.0.0" magic-string: "npm:^0.30.0" react-docgen: "npm:^7.0.0" @@ -1921,22 +1921,22 @@ __metadata: peerDependencies: react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.3.5 + storybook: ^8.3.6 vite: ^4.0.0 || ^5.0.0 - checksum: 10c0/a1e8969013cc74ffd353914880a533d5d64c2b912fa7b8e9528e06e2870625f7e9523647a8dfb03013e449a3eabcdefa5aa2155916dc6bb3063b66c3aa579be3 + checksum: 10c0/a1fa15aa49863cc1e1c6dc83186094ff43091c40daa720355eefb9a74934fa47d4c126bb6252ae0380a19219dd7e542c1782026acab3cd9a68f9513ba2f210e1 languageName: node linkType: hard -"@storybook/react@npm:8.3.5, @storybook/react@npm:^8.3.5": - version: 8.3.5 - resolution: "@storybook/react@npm:8.3.5" +"@storybook/react@npm:8.3.6, @storybook/react@npm:^8.3.6": + version: 8.3.6 + resolution: "@storybook/react@npm:8.3.6" dependencies: - "@storybook/components": "npm:^8.3.5" + "@storybook/components": "npm:^8.3.6" "@storybook/global": "npm:^5.0.0" - "@storybook/manager-api": "npm:^8.3.5" - "@storybook/preview-api": "npm:^8.3.5" - "@storybook/react-dom-shim": "npm:8.3.5" - "@storybook/theming": "npm:^8.3.5" + "@storybook/manager-api": "npm:^8.3.6" + "@storybook/preview-api": "npm:^8.3.6" + "@storybook/react-dom-shim": "npm:8.3.6" + "@storybook/theming": "npm:^8.3.6" "@types/escodegen": "npm:^0.0.6" "@types/estree": "npm:^0.0.51" "@types/node": "npm:^22.0.0" @@ -1952,27 +1952,27 @@ __metadata: type-fest: "npm:~2.19" util-deprecate: "npm:^1.0.2" peerDependencies: - "@storybook/test": 8.3.5 + "@storybook/test": 8.3.6 react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta react-dom: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0-beta - storybook: ^8.3.5 + storybook: ^8.3.6 typescript: ">= 4.2.x" peerDependenciesMeta: "@storybook/test": optional: true typescript: optional: true - checksum: 10c0/2db9aa673be975018c9a44cc4c0c662439a85298a4d931afe63bf4e1ca6f7ab6889eddf6d64a555483af84ccc65b3d81b712c2231096124063cf5afa77fcbb6d + checksum: 10c0/f536ec3c002f678b501ed0eb12b402770e2e185f9d751a6714609bacee7ae5f3ee05d25db3c7d44f1408819e313b78ce3aaa3eaa56a817b4c3b8083e5bd1383d languageName: node linkType: hard -"@storybook/test@npm:8.3.5, @storybook/test@npm:^8.3.5": - version: 8.3.5 - resolution: "@storybook/test@npm:8.3.5" +"@storybook/test@npm:8.3.6, @storybook/test@npm:^8.3.6": + version: 8.3.6 + resolution: "@storybook/test@npm:8.3.6" dependencies: "@storybook/csf": "npm:^0.1.11" "@storybook/global": "npm:^5.0.0" - "@storybook/instrumenter": "npm:8.3.5" + "@storybook/instrumenter": "npm:8.3.6" "@testing-library/dom": "npm:10.4.0" "@testing-library/jest-dom": "npm:6.5.0" "@testing-library/user-event": "npm:14.5.2" @@ -1980,8 +1980,8 @@ __metadata: "@vitest/spy": "npm:2.0.5" util: "npm:^0.12.4" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/1890aeab0b10d08f6b6bbaf68defaa2a0794e17e8f43ac3d92c3873d34771e198d088a2f4c0b135a299fe586407c4315cd443e270afa65d84914fcc5d63ea099 + storybook: ^8.3.6 + checksum: 10c0/708932d35b62fd84fb0fe7813d229fdb8fda77a8403496c79652e5418f015a68d15a2c422325790bf71d869f9cca3a377e92bde7fc8881285ffb290087b08daf languageName: node linkType: hard @@ -1994,12 +1994,12 @@ __metadata: languageName: node linkType: hard -"@storybook/theming@npm:^8.3.5": - version: 8.3.5 - resolution: "@storybook/theming@npm:8.3.5" +"@storybook/theming@npm:^8.3.6": + version: 8.3.6 + resolution: "@storybook/theming@npm:8.3.6" peerDependencies: - storybook: ^8.3.5 - checksum: 10c0/25455033b2b3bdb86083f759df77df42bfff71405c6abd301963dd7596003b462a0960a86c5cec3503dc9e1eba565eeb82a897002c6823f9ee361155b9ddfd23 + storybook: ^8.3.6 + checksum: 10c0/9e6dc4cb4bb444cbf3ac0f5b42696d462cd4886a5dcd42b4a8aee332ab141a1b745041bbb3fb36ab220820a3ab36ac4edd5f1ef81b66bba4059b4bdaa890006e languageName: node linkType: hard @@ -10545,16 +10545,16 @@ __metadata: languageName: node linkType: hard -"storybook@npm:^8.3.5": - version: 8.3.5 - resolution: "storybook@npm:8.3.5" +"storybook@npm:^8.3.6": + version: 8.3.6 + resolution: "storybook@npm:8.3.6" dependencies: - "@storybook/core": "npm:8.3.5" + "@storybook/core": "npm:8.3.6" bin: getstorybook: ./bin/index.cjs sb: ./bin/index.cjs storybook: ./bin/index.cjs - checksum: 10c0/8f8ffe54c5dad8bad9d8701f63f4670cf3f388acd0e21e5bedeb86ebd2af5adf905024b6b9a2c46cf1199a0c1c86a97fddfa1fc70546149e18263b3b47c80585 + checksum: 10c0/f366ab5feeb354200c6df58f6d7bafc146b56af2d72ad93e19438e1750de2185c199fd804da7728ecaba73ef73404a53f0501829c2af6dffff830f848faf198c languageName: node linkType: hard @@ -11643,14 +11643,14 @@ __metadata: "@observablehq/plot": "npm:^0.6.16" "@react-hook/resize-observer": "npm:^2.0.2" "@rollup/plugin-node-resolve": "npm:^15.3.0" - "@storybook/addon-essentials": "npm:^8.3.5" - "@storybook/addon-interactions": "npm:^8.3.5" - "@storybook/addon-links": "npm:^8.3.5" - "@storybook/blocks": "npm:^8.3.5" - "@storybook/react": "npm:^8.3.5" - "@storybook/react-vite": "npm:^8.3.5" - "@storybook/test": "npm:^8.3.5" - "@storybook/theming": "npm:^8.3.5" + "@storybook/addon-essentials": "npm:^8.3.6" + "@storybook/addon-interactions": "npm:^8.3.6" + "@storybook/addon-links": "npm:^8.3.6" + "@storybook/blocks": "npm:^8.3.6" + "@storybook/react": "npm:^8.3.6" + "@storybook/react-vite": "npm:^8.3.6" + "@storybook/test": "npm:^8.3.6" + "@storybook/theming": "npm:^8.3.6" "@table-nav/core": "npm:^0.0.7" "@table-nav/react": "npm:^0.0.7" "@tanstack/react-table": "npm:^8.20.5" @@ -11724,7 +11724,7 @@ __metadata: sharp: "npm:^0.33.5" shell-quote: "npm:^1.8.1" sprintf-js: "npm:^1.1.3" - storybook: "npm:^8.3.5" + storybook: "npm:^8.3.6" storybook-dark-mode: "npm:^4.0.2" throttle-debounce: "npm:^5.0.2" tinycolor2: "npm:^1.6.0" From a02a63bd8fb4875613815a86bace2fe0349a8abc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:33:45 -0700 Subject: [PATCH 23/34] Bump the dev-dependencies group with 6 updates (#1060) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the dev-dependencies group with 6 updates: | Package | From | To | | --- | --- | --- | | [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node) | `22.7.5` | `22.7.6` | | [@vitest/coverage-istanbul](https://github.com/vitest-dev/vitest/tree/HEAD/packages/coverage-istanbul) | `2.1.2` | `2.1.3` | | [tslib](https://github.com/Microsoft/tslib) | `2.7.0` | `2.8.0` | | [typescript-eslint](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint) | `8.8.1` | `8.10.0` | | [vite](https://github.com/vitejs/vite/tree/HEAD/packages/vite) | `5.4.8` | `5.4.9` | | [vitest](https://github.com/vitest-dev/vitest/tree/HEAD/packages/vitest) | `2.1.2` | `2.1.3` | Updates `@types/node` from 22.7.5 to 22.7.6
Commits

Updates `@vitest/coverage-istanbul` from 2.1.2 to 2.1.3
Release notes

Sourced from @​vitest/coverage-istanbul's releases.

v2.1.3

   🐞 Bug Fixes

   🏎 Performance

    View changes on GitHub
Commits

Updates `tslib` from 2.7.0 to 2.8.0
Release notes

Sourced from tslib's releases.

v2.8.0

What's Changed

Full Changelog: https://github.com/microsoft/tslib/compare/v2.7.0...v2.8.0

Commits

Updates `typescript-eslint` from 8.8.1 to 8.10.0
Release notes

Sourced from typescript-eslint's releases.

v8.10.0

8.10.0 (2024-10-17)

🚀 Features

  • support TypeScript 5.6 (#9972)

🩹 Fixes

  • typescript-eslint: propagate name field to extended configs in config helper (#10094)

❤️ Thank You

You can read about our versioning strategy and releases on our website.

v8.9.0

8.9.0 (2024-10-14)

🚀 Features

  • rule-tester: hooks for test cases (#10109)

🩹 Fixes

  • eslint-plugin: [no-unnecessary-type-parameters] cannot assume variables are either type or value (#10093)
  • eslint-plugin: [return-await] sync the behavior with await-thenable (#10069)
  • eslint-plugin: [prefer-literal-enum-member] report a different error message when allowBitwiseExpressions is enabled (#10096)
  • eslint-plugin: [no-loop-func] sync from upstream base rule (#10103)
  • eslint-plugin: [no-unused-vars] never report the naming of an enum member (#10117)
  • eslint-plugin: correct use-at-your-own-risk type definitions (#10049)
  • eslint-plugin: handle unions in await...for (#10110)
  • rule-tester: merge provided linterOptions (#10131)
  • scope-manager: [no-use-before-define] do not treat nested namespace aliases as variable references (#10095)
  • typescript-estree: improve project service error message when file extension missing from extraFileExtensions (#10076)
  • visitor-keys: reorder TSSatisfiesExpression and TSTypeAssertion (#10139)

❤️ Thank You

... (truncated)

Changelog

Sourced from typescript-eslint's changelog.

8.10.0 (2024-10-17)

🩹 Fixes

  • typescript-eslint: propagate name field to extended configs in config helper (#10094)

❤️ Thank You

You can read about our versioning strategy and releases on our website.

8.9.0 (2024-10-14)

This was a version bump only for typescript-eslint to align it with other projects, there were no code changes.

You can read about our versioning strategy and releases on our website.

Commits
  • 7effdea chore(release): publish 8.10.0
  • be5bc0f fix(typescript-eslint): propagate name field to extended configs in `config...
  • 4666ed4 chore(release): publish 8.9.0
  • See full diff in compare view

Updates `vite` from 5.4.8 to 5.4.9
Release notes

Sourced from vite's releases.

v5.4.9

Please refer to CHANGELOG.md for details.

Changelog

Sourced from vite's changelog.

5.4.9 (2024-10-14)

Commits

Updates `vitest` from 2.1.2 to 2.1.3
Release notes

Sourced from vitest's releases.

v2.1.3

   🐞 Bug Fixes

   🏎 Performance

    View changes on GitHub
Commits
  • 4c03a0d chore: release v2.1.3
  • 70baaaa fix(vitest): use fast-glob instead of tinyglobby in Vitest (#6688)
  • 19d64e2 fix(vitest): always inline setup files (#6689)
  • 47dde76 fix(vitest): show rollup error details as test error (#6686)
  • 7155cee refactor(coverage): move re-usable parts to base provider (#6665)
  • 7a0de0a perf: reuse full name in reported tasks, update generator types (#6666)
  • 8bef5d2 fix(browser): not.toBeInTheDocument works with locators API (#6634)
  • 9ece395 fix(vitest): fix \<empty line> logs when interleaving console.log/error (#...
  • 000459a fix(vitest): deprecate old task types and node-reliant types (#6632)
  • 946d8bb fix(vitest): don't hang with maxConcurrency 0 (#6627)
  • Additional commits viewable in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 12 +-- yarn.lock | 276 +++++++++++++++++++++++++-------------------------- 2 files changed, 143 insertions(+), 145 deletions(-) diff --git a/package.json b/package.json index 9d2e150c6..3548deaba 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@types/css-tree": "^2", "@types/debug": "^4", "@types/electron": "^1.6.10", - "@types/node": "^22.7.5", + "@types/node": "^22.7.6", "@types/papaparse": "^5", "@types/pngjs": "^6.0.5", "@types/react": "^18.3.11", @@ -54,7 +54,7 @@ "@types/uuid": "^10.0.0", "@types/ws": "^8", "@vitejs/plugin-react-swc": "^3.7.1", - "@vitest/coverage-istanbul": "^2.1.2", + "@vitest/coverage-istanbul": "^2.1.3", "electron": "^32.2.0", "electron-builder": "^25.1.7", "electron-vite": "^2.3.0", @@ -69,16 +69,16 @@ "storybook": "^8.3.6", "storybook-dark-mode": "^4.0.2", "ts-node": "^10.9.2", - "tslib": "^2.6.3", + "tslib": "^2.8.0", "tsx": "^4.19.1", "typescript": "^5.6.3", - "typescript-eslint": "^8.8.1", - "vite": "^5.4.8", + "typescript-eslint": "^8.10.0", + "vite": "^5.4.9", "vite-plugin-image-optimizer": "^1.1.8", "vite-plugin-static-copy": "^2.0.0", "vite-plugin-svgr": "^4.2.0", "vite-tsconfig-paths": "^5.0.1", - "vitest": "^2.1.2" + "vitest": "^2.1.3" }, "dependencies": { "@floating-ui/react": "^0.26.24", diff --git a/yarn.lock b/yarn.lock index 5bc38825f..09d61851b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2714,12 +2714,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^22.7.5": - version: 22.7.5 - resolution: "@types/node@npm:22.7.5" +"@types/node@npm:^22.7.6": + version: 22.7.6 + resolution: "@types/node@npm:22.7.6" dependencies: undici-types: "npm:~6.19.2" - checksum: 10c0/cf11f74f1a26053ec58066616e3a8685b6bcd7259bc569738b8f752009f9f0f7f85a1b2d24908e5b0f752482d1e8b6babdf1fbb25758711ec7bb9500bfcd6e60 + checksum: 10c0/d4406a63afce981c363fb1d1954aaf1759ad2d487c0833ebf667565ea4e45ff217d6fab4b5343badbdeccdf9d2e4a0841d633e0c929ceabcb33c288663dd0c73 languageName: node linkType: hard @@ -2950,15 +2950,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/eslint-plugin@npm:8.8.1" +"@typescript-eslint/eslint-plugin@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.10.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.8.1" - "@typescript-eslint/type-utils": "npm:8.8.1" - "@typescript-eslint/utils": "npm:8.8.1" - "@typescript-eslint/visitor-keys": "npm:8.8.1" + "@typescript-eslint/scope-manager": "npm:8.10.0" + "@typescript-eslint/type-utils": "npm:8.10.0" + "@typescript-eslint/utils": "npm:8.10.0" + "@typescript-eslint/visitor-keys": "npm:8.10.0" graphemer: "npm:^1.4.0" ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" @@ -2969,66 +2969,66 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/020a0a482202b34c6665a56ec5902e38ae1870b2600ec1b2092de352b23099dde553781ee8323974f63962ebe164a6304f0019e937afb5cf7854b0e0163ad1ca + checksum: 10c0/4b77ba9c865a2a14e238cd330b5901f0274b8ce1c13324fccd0339b8eea82a50a4709394c903fd8cd5bd0d3aebace0761ff9a4a19fa20b00bb61349b7671c035 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/parser@npm:8.8.1" +"@typescript-eslint/parser@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/parser@npm:8.10.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.8.1" - "@typescript-eslint/types": "npm:8.8.1" - "@typescript-eslint/typescript-estree": "npm:8.8.1" - "@typescript-eslint/visitor-keys": "npm:8.8.1" + "@typescript-eslint/scope-manager": "npm:8.10.0" + "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/typescript-estree": "npm:8.10.0" + "@typescript-eslint/visitor-keys": "npm:8.10.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/2afd147ccec6754316d6837d6108a5d822eb6071e1a7355073288c232530bc3e49901d3f08755ce02d497110c531f3b3658eb46d0ff875a69d4f360b5f938cb4 + checksum: 10c0/7becb2457c085c239838d301796074b790f46dd38c9fbc14ec1dec8e993c7115cd8a66cdc07983c3a68a2dd92e24e8acc49d69a4ebcc29e9869957eb52d1cb74 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/scope-manager@npm:8.8.1" +"@typescript-eslint/scope-manager@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/scope-manager@npm:8.10.0" dependencies: - "@typescript-eslint/types": "npm:8.8.1" - "@typescript-eslint/visitor-keys": "npm:8.8.1" - checksum: 10c0/6f697baf087aedc3f0f228ff964fd108a9dd33fe4e5cc6c914be6367c324cee55629e099832668042bedfec8cdc72c6ef2ca960ee26966dbcc75753059a1352f + "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/visitor-keys": "npm:8.10.0" + checksum: 10c0/b8bb8635c4d6c00a3578d6265e3ee0f5d96d0c9dee534ed588aa411c3f4497fd71cce730c3ae7571e52453d955b191bc9edcc47c9af21a20c90e9a20f2371108 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/type-utils@npm:8.8.1" +"@typescript-eslint/type-utils@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/type-utils@npm:8.10.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:8.8.1" - "@typescript-eslint/utils": "npm:8.8.1" + "@typescript-eslint/typescript-estree": "npm:8.10.0" + "@typescript-eslint/utils": "npm:8.10.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.3.0" peerDependenciesMeta: typescript: optional: true - checksum: 10c0/6edfc2b9fca5233dd922141f080377b677db1093ec3e702a3ab52d58f77b91c0fb69479d4d42f125536b8fc0ffa85c07c7de2f17cc4c6fa1df1226ec01e5608c + checksum: 10c0/1af8fce8394279e6ac7bcef449a132072ee36e374c8d557564246ffe7150230844901ca0305e29525bf37c87010e03bf8bedec76fccbfe1e41931cb4f274e208 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/types@npm:8.8.1" - checksum: 10c0/4b44857332a0b1bfafbeccb8be157f8266d9e226ac723f6af1272b9b670b49444423ddac733655163eb3b90e8c88393a68ab2d7f326f5775371eaf4b9ca31d7b +"@typescript-eslint/types@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/types@npm:8.10.0" + checksum: 10c0/f27dd43c8383e02e914a254257627e393dfc0f08b0f74a253c106813ae361f090271b2f3f2ef588fa3ca1329897d873da595bb5641fe8e3091b25eddca24b5d2 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/typescript-estree@npm:8.8.1" +"@typescript-eslint/typescript-estree@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.10.0" dependencies: - "@typescript-eslint/types": "npm:8.8.1" - "@typescript-eslint/visitor-keys": "npm:8.8.1" + "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/visitor-keys": "npm:8.10.0" debug: "npm:^4.3.4" fast-glob: "npm:^3.3.2" is-glob: "npm:^4.0.3" @@ -3038,31 +3038,31 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/e3b9bc1e925c07833237044271cdc9bd8bdba3e2143dcfc5bf3bf481c89731b666a6fad25333a4b1980ac2f4c6f5e6e42c71206f73f3704e319f6b3b67463a6a + checksum: 10c0/535a740fe25be0e28fe68c41e3264273d1e5169c9f938e08cc0e3415c357726f43efa44621960108c318fc3305c425d29f3223b6e731d44d67f84058a8947304 languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/utils@npm:8.8.1" +"@typescript-eslint/utils@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/utils@npm:8.10.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:8.8.1" - "@typescript-eslint/types": "npm:8.8.1" - "@typescript-eslint/typescript-estree": "npm:8.8.1" + "@typescript-eslint/scope-manager": "npm:8.10.0" + "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/typescript-estree": "npm:8.10.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - checksum: 10c0/954a2e85ae56a3ebefb6e41fb33c59ffa886963860536e9729a35ecea55eefdc58858c7aa126048c4a61f4fd9997b4f7601e7884ed2b3e4e7a46c9e4617a9f29 + checksum: 10c0/a21a2933517176abd00fcd5d8d80023e35dc3d89d5746bbac43790b4e984ab1f371117db08048bce7f42d54c64f4e0e35161149f8f34fd25a27bff9d1110fd16 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/visitor-keys@npm:8.8.1" +"@typescript-eslint/visitor-keys@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.10.0" dependencies: - "@typescript-eslint/types": "npm:8.8.1" + "@typescript-eslint/types": "npm:8.10.0" eslint-visitor-keys: "npm:^3.4.3" - checksum: 10c0/6f917090b61277bd443aa851c532c4a9cc91ad57aedf185c5dff0c530f158cce84ef815833bd8deffa87f0bbf7a9f1abd1e02e30af2463c4e7f27c0c08f59080 + checksum: 10c0/14721c4ac939640d5fd1ee1b6eeb07604b11a6017e319e21dcc71e7aac2992341fc7ae1992d977bad4433b6a1d0d1c0c279e6927316b26245f6e333f922fa458 languageName: node linkType: hard @@ -3084,9 +3084,9 @@ __metadata: languageName: node linkType: hard -"@vitest/coverage-istanbul@npm:^2.1.2": - version: 2.1.2 - resolution: "@vitest/coverage-istanbul@npm:2.1.2" +"@vitest/coverage-istanbul@npm:^2.1.3": + version: 2.1.3 + resolution: "@vitest/coverage-istanbul@npm:2.1.3" dependencies: "@istanbuljs/schema": "npm:^0.1.3" debug: "npm:^4.3.6" @@ -3099,8 +3099,8 @@ __metadata: test-exclude: "npm:^7.0.1" tinyrainbow: "npm:^1.2.0" peerDependencies: - vitest: 2.1.2 - checksum: 10c0/38da5a0ec4f67e83a41b49c6c1861b9bfc4ca8458fd06d96735f2998a105ae42190dbfb41c75549e6b9268dc932dcde8c1323b4df20139fc49d1a42ffab65823 + vitest: 2.1.3 + checksum: 10c0/6b21eb219f45dc0f3bfb35049280658687b6b2f4ba5e17dc2c7e2c221f5d37e60c6962c5cfd77bd5f2848bb56debd26f82e5684b293f5775a8a416a0173f1803 languageName: node linkType: hard @@ -3116,27 +3116,27 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:2.1.2": - version: 2.1.2 - resolution: "@vitest/expect@npm:2.1.2" +"@vitest/expect@npm:2.1.3": + version: 2.1.3 + resolution: "@vitest/expect@npm:2.1.3" dependencies: - "@vitest/spy": "npm:2.1.2" - "@vitest/utils": "npm:2.1.2" + "@vitest/spy": "npm:2.1.3" + "@vitest/utils": "npm:2.1.3" chai: "npm:^5.1.1" tinyrainbow: "npm:^1.2.0" - checksum: 10c0/57233a60685f81ff5cb615156ac164608488c584cb62d7cc63d7ac28674e4c954133d4bb0948e88241c0f07d31803c0d1efd88562c4cac8e1bc5a2b24367ec0f + checksum: 10c0/0837adcbb938feebcc083664afc5c4d12e42f1f2442b6f1bedc6b5650a8ff2448b1f10713b45afb099c839fb5cf766c971736267fa9b0fe2ac87f3e2d7f782c2 languageName: node linkType: hard -"@vitest/mocker@npm:2.1.2": - version: 2.1.2 - resolution: "@vitest/mocker@npm:2.1.2" +"@vitest/mocker@npm:2.1.3": + version: 2.1.3 + resolution: "@vitest/mocker@npm:2.1.3" dependencies: - "@vitest/spy": "npm:^2.1.0-beta.1" + "@vitest/spy": "npm:2.1.3" estree-walker: "npm:^3.0.3" magic-string: "npm:^0.30.11" peerDependencies: - "@vitest/spy": 2.1.2 + "@vitest/spy": 2.1.3 msw: ^2.3.5 vite: ^5.0.0 peerDependenciesMeta: @@ -3144,7 +3144,7 @@ __metadata: optional: true vite: optional: true - checksum: 10c0/24824666d3045bdbbff77481b033d58fd07db6247846c6090cae44b75080e691f743f850300f27f9b0a790c9e3c918848a400cf7c024c9633084c1ad6311d201 + checksum: 10c0/03c80628d092244f21a0ba9041665fc75f987d0d11fab1ae0b7027ec21e503f65057e8c24b936602c5f852d83fbb183da13d05dba117c99785b41b3dafd105ce languageName: node linkType: hard @@ -3166,33 +3166,33 @@ __metadata: languageName: node linkType: hard -"@vitest/pretty-format@npm:2.1.2, @vitest/pretty-format@npm:^2.1.2": - version: 2.1.2 - resolution: "@vitest/pretty-format@npm:2.1.2" +"@vitest/pretty-format@npm:2.1.3, @vitest/pretty-format@npm:^2.1.3": + version: 2.1.3 + resolution: "@vitest/pretty-format@npm:2.1.3" dependencies: tinyrainbow: "npm:^1.2.0" - checksum: 10c0/e2c35dc424450f46794ff420b050e2ce77b3f3d2bdf2509c1adf51d327eeb5cc4ea42fc44919d63b3afdbfcc6da7d7e82962193d0a543c81e0f35ccdfc808835 + checksum: 10c0/5a6ee872a8adf5e2764f2b5b2276d8a2199be4ef14777ab693428caf359481851400af10b59721d4972289c955ffe7277954a662b04cfb10233824574c7074ba languageName: node linkType: hard -"@vitest/runner@npm:2.1.2": - version: 2.1.2 - resolution: "@vitest/runner@npm:2.1.2" +"@vitest/runner@npm:2.1.3": + version: 2.1.3 + resolution: "@vitest/runner@npm:2.1.3" dependencies: - "@vitest/utils": "npm:2.1.2" + "@vitest/utils": "npm:2.1.3" pathe: "npm:^1.1.2" - checksum: 10c0/c6008703ef7b9033b219690a84003c9c078e9de7ace63cefe7c9cd455667d5081c328645e3a538e23fcc221170901d1d1bb0430c4402391d74f8ffab8db62f81 + checksum: 10c0/d5b077643265d10025e22fa64a0e54c3d4fddc23e05f9fcd143dbcc4080851b0df31985986e57890a974577a18d3af624758b6062801d7dd96f9b4f2eaf591f1 languageName: node linkType: hard -"@vitest/snapshot@npm:2.1.2": - version: 2.1.2 - resolution: "@vitest/snapshot@npm:2.1.2" +"@vitest/snapshot@npm:2.1.3": + version: 2.1.3 + resolution: "@vitest/snapshot@npm:2.1.3" dependencies: - "@vitest/pretty-format": "npm:2.1.2" + "@vitest/pretty-format": "npm:2.1.3" magic-string: "npm:^0.30.11" pathe: "npm:^1.1.2" - checksum: 10c0/a05805e9eb9d460830d9f30fbdd488fee4e8bb87dc55e71f5c3541fcd4ef4d333f5c020fd26e8554771157e4e8037d164a63ab5ac0046f7640aca0b8b3fbc837 + checksum: 10c0/a3dcea6a5f7581b6a34dc3bf5f7bd42a05e2ccf6e1171d9f1b759688aebe650e6412564d066aeaa45e83ac549d453b6a3edcf774a8ac728c0c639f8dc919039f languageName: node linkType: hard @@ -3205,21 +3205,12 @@ __metadata: languageName: node linkType: hard -"@vitest/spy@npm:2.1.2": - version: 2.1.2 - resolution: "@vitest/spy@npm:2.1.2" +"@vitest/spy@npm:2.1.3": + version: 2.1.3 + resolution: "@vitest/spy@npm:2.1.3" dependencies: tinyspy: "npm:^3.0.0" - checksum: 10c0/28781abb8c33274bfcf7ab85d4ce47f1583b0a11575fecbdce7b88dac5df5de62c5e11b0b55043e610c0712258b66aee2a8ff2f55068352c61b4a5d2aa9d50ca - languageName: node - linkType: hard - -"@vitest/spy@npm:^2.1.0-beta.1": - version: 2.1.1 - resolution: "@vitest/spy@npm:2.1.1" - dependencies: - tinyspy: "npm:^3.0.0" - checksum: 10c0/b251be1390c105b68aa95270159c4583c3e1a0f7a2e1f82db8b7fadedc3cb459c5ef9286033a1ae764810e00715552fc80afe4507cd8b0065934fb1a64926e06 + checksum: 10c0/8d85a5c2848c5bd81892af989aebad65d0c7ae74094aa98ad4f35ecf80755259c7a748a8e7bf683b2906fac29a51fc0ffa82f8fc073b36dbd8a0418261fccdba languageName: node linkType: hard @@ -3235,14 +3226,14 @@ __metadata: languageName: node linkType: hard -"@vitest/utils@npm:2.1.2": - version: 2.1.2 - resolution: "@vitest/utils@npm:2.1.2" +"@vitest/utils@npm:2.1.3": + version: 2.1.3 + resolution: "@vitest/utils@npm:2.1.3" dependencies: - "@vitest/pretty-format": "npm:2.1.2" + "@vitest/pretty-format": "npm:2.1.3" loupe: "npm:^3.1.1" tinyrainbow: "npm:^1.2.0" - checksum: 10c0/ab1fac69f34c32eb229c4e5f14bec37f16211a77ba16b0e178678d5a67fd74a209c365df0cf7d27bfd6fd2572d563a6b28269d13f958dc083175a6ae2c269085 + checksum: 10c0/55a044e43b84c0f8f573d8578107f26440678b6f506c8d9fee88b7ef120d19efd27c9be77985c107113b0f3f3db298dcee57074e1c1c214bee7a097fd08a209b languageName: node linkType: hard @@ -10975,13 +10966,20 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.4.0, tslib@npm:^2.6.3": +"tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.4.0": version: 2.7.0 resolution: "tslib@npm:2.7.0" checksum: 10c0/469e1d5bf1af585742128827000711efa61010b699cb040ab1800bcd3ccdd37f63ec30642c9e07c4439c1db6e46345582614275daca3e0f4abae29b0083f04a6 languageName: node linkType: hard +"tslib@npm:^2.8.0": + version: 2.8.0 + resolution: "tslib@npm:2.8.0" + checksum: 10c0/31e4d14dc1355e9b89e4d3c893a18abb7f90b6886b089c2da91224d0a7752c79f3ddc41bc1aa0a588ac895bd97bb99c5bc2bfdb2f86de849f31caeb3ba79bbe5 + languageName: node + linkType: hard + "tsx@npm:^4.19.1": version: 4.19.1 resolution: "tsx@npm:4.19.1" @@ -11038,17 +11036,17 @@ __metadata: languageName: node linkType: hard -"typescript-eslint@npm:^8.8.1": - version: 8.8.1 - resolution: "typescript-eslint@npm:8.8.1" +"typescript-eslint@npm:^8.10.0": + version: 8.10.0 + resolution: "typescript-eslint@npm:8.10.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.8.1" - "@typescript-eslint/parser": "npm:8.8.1" - "@typescript-eslint/utils": "npm:8.8.1" + "@typescript-eslint/eslint-plugin": "npm:8.10.0" + "@typescript-eslint/parser": "npm:8.10.0" + "@typescript-eslint/utils": "npm:8.10.0" peerDependenciesMeta: typescript: optional: true - checksum: 10c0/d6793697fce239ef8838ced6e1e59940c30579c8f62c49bc605fdeda9f3f7a5c24bfddd997b142f8c411859dc0b9985ecdae569814dd4f8e6775e1899d55e9cc + checksum: 10c0/9eca1bfdea4e108bea06f0053b57f8a9eaeb43bf3316a39c6d29631bd3217ec67611e46d361417c48a5f6eeb99c4a7fc81c020734b1b47d7b8e42fa67d74ea0f languageName: node linkType: hard @@ -11382,9 +11380,9 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:2.1.2": - version: 2.1.2 - resolution: "vite-node@npm:2.1.2" +"vite-node@npm:2.1.3": + version: 2.1.3 + resolution: "vite-node@npm:2.1.3" dependencies: cac: "npm:^6.7.14" debug: "npm:^4.3.6" @@ -11392,7 +11390,7 @@ __metadata: vite: "npm:^5.0.0" bin: vite-node: vite-node.mjs - checksum: 10c0/7bef84ee757373cc3d171aba51299389e31cb39265df7beef3bb4b70edf1f99425577cd70b9048d357653a0247e8c20f2aa62579d57b2cfc8d74cd6945828b7f + checksum: 10c0/1b06139880a8170651e025e8c35aa92a917f8ec8f24507cda5bf4be09843f6447e1f494932a8d7eb98124f1c8c9fee02283ef318ddd57e2b861d2d85a409a206 languageName: node linkType: hard @@ -11494,9 +11492,9 @@ __metadata: languageName: node linkType: hard -"vite@npm:^5.4.8": - version: 5.4.8 - resolution: "vite@npm:5.4.8" +"vite@npm:^5.4.9": + version: 5.4.9 + resolution: "vite@npm:5.4.9" dependencies: esbuild: "npm:^0.21.3" fsevents: "npm:~2.3.3" @@ -11533,21 +11531,21 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10c0/af70af6d6316a3af71f44ebe3ab343bd66450d4157af73af3b32239e1b6ec43ff6f651d7cc4193b21ed3bff2e9356a3de9e96aee53857f39922e4a2d9fad75a1 + checksum: 10c0/e9c59f2c639047e37c79bbbb151c7a55a3dc27932957cf4cf0447ee0bdcc1ddfd9b1fb3ba0465371c01ba3616d62561327855794c2d652213c3a10a32e6d369d languageName: node linkType: hard -"vitest@npm:^2.1.2": - version: 2.1.2 - resolution: "vitest@npm:2.1.2" +"vitest@npm:^2.1.3": + version: 2.1.3 + resolution: "vitest@npm:2.1.3" dependencies: - "@vitest/expect": "npm:2.1.2" - "@vitest/mocker": "npm:2.1.2" - "@vitest/pretty-format": "npm:^2.1.2" - "@vitest/runner": "npm:2.1.2" - "@vitest/snapshot": "npm:2.1.2" - "@vitest/spy": "npm:2.1.2" - "@vitest/utils": "npm:2.1.2" + "@vitest/expect": "npm:2.1.3" + "@vitest/mocker": "npm:2.1.3" + "@vitest/pretty-format": "npm:^2.1.3" + "@vitest/runner": "npm:2.1.3" + "@vitest/snapshot": "npm:2.1.3" + "@vitest/spy": "npm:2.1.3" + "@vitest/utils": "npm:2.1.3" chai: "npm:^5.1.1" debug: "npm:^4.3.6" magic-string: "npm:^0.30.11" @@ -11558,13 +11556,13 @@ __metadata: tinypool: "npm:^1.0.0" tinyrainbow: "npm:^1.2.0" vite: "npm:^5.0.0" - vite-node: "npm:2.1.2" + vite-node: "npm:2.1.3" why-is-node-running: "npm:^2.3.0" peerDependencies: "@edge-runtime/vm": "*" "@types/node": ^18.0.0 || >=20.0.0 - "@vitest/browser": 2.1.2 - "@vitest/ui": 2.1.2 + "@vitest/browser": 2.1.3 + "@vitest/ui": 2.1.3 happy-dom: "*" jsdom: "*" peerDependenciesMeta: @@ -11582,7 +11580,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: 10c0/79301678bb0207f4bfb16e155e1744ed0b9866c4e1913bb43a3821c01fcda033b7263dac8da87946f90dff6f8f1578a4f94f860409edf0332c3dbfa3a8202803 + checksum: 10c0/7688fdce37205e7f3b448039df216e103e3a52994af0201993e22decbb558d129a734001b991f3c3d80bf4a4ef91ca6a5665a7395d5b051249da60a0016eda36 languageName: node linkType: hard @@ -11658,7 +11656,7 @@ __metadata: "@types/css-tree": "npm:^2" "@types/debug": "npm:^4" "@types/electron": "npm:^1.6.10" - "@types/node": "npm:^22.7.5" + "@types/node": "npm:^22.7.6" "@types/papaparse": "npm:^5" "@types/pngjs": "npm:^6.0.5" "@types/react": "npm:^18.3.11" @@ -11671,7 +11669,7 @@ __metadata: "@types/uuid": "npm:^10.0.0" "@types/ws": "npm:^8" "@vitejs/plugin-react-swc": "npm:^3.7.1" - "@vitest/coverage-istanbul": "npm:^2.1.2" + "@vitest/coverage-istanbul": "npm:^2.1.3" "@xterm/addon-fit": "npm:^0.10.0" "@xterm/addon-serialize": "npm:^0.13.0" "@xterm/addon-web-links": "npm:^0.11.0" @@ -11729,17 +11727,17 @@ __metadata: throttle-debounce: "npm:^5.0.2" tinycolor2: "npm:^1.6.0" ts-node: "npm:^10.9.2" - tslib: "npm:^2.6.3" + tslib: "npm:^2.8.0" tsx: "npm:^4.19.1" typescript: "npm:^5.6.3" - typescript-eslint: "npm:^8.8.1" + typescript-eslint: "npm:^8.10.0" use-device-pixel-ratio: "npm:^1.1.2" - vite: "npm:^5.4.8" + vite: "npm:^5.4.9" vite-plugin-image-optimizer: "npm:^1.1.8" vite-plugin-static-copy: "npm:^2.0.0" vite-plugin-svgr: "npm:^4.2.0" vite-tsconfig-paths: "npm:^5.0.1" - vitest: "npm:^2.1.2" + vitest: "npm:^2.1.3" winston: "npm:^3.15.0" ws: "npm:^8.18.0" yaml: "npm:^2.5.1" From 447e9b737075f50ca5427d51639dbb3f06cb13c0 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:34:13 -0700 Subject: [PATCH 24/34] Bump the prod-dependencies group with 2 updates (#1062) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps the prod-dependencies group with 2 updates: [@floating-ui/react](https://github.com/floating-ui/floating-ui/tree/HEAD/packages/react) and [yaml](https://github.com/eemeli/yaml). Updates `@floating-ui/react` from 0.26.24 to 0.26.25
Release notes

Sourced from @​floating-ui/react's releases.

@​floating-ui/react@​0.26.25

Patch Changes

  • fix(useListNavigation): handle virtual nested Home/End key press
  • fix(useHover): ignore insignificant movement when resetting restMs
  • fix(useListNavigation): ignore duplicate arrow navigation when composing
  • feat(useDelayGroup): add enabled option
  • fix(useDismiss): handle IME keydown events on Escape
  • fix(inner): round max-height only if not scrollable
Changelog

Sourced from @​floating-ui/react's changelog.

0.26.25

Patch Changes

  • fix(useListNavigation): handle virtual nested Home/End key press
  • fix(useHover): ignore insignificant movement when resetting restMs
  • fix(useListNavigation): ignore duplicate arrow navigation when composing
  • feat(useDelayGroup): add enabled option
  • fix(useDismiss): handle IME keydown events on Escape
  • fix(inner): round max-height only if not scrollable
Commits
  • 1ed123b Version Packages (#3074)
  • 4a0f925 fix(inner): round only if not scrollable (#3081)
  • c0c83b4 feat(useDelayGroup): add enabled option (#3080)
  • 5f4d7fc fix(useListNavigation): handle virtual nested Home/End key press (#3079)
  • 1d3c357 fix(useListNavigation): ignore duplicate arrow navigation when composing (#3078)
  • da6583b fix(useDismiss): handle IME keydown events on Escape (#3075)
  • 98fd203 fix(useHover): ignore insignificant movement when resetting restMs (#3073)
  • See full diff in compare view

Updates `yaml` from 2.5.1 to 2.6.0
Release notes

Sourced from yaml's releases.

v2.6.0

  • Use a proper tag for !!merge << keys (#580)
  • Add stringKeys parse option (#581)
  • Stringify a Document as a Document (#576)
  • Add sponsorship by Manifest
Commits
  • 808fba3 2.6.0
  • 438688f fix: Stringify a Document as a Document (fixes #576)
  • baaabd0 feat: Add stringKeys parse option (#581)
  • f2fa108 docs: Update Manifest logo (#582)
  • f088599 docs: Align logos using the restricted styling available for GitHub readmes
  • dbb8a42 docs: Fix manifest.png reference
  • 28dc0a4 chore: Add sponsorship by Manifest
  • 1491c20 chore: Refresh lockfile
  • 7a434f0 feat: Use a proper tag for !!merge << keys (#580)
  • See full diff in compare view

Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore major version` will close this group update PR and stop Dependabot creating any more for the specific dependency's major version (unless you unignore this specific dependency's major version or upgrade to it yourself) - `@dependabot ignore minor version` will close this group update PR and stop Dependabot creating any more for the specific dependency's minor version (unless you unignore this specific dependency's minor version or upgrade to it yourself) - `@dependabot ignore ` will close this group update PR and stop Dependabot creating any more for the specific dependency (unless you unignore this specific dependency or upgrade to it yourself) - `@dependabot unignore ` will remove all of the ignore conditions of the specified dependency - `@dependabot unignore ` will remove the ignore condition of the specified dependency and ignore conditions
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- package.json | 4 ++-- yarn.lock | 23 +++++++---------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 3548deaba..56d3a76e9 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "vitest": "^2.1.3" }, "dependencies": { - "@floating-ui/react": "^0.26.24", + "@floating-ui/react": "^0.26.25", "@monaco-editor/loader": "^1.4.0", "@monaco-editor/react": "^4.6.0", "@observablehq/plot": "^0.6.16", @@ -136,7 +136,7 @@ "use-device-pixel-ratio": "^1.1.2", "winston": "^3.15.0", "ws": "^8.18.0", - "yaml": "^2.5.1" + "yaml": "^2.6.0" }, "resolutions": { "send@npm:0.18.0": "0.19.0", diff --git a/yarn.lock b/yarn.lock index 09d61851b..f63fa4aa4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -847,9 +847,9 @@ __metadata: languageName: node linkType: hard -"@floating-ui/react@npm:^0.26.24": - version: 0.26.24 - resolution: "@floating-ui/react@npm:0.26.24" +"@floating-ui/react@npm:^0.26.25": + version: 0.26.25 + resolution: "@floating-ui/react@npm:0.26.25" dependencies: "@floating-ui/react-dom": "npm:^2.1.2" "@floating-ui/utils": "npm:^0.2.8" @@ -857,7 +857,7 @@ __metadata: peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: 10c0/c5c3ac265802087673a69b0e08b3bea1ee02de9da4cdbc40bb1c9e06823be72628a82f1655b40d56a4383715b4ab3b6deddff4e69146f513970ee592e1dd8f92 + checksum: 10c0/5206b06a5963e795af2f0b0a6ac39230012263ffa38dd60158e0f0b82d43a24e6a1c005fc8556ee5fe26e6353546ffb72e54716f6bd584fdab516dc128a78995 languageName: node linkType: hard @@ -11635,7 +11635,7 @@ __metadata: dependencies: "@chromatic-com/storybook": "npm:^2.0.2" "@eslint/js": "npm:^9.12.0" - "@floating-ui/react": "npm:^0.26.24" + "@floating-ui/react": "npm:^0.26.25" "@monaco-editor/loader": "npm:^1.4.0" "@monaco-editor/react": "npm:^4.6.0" "@observablehq/plot": "npm:^0.6.16" @@ -11740,7 +11740,7 @@ __metadata: vitest: "npm:^2.1.3" winston: "npm:^3.15.0" ws: "npm:^8.18.0" - yaml: "npm:^2.5.1" + yaml: "npm:^2.6.0" languageName: unknown linkType: soft @@ -11939,7 +11939,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.0.0": +"yaml@npm:^2.0.0, yaml@npm:^2.6.0": version: 2.6.0 resolution: "yaml@npm:2.6.0" bin: @@ -11948,15 +11948,6 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.5.1": - version: 2.5.1 - resolution: "yaml@npm:2.5.1" - bin: - yaml: bin.mjs - checksum: 10c0/40fba5682898dbeeb3319e358a968fe886509fab6f58725732a15f8dda3abac509f91e76817c708c9959a15f786f38ff863c1b88062d7c1162c5334a7d09cb4a - languageName: node - linkType: hard - "yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" From 0e3d7c69d258fa413f1d53f4a651f1c21a4d4a6b Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 12:34:24 -0700 Subject: [PATCH 25/34] Bump github.com/sashabaranov/go-openai from 1.32.0 to 1.32.2 (#1059) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [github.com/sashabaranov/go-openai](https://github.com/sashabaranov/go-openai) from 1.32.0 to 1.32.2.
Release notes

Sourced from github.com/sashabaranov/go-openai's releases.

v1.32.2

What's Changed

New Contributors

Full Changelog: https://github.com/sashabaranov/go-openai/compare/v1.32.1...v1.32.2

v1.32.1

What's Changed

New Contributors

Full Changelog: https://github.com/sashabaranov/go-openai/compare/v1.32.0...v1.32.1

Commits

[![Dependabot compatibility score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=github.com/sashabaranov/go-openai&package-manager=go_modules&previous-version=1.32.0&new-version=1.32.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores) Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`. [//]: # (dependabot-automerge-start) [//]: # (dependabot-automerge-end) ---
Dependabot commands and options
You can trigger Dependabot actions by commenting on this PR: - `@dependabot rebase` will rebase this PR - `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it - `@dependabot merge` will merge this PR after your CI passes on it - `@dependabot squash and merge` will squash and merge this PR after your CI passes on it - `@dependabot cancel merge` will cancel a previously requested merge and block automerging - `@dependabot reopen` will reopen this PR if it is closed - `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually - `@dependabot show ignore conditions` will show all of the ignore conditions of the specified dependency - `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself) - `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d1e5b4466..202dccedf 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/kevinburke/ssh_config v1.2.0 github.com/mattn/go-sqlite3 v1.14.24 github.com/mitchellh/mapstructure v1.5.0 - github.com/sashabaranov/go-openai v1.32.0 + github.com/sashabaranov/go-openai v1.32.2 github.com/sawka/txwrap v0.2.0 github.com/shirou/gopsutil/v4 v4.24.9 github.com/skeema/knownhosts v1.3.0 diff --git a/go.sum b/go.sum index ae94a83f4..590fed68d 100644 --- a/go.sum +++ b/go.sum @@ -56,8 +56,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sashabaranov/go-openai v1.32.0 h1:Yk3iE9moX3RBXxrof3OBtUBrE7qZR0zF9ebsoO4zVzI= -github.com/sashabaranov/go-openai v1.32.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= +github.com/sashabaranov/go-openai v1.32.2 h1:8z9PfYaLPbRzmJIYpwcWu6z3XU8F+RwVMF1QRSeSF2M= +github.com/sashabaranov/go-openai v1.32.2/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/sawka/txwrap v0.2.0 h1:V3LfvKVLULxcYSxdMguLwFyQFMEU9nFDJopg0ZkL+94= github.com/sawka/txwrap v0.2.0/go.mod h1:wwQ2SQiN4U+6DU/iVPhbvr7OzXAtgZlQCIGuvOswEfA= github.com/shirou/gopsutil/v4 v4.24.9 h1:KIV+/HaHD5ka5f570RZq+2SaeFsb/pq+fp2DGNWYoOI= From 205d33e7f5d09cc443d6c3ba6f4248a5ca7f3aa7 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Fri, 18 Oct 2024 12:49:15 -0700 Subject: [PATCH 26/34] Revert "Bump the prod-dependencies group with 2 updates" (#1071) Reverts wavetermdev/waveterm#1062, Will reapply after 0.8.12 --- package.json | 4 ++-- yarn.lock | 23 ++++++++++++++++------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 56d3a76e9..3548deaba 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "vitest": "^2.1.3" }, "dependencies": { - "@floating-ui/react": "^0.26.25", + "@floating-ui/react": "^0.26.24", "@monaco-editor/loader": "^1.4.0", "@monaco-editor/react": "^4.6.0", "@observablehq/plot": "^0.6.16", @@ -136,7 +136,7 @@ "use-device-pixel-ratio": "^1.1.2", "winston": "^3.15.0", "ws": "^8.18.0", - "yaml": "^2.6.0" + "yaml": "^2.5.1" }, "resolutions": { "send@npm:0.18.0": "0.19.0", diff --git a/yarn.lock b/yarn.lock index f63fa4aa4..09d61851b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -847,9 +847,9 @@ __metadata: languageName: node linkType: hard -"@floating-ui/react@npm:^0.26.25": - version: 0.26.25 - resolution: "@floating-ui/react@npm:0.26.25" +"@floating-ui/react@npm:^0.26.24": + version: 0.26.24 + resolution: "@floating-ui/react@npm:0.26.24" dependencies: "@floating-ui/react-dom": "npm:^2.1.2" "@floating-ui/utils": "npm:^0.2.8" @@ -857,7 +857,7 @@ __metadata: peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: 10c0/5206b06a5963e795af2f0b0a6ac39230012263ffa38dd60158e0f0b82d43a24e6a1c005fc8556ee5fe26e6353546ffb72e54716f6bd584fdab516dc128a78995 + checksum: 10c0/c5c3ac265802087673a69b0e08b3bea1ee02de9da4cdbc40bb1c9e06823be72628a82f1655b40d56a4383715b4ab3b6deddff4e69146f513970ee592e1dd8f92 languageName: node linkType: hard @@ -11635,7 +11635,7 @@ __metadata: dependencies: "@chromatic-com/storybook": "npm:^2.0.2" "@eslint/js": "npm:^9.12.0" - "@floating-ui/react": "npm:^0.26.25" + "@floating-ui/react": "npm:^0.26.24" "@monaco-editor/loader": "npm:^1.4.0" "@monaco-editor/react": "npm:^4.6.0" "@observablehq/plot": "npm:^0.6.16" @@ -11740,7 +11740,7 @@ __metadata: vitest: "npm:^2.1.3" winston: "npm:^3.15.0" ws: "npm:^8.18.0" - yaml: "npm:^2.6.0" + yaml: "npm:^2.5.1" languageName: unknown linkType: soft @@ -11939,7 +11939,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.0.0, yaml@npm:^2.6.0": +"yaml@npm:^2.0.0": version: 2.6.0 resolution: "yaml@npm:2.6.0" bin: @@ -11948,6 +11948,15 @@ __metadata: languageName: node linkType: hard +"yaml@npm:^2.5.1": + version: 2.5.1 + resolution: "yaml@npm:2.5.1" + bin: + yaml: bin.mjs + checksum: 10c0/40fba5682898dbeeb3319e358a968fe886509fab6f58725732a15f8dda3abac509f91e76817c708c9959a15f786f38ff863c1b88062d7c1162c5334a7d09cb4a + languageName: node + linkType: hard + "yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1" From 6045c1f42892586bf8ff1792a5878555d14a2854 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Fri, 18 Oct 2024 12:49:23 -0700 Subject: [PATCH 27/34] Revert "Bump the dev-dependencies group with 6 updates" (#1070) Reverts wavetermdev/waveterm#1060, Will reapply after 0.8.12 --- package.json | 12 +-- yarn.lock | 276 ++++++++++++++++++++++++++------------------------- 2 files changed, 145 insertions(+), 143 deletions(-) diff --git a/package.json b/package.json index 3548deaba..9d2e150c6 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@types/css-tree": "^2", "@types/debug": "^4", "@types/electron": "^1.6.10", - "@types/node": "^22.7.6", + "@types/node": "^22.7.5", "@types/papaparse": "^5", "@types/pngjs": "^6.0.5", "@types/react": "^18.3.11", @@ -54,7 +54,7 @@ "@types/uuid": "^10.0.0", "@types/ws": "^8", "@vitejs/plugin-react-swc": "^3.7.1", - "@vitest/coverage-istanbul": "^2.1.3", + "@vitest/coverage-istanbul": "^2.1.2", "electron": "^32.2.0", "electron-builder": "^25.1.7", "electron-vite": "^2.3.0", @@ -69,16 +69,16 @@ "storybook": "^8.3.6", "storybook-dark-mode": "^4.0.2", "ts-node": "^10.9.2", - "tslib": "^2.8.0", + "tslib": "^2.6.3", "tsx": "^4.19.1", "typescript": "^5.6.3", - "typescript-eslint": "^8.10.0", - "vite": "^5.4.9", + "typescript-eslint": "^8.8.1", + "vite": "^5.4.8", "vite-plugin-image-optimizer": "^1.1.8", "vite-plugin-static-copy": "^2.0.0", "vite-plugin-svgr": "^4.2.0", "vite-tsconfig-paths": "^5.0.1", - "vitest": "^2.1.3" + "vitest": "^2.1.2" }, "dependencies": { "@floating-ui/react": "^0.26.24", diff --git a/yarn.lock b/yarn.lock index 09d61851b..5bc38825f 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2714,12 +2714,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^22.7.6": - version: 22.7.6 - resolution: "@types/node@npm:22.7.6" +"@types/node@npm:^22.7.5": + version: 22.7.5 + resolution: "@types/node@npm:22.7.5" dependencies: undici-types: "npm:~6.19.2" - checksum: 10c0/d4406a63afce981c363fb1d1954aaf1759ad2d487c0833ebf667565ea4e45ff217d6fab4b5343badbdeccdf9d2e4a0841d633e0c929ceabcb33c288663dd0c73 + checksum: 10c0/cf11f74f1a26053ec58066616e3a8685b6bcd7259bc569738b8f752009f9f0f7f85a1b2d24908e5b0f752482d1e8b6babdf1fbb25758711ec7bb9500bfcd6e60 languageName: node linkType: hard @@ -2950,15 +2950,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.10.0": - version: 8.10.0 - resolution: "@typescript-eslint/eslint-plugin@npm:8.10.0" +"@typescript-eslint/eslint-plugin@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/eslint-plugin@npm:8.8.1" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.10.0" - "@typescript-eslint/type-utils": "npm:8.10.0" - "@typescript-eslint/utils": "npm:8.10.0" - "@typescript-eslint/visitor-keys": "npm:8.10.0" + "@typescript-eslint/scope-manager": "npm:8.8.1" + "@typescript-eslint/type-utils": "npm:8.8.1" + "@typescript-eslint/utils": "npm:8.8.1" + "@typescript-eslint/visitor-keys": "npm:8.8.1" graphemer: "npm:^1.4.0" ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" @@ -2969,66 +2969,66 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/4b77ba9c865a2a14e238cd330b5901f0274b8ce1c13324fccd0339b8eea82a50a4709394c903fd8cd5bd0d3aebace0761ff9a4a19fa20b00bb61349b7671c035 + checksum: 10c0/020a0a482202b34c6665a56ec5902e38ae1870b2600ec1b2092de352b23099dde553781ee8323974f63962ebe164a6304f0019e937afb5cf7854b0e0163ad1ca languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.10.0": - version: 8.10.0 - resolution: "@typescript-eslint/parser@npm:8.10.0" +"@typescript-eslint/parser@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/parser@npm:8.8.1" dependencies: - "@typescript-eslint/scope-manager": "npm:8.10.0" - "@typescript-eslint/types": "npm:8.10.0" - "@typescript-eslint/typescript-estree": "npm:8.10.0" - "@typescript-eslint/visitor-keys": "npm:8.10.0" + "@typescript-eslint/scope-manager": "npm:8.8.1" + "@typescript-eslint/types": "npm:8.8.1" + "@typescript-eslint/typescript-estree": "npm:8.8.1" + "@typescript-eslint/visitor-keys": "npm:8.8.1" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/7becb2457c085c239838d301796074b790f46dd38c9fbc14ec1dec8e993c7115cd8a66cdc07983c3a68a2dd92e24e8acc49d69a4ebcc29e9869957eb52d1cb74 + checksum: 10c0/2afd147ccec6754316d6837d6108a5d822eb6071e1a7355073288c232530bc3e49901d3f08755ce02d497110c531f3b3658eb46d0ff875a69d4f360b5f938cb4 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.10.0": - version: 8.10.0 - resolution: "@typescript-eslint/scope-manager@npm:8.10.0" +"@typescript-eslint/scope-manager@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/scope-manager@npm:8.8.1" dependencies: - "@typescript-eslint/types": "npm:8.10.0" - "@typescript-eslint/visitor-keys": "npm:8.10.0" - checksum: 10c0/b8bb8635c4d6c00a3578d6265e3ee0f5d96d0c9dee534ed588aa411c3f4497fd71cce730c3ae7571e52453d955b191bc9edcc47c9af21a20c90e9a20f2371108 + "@typescript-eslint/types": "npm:8.8.1" + "@typescript-eslint/visitor-keys": "npm:8.8.1" + checksum: 10c0/6f697baf087aedc3f0f228ff964fd108a9dd33fe4e5cc6c914be6367c324cee55629e099832668042bedfec8cdc72c6ef2ca960ee26966dbcc75753059a1352f languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.10.0": - version: 8.10.0 - resolution: "@typescript-eslint/type-utils@npm:8.10.0" +"@typescript-eslint/type-utils@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/type-utils@npm:8.8.1" dependencies: - "@typescript-eslint/typescript-estree": "npm:8.10.0" - "@typescript-eslint/utils": "npm:8.10.0" + "@typescript-eslint/typescript-estree": "npm:8.8.1" + "@typescript-eslint/utils": "npm:8.8.1" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.3.0" peerDependenciesMeta: typescript: optional: true - checksum: 10c0/1af8fce8394279e6ac7bcef449a132072ee36e374c8d557564246ffe7150230844901ca0305e29525bf37c87010e03bf8bedec76fccbfe1e41931cb4f274e208 + checksum: 10c0/6edfc2b9fca5233dd922141f080377b677db1093ec3e702a3ab52d58f77b91c0fb69479d4d42f125536b8fc0ffa85c07c7de2f17cc4c6fa1df1226ec01e5608c languageName: node linkType: hard -"@typescript-eslint/types@npm:8.10.0": - version: 8.10.0 - resolution: "@typescript-eslint/types@npm:8.10.0" - checksum: 10c0/f27dd43c8383e02e914a254257627e393dfc0f08b0f74a253c106813ae361f090271b2f3f2ef588fa3ca1329897d873da595bb5641fe8e3091b25eddca24b5d2 +"@typescript-eslint/types@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/types@npm:8.8.1" + checksum: 10c0/4b44857332a0b1bfafbeccb8be157f8266d9e226ac723f6af1272b9b670b49444423ddac733655163eb3b90e8c88393a68ab2d7f326f5775371eaf4b9ca31d7b languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.10.0": - version: 8.10.0 - resolution: "@typescript-eslint/typescript-estree@npm:8.10.0" +"@typescript-eslint/typescript-estree@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/typescript-estree@npm:8.8.1" dependencies: - "@typescript-eslint/types": "npm:8.10.0" - "@typescript-eslint/visitor-keys": "npm:8.10.0" + "@typescript-eslint/types": "npm:8.8.1" + "@typescript-eslint/visitor-keys": "npm:8.8.1" debug: "npm:^4.3.4" fast-glob: "npm:^3.3.2" is-glob: "npm:^4.0.3" @@ -3038,31 +3038,31 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/535a740fe25be0e28fe68c41e3264273d1e5169c9f938e08cc0e3415c357726f43efa44621960108c318fc3305c425d29f3223b6e731d44d67f84058a8947304 + checksum: 10c0/e3b9bc1e925c07833237044271cdc9bd8bdba3e2143dcfc5bf3bf481c89731b666a6fad25333a4b1980ac2f4c6f5e6e42c71206f73f3704e319f6b3b67463a6a languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.10.0": - version: 8.10.0 - resolution: "@typescript-eslint/utils@npm:8.10.0" +"@typescript-eslint/utils@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/utils@npm:8.8.1" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:8.10.0" - "@typescript-eslint/types": "npm:8.10.0" - "@typescript-eslint/typescript-estree": "npm:8.10.0" + "@typescript-eslint/scope-manager": "npm:8.8.1" + "@typescript-eslint/types": "npm:8.8.1" + "@typescript-eslint/typescript-estree": "npm:8.8.1" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - checksum: 10c0/a21a2933517176abd00fcd5d8d80023e35dc3d89d5746bbac43790b4e984ab1f371117db08048bce7f42d54c64f4e0e35161149f8f34fd25a27bff9d1110fd16 + checksum: 10c0/954a2e85ae56a3ebefb6e41fb33c59ffa886963860536e9729a35ecea55eefdc58858c7aa126048c4a61f4fd9997b4f7601e7884ed2b3e4e7a46c9e4617a9f29 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.10.0": - version: 8.10.0 - resolution: "@typescript-eslint/visitor-keys@npm:8.10.0" +"@typescript-eslint/visitor-keys@npm:8.8.1": + version: 8.8.1 + resolution: "@typescript-eslint/visitor-keys@npm:8.8.1" dependencies: - "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/types": "npm:8.8.1" eslint-visitor-keys: "npm:^3.4.3" - checksum: 10c0/14721c4ac939640d5fd1ee1b6eeb07604b11a6017e319e21dcc71e7aac2992341fc7ae1992d977bad4433b6a1d0d1c0c279e6927316b26245f6e333f922fa458 + checksum: 10c0/6f917090b61277bd443aa851c532c4a9cc91ad57aedf185c5dff0c530f158cce84ef815833bd8deffa87f0bbf7a9f1abd1e02e30af2463c4e7f27c0c08f59080 languageName: node linkType: hard @@ -3084,9 +3084,9 @@ __metadata: languageName: node linkType: hard -"@vitest/coverage-istanbul@npm:^2.1.3": - version: 2.1.3 - resolution: "@vitest/coverage-istanbul@npm:2.1.3" +"@vitest/coverage-istanbul@npm:^2.1.2": + version: 2.1.2 + resolution: "@vitest/coverage-istanbul@npm:2.1.2" dependencies: "@istanbuljs/schema": "npm:^0.1.3" debug: "npm:^4.3.6" @@ -3099,8 +3099,8 @@ __metadata: test-exclude: "npm:^7.0.1" tinyrainbow: "npm:^1.2.0" peerDependencies: - vitest: 2.1.3 - checksum: 10c0/6b21eb219f45dc0f3bfb35049280658687b6b2f4ba5e17dc2c7e2c221f5d37e60c6962c5cfd77bd5f2848bb56debd26f82e5684b293f5775a8a416a0173f1803 + vitest: 2.1.2 + checksum: 10c0/38da5a0ec4f67e83a41b49c6c1861b9bfc4ca8458fd06d96735f2998a105ae42190dbfb41c75549e6b9268dc932dcde8c1323b4df20139fc49d1a42ffab65823 languageName: node linkType: hard @@ -3116,27 +3116,27 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:2.1.3": - version: 2.1.3 - resolution: "@vitest/expect@npm:2.1.3" +"@vitest/expect@npm:2.1.2": + version: 2.1.2 + resolution: "@vitest/expect@npm:2.1.2" dependencies: - "@vitest/spy": "npm:2.1.3" - "@vitest/utils": "npm:2.1.3" + "@vitest/spy": "npm:2.1.2" + "@vitest/utils": "npm:2.1.2" chai: "npm:^5.1.1" tinyrainbow: "npm:^1.2.0" - checksum: 10c0/0837adcbb938feebcc083664afc5c4d12e42f1f2442b6f1bedc6b5650a8ff2448b1f10713b45afb099c839fb5cf766c971736267fa9b0fe2ac87f3e2d7f782c2 + checksum: 10c0/57233a60685f81ff5cb615156ac164608488c584cb62d7cc63d7ac28674e4c954133d4bb0948e88241c0f07d31803c0d1efd88562c4cac8e1bc5a2b24367ec0f languageName: node linkType: hard -"@vitest/mocker@npm:2.1.3": - version: 2.1.3 - resolution: "@vitest/mocker@npm:2.1.3" +"@vitest/mocker@npm:2.1.2": + version: 2.1.2 + resolution: "@vitest/mocker@npm:2.1.2" dependencies: - "@vitest/spy": "npm:2.1.3" + "@vitest/spy": "npm:^2.1.0-beta.1" estree-walker: "npm:^3.0.3" magic-string: "npm:^0.30.11" peerDependencies: - "@vitest/spy": 2.1.3 + "@vitest/spy": 2.1.2 msw: ^2.3.5 vite: ^5.0.0 peerDependenciesMeta: @@ -3144,7 +3144,7 @@ __metadata: optional: true vite: optional: true - checksum: 10c0/03c80628d092244f21a0ba9041665fc75f987d0d11fab1ae0b7027ec21e503f65057e8c24b936602c5f852d83fbb183da13d05dba117c99785b41b3dafd105ce + checksum: 10c0/24824666d3045bdbbff77481b033d58fd07db6247846c6090cae44b75080e691f743f850300f27f9b0a790c9e3c918848a400cf7c024c9633084c1ad6311d201 languageName: node linkType: hard @@ -3166,33 +3166,33 @@ __metadata: languageName: node linkType: hard -"@vitest/pretty-format@npm:2.1.3, @vitest/pretty-format@npm:^2.1.3": - version: 2.1.3 - resolution: "@vitest/pretty-format@npm:2.1.3" +"@vitest/pretty-format@npm:2.1.2, @vitest/pretty-format@npm:^2.1.2": + version: 2.1.2 + resolution: "@vitest/pretty-format@npm:2.1.2" dependencies: tinyrainbow: "npm:^1.2.0" - checksum: 10c0/5a6ee872a8adf5e2764f2b5b2276d8a2199be4ef14777ab693428caf359481851400af10b59721d4972289c955ffe7277954a662b04cfb10233824574c7074ba + checksum: 10c0/e2c35dc424450f46794ff420b050e2ce77b3f3d2bdf2509c1adf51d327eeb5cc4ea42fc44919d63b3afdbfcc6da7d7e82962193d0a543c81e0f35ccdfc808835 languageName: node linkType: hard -"@vitest/runner@npm:2.1.3": - version: 2.1.3 - resolution: "@vitest/runner@npm:2.1.3" +"@vitest/runner@npm:2.1.2": + version: 2.1.2 + resolution: "@vitest/runner@npm:2.1.2" dependencies: - "@vitest/utils": "npm:2.1.3" + "@vitest/utils": "npm:2.1.2" pathe: "npm:^1.1.2" - checksum: 10c0/d5b077643265d10025e22fa64a0e54c3d4fddc23e05f9fcd143dbcc4080851b0df31985986e57890a974577a18d3af624758b6062801d7dd96f9b4f2eaf591f1 + checksum: 10c0/c6008703ef7b9033b219690a84003c9c078e9de7ace63cefe7c9cd455667d5081c328645e3a538e23fcc221170901d1d1bb0430c4402391d74f8ffab8db62f81 languageName: node linkType: hard -"@vitest/snapshot@npm:2.1.3": - version: 2.1.3 - resolution: "@vitest/snapshot@npm:2.1.3" +"@vitest/snapshot@npm:2.1.2": + version: 2.1.2 + resolution: "@vitest/snapshot@npm:2.1.2" dependencies: - "@vitest/pretty-format": "npm:2.1.3" + "@vitest/pretty-format": "npm:2.1.2" magic-string: "npm:^0.30.11" pathe: "npm:^1.1.2" - checksum: 10c0/a3dcea6a5f7581b6a34dc3bf5f7bd42a05e2ccf6e1171d9f1b759688aebe650e6412564d066aeaa45e83ac549d453b6a3edcf774a8ac728c0c639f8dc919039f + checksum: 10c0/a05805e9eb9d460830d9f30fbdd488fee4e8bb87dc55e71f5c3541fcd4ef4d333f5c020fd26e8554771157e4e8037d164a63ab5ac0046f7640aca0b8b3fbc837 languageName: node linkType: hard @@ -3205,12 +3205,21 @@ __metadata: languageName: node linkType: hard -"@vitest/spy@npm:2.1.3": - version: 2.1.3 - resolution: "@vitest/spy@npm:2.1.3" +"@vitest/spy@npm:2.1.2": + version: 2.1.2 + resolution: "@vitest/spy@npm:2.1.2" dependencies: tinyspy: "npm:^3.0.0" - checksum: 10c0/8d85a5c2848c5bd81892af989aebad65d0c7ae74094aa98ad4f35ecf80755259c7a748a8e7bf683b2906fac29a51fc0ffa82f8fc073b36dbd8a0418261fccdba + checksum: 10c0/28781abb8c33274bfcf7ab85d4ce47f1583b0a11575fecbdce7b88dac5df5de62c5e11b0b55043e610c0712258b66aee2a8ff2f55068352c61b4a5d2aa9d50ca + languageName: node + linkType: hard + +"@vitest/spy@npm:^2.1.0-beta.1": + version: 2.1.1 + resolution: "@vitest/spy@npm:2.1.1" + dependencies: + tinyspy: "npm:^3.0.0" + checksum: 10c0/b251be1390c105b68aa95270159c4583c3e1a0f7a2e1f82db8b7fadedc3cb459c5ef9286033a1ae764810e00715552fc80afe4507cd8b0065934fb1a64926e06 languageName: node linkType: hard @@ -3226,14 +3235,14 @@ __metadata: languageName: node linkType: hard -"@vitest/utils@npm:2.1.3": - version: 2.1.3 - resolution: "@vitest/utils@npm:2.1.3" +"@vitest/utils@npm:2.1.2": + version: 2.1.2 + resolution: "@vitest/utils@npm:2.1.2" dependencies: - "@vitest/pretty-format": "npm:2.1.3" + "@vitest/pretty-format": "npm:2.1.2" loupe: "npm:^3.1.1" tinyrainbow: "npm:^1.2.0" - checksum: 10c0/55a044e43b84c0f8f573d8578107f26440678b6f506c8d9fee88b7ef120d19efd27c9be77985c107113b0f3f3db298dcee57074e1c1c214bee7a097fd08a209b + checksum: 10c0/ab1fac69f34c32eb229c4e5f14bec37f16211a77ba16b0e178678d5a67fd74a209c365df0cf7d27bfd6fd2572d563a6b28269d13f958dc083175a6ae2c269085 languageName: node linkType: hard @@ -10966,20 +10975,13 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.4.0": +"tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.4.0, tslib@npm:^2.6.3": version: 2.7.0 resolution: "tslib@npm:2.7.0" checksum: 10c0/469e1d5bf1af585742128827000711efa61010b699cb040ab1800bcd3ccdd37f63ec30642c9e07c4439c1db6e46345582614275daca3e0f4abae29b0083f04a6 languageName: node linkType: hard -"tslib@npm:^2.8.0": - version: 2.8.0 - resolution: "tslib@npm:2.8.0" - checksum: 10c0/31e4d14dc1355e9b89e4d3c893a18abb7f90b6886b089c2da91224d0a7752c79f3ddc41bc1aa0a588ac895bd97bb99c5bc2bfdb2f86de849f31caeb3ba79bbe5 - languageName: node - linkType: hard - "tsx@npm:^4.19.1": version: 4.19.1 resolution: "tsx@npm:4.19.1" @@ -11036,17 +11038,17 @@ __metadata: languageName: node linkType: hard -"typescript-eslint@npm:^8.10.0": - version: 8.10.0 - resolution: "typescript-eslint@npm:8.10.0" +"typescript-eslint@npm:^8.8.1": + version: 8.8.1 + resolution: "typescript-eslint@npm:8.8.1" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.10.0" - "@typescript-eslint/parser": "npm:8.10.0" - "@typescript-eslint/utils": "npm:8.10.0" + "@typescript-eslint/eslint-plugin": "npm:8.8.1" + "@typescript-eslint/parser": "npm:8.8.1" + "@typescript-eslint/utils": "npm:8.8.1" peerDependenciesMeta: typescript: optional: true - checksum: 10c0/9eca1bfdea4e108bea06f0053b57f8a9eaeb43bf3316a39c6d29631bd3217ec67611e46d361417c48a5f6eeb99c4a7fc81c020734b1b47d7b8e42fa67d74ea0f + checksum: 10c0/d6793697fce239ef8838ced6e1e59940c30579c8f62c49bc605fdeda9f3f7a5c24bfddd997b142f8c411859dc0b9985ecdae569814dd4f8e6775e1899d55e9cc languageName: node linkType: hard @@ -11380,9 +11382,9 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:2.1.3": - version: 2.1.3 - resolution: "vite-node@npm:2.1.3" +"vite-node@npm:2.1.2": + version: 2.1.2 + resolution: "vite-node@npm:2.1.2" dependencies: cac: "npm:^6.7.14" debug: "npm:^4.3.6" @@ -11390,7 +11392,7 @@ __metadata: vite: "npm:^5.0.0" bin: vite-node: vite-node.mjs - checksum: 10c0/1b06139880a8170651e025e8c35aa92a917f8ec8f24507cda5bf4be09843f6447e1f494932a8d7eb98124f1c8c9fee02283ef318ddd57e2b861d2d85a409a206 + checksum: 10c0/7bef84ee757373cc3d171aba51299389e31cb39265df7beef3bb4b70edf1f99425577cd70b9048d357653a0247e8c20f2aa62579d57b2cfc8d74cd6945828b7f languageName: node linkType: hard @@ -11492,9 +11494,9 @@ __metadata: languageName: node linkType: hard -"vite@npm:^5.4.9": - version: 5.4.9 - resolution: "vite@npm:5.4.9" +"vite@npm:^5.4.8": + version: 5.4.8 + resolution: "vite@npm:5.4.8" dependencies: esbuild: "npm:^0.21.3" fsevents: "npm:~2.3.3" @@ -11531,21 +11533,21 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10c0/e9c59f2c639047e37c79bbbb151c7a55a3dc27932957cf4cf0447ee0bdcc1ddfd9b1fb3ba0465371c01ba3616d62561327855794c2d652213c3a10a32e6d369d + checksum: 10c0/af70af6d6316a3af71f44ebe3ab343bd66450d4157af73af3b32239e1b6ec43ff6f651d7cc4193b21ed3bff2e9356a3de9e96aee53857f39922e4a2d9fad75a1 languageName: node linkType: hard -"vitest@npm:^2.1.3": - version: 2.1.3 - resolution: "vitest@npm:2.1.3" +"vitest@npm:^2.1.2": + version: 2.1.2 + resolution: "vitest@npm:2.1.2" dependencies: - "@vitest/expect": "npm:2.1.3" - "@vitest/mocker": "npm:2.1.3" - "@vitest/pretty-format": "npm:^2.1.3" - "@vitest/runner": "npm:2.1.3" - "@vitest/snapshot": "npm:2.1.3" - "@vitest/spy": "npm:2.1.3" - "@vitest/utils": "npm:2.1.3" + "@vitest/expect": "npm:2.1.2" + "@vitest/mocker": "npm:2.1.2" + "@vitest/pretty-format": "npm:^2.1.2" + "@vitest/runner": "npm:2.1.2" + "@vitest/snapshot": "npm:2.1.2" + "@vitest/spy": "npm:2.1.2" + "@vitest/utils": "npm:2.1.2" chai: "npm:^5.1.1" debug: "npm:^4.3.6" magic-string: "npm:^0.30.11" @@ -11556,13 +11558,13 @@ __metadata: tinypool: "npm:^1.0.0" tinyrainbow: "npm:^1.2.0" vite: "npm:^5.0.0" - vite-node: "npm:2.1.3" + vite-node: "npm:2.1.2" why-is-node-running: "npm:^2.3.0" peerDependencies: "@edge-runtime/vm": "*" "@types/node": ^18.0.0 || >=20.0.0 - "@vitest/browser": 2.1.3 - "@vitest/ui": 2.1.3 + "@vitest/browser": 2.1.2 + "@vitest/ui": 2.1.2 happy-dom: "*" jsdom: "*" peerDependenciesMeta: @@ -11580,7 +11582,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: 10c0/7688fdce37205e7f3b448039df216e103e3a52994af0201993e22decbb558d129a734001b991f3c3d80bf4a4ef91ca6a5665a7395d5b051249da60a0016eda36 + checksum: 10c0/79301678bb0207f4bfb16e155e1744ed0b9866c4e1913bb43a3821c01fcda033b7263dac8da87946f90dff6f8f1578a4f94f860409edf0332c3dbfa3a8202803 languageName: node linkType: hard @@ -11656,7 +11658,7 @@ __metadata: "@types/css-tree": "npm:^2" "@types/debug": "npm:^4" "@types/electron": "npm:^1.6.10" - "@types/node": "npm:^22.7.6" + "@types/node": "npm:^22.7.5" "@types/papaparse": "npm:^5" "@types/pngjs": "npm:^6.0.5" "@types/react": "npm:^18.3.11" @@ -11669,7 +11671,7 @@ __metadata: "@types/uuid": "npm:^10.0.0" "@types/ws": "npm:^8" "@vitejs/plugin-react-swc": "npm:^3.7.1" - "@vitest/coverage-istanbul": "npm:^2.1.3" + "@vitest/coverage-istanbul": "npm:^2.1.2" "@xterm/addon-fit": "npm:^0.10.0" "@xterm/addon-serialize": "npm:^0.13.0" "@xterm/addon-web-links": "npm:^0.11.0" @@ -11727,17 +11729,17 @@ __metadata: throttle-debounce: "npm:^5.0.2" tinycolor2: "npm:^1.6.0" ts-node: "npm:^10.9.2" - tslib: "npm:^2.8.0" + tslib: "npm:^2.6.3" tsx: "npm:^4.19.1" typescript: "npm:^5.6.3" - typescript-eslint: "npm:^8.10.0" + typescript-eslint: "npm:^8.8.1" use-device-pixel-ratio: "npm:^1.1.2" - vite: "npm:^5.4.9" + vite: "npm:^5.4.8" vite-plugin-image-optimizer: "npm:^1.1.8" vite-plugin-static-copy: "npm:^2.0.0" vite-plugin-svgr: "npm:^4.2.0" vite-tsconfig-paths: "npm:^5.0.1" - vitest: "npm:^2.1.3" + vitest: "npm:^2.1.2" winston: "npm:^3.15.0" ws: "npm:^8.18.0" yaml: "npm:^2.5.1" From 89698289dd275f2c7a80e42a4c783407a51e4a53 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Fri, 18 Oct 2024 12:49:35 -0700 Subject: [PATCH 28/34] Revert "Bump github.com/sashabaranov/go-openai from 1.32.0 to 1.32.2" (#1069) Reverts wavetermdev/waveterm#1059, will reapply after 0.8.12 goes out --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 202dccedf..d1e5b4466 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/kevinburke/ssh_config v1.2.0 github.com/mattn/go-sqlite3 v1.14.24 github.com/mitchellh/mapstructure v1.5.0 - github.com/sashabaranov/go-openai v1.32.2 + github.com/sashabaranov/go-openai v1.32.0 github.com/sawka/txwrap v0.2.0 github.com/shirou/gopsutil/v4 v4.24.9 github.com/skeema/knownhosts v1.3.0 diff --git a/go.sum b/go.sum index 590fed68d..ae94a83f4 100644 --- a/go.sum +++ b/go.sum @@ -56,8 +56,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sashabaranov/go-openai v1.32.2 h1:8z9PfYaLPbRzmJIYpwcWu6z3XU8F+RwVMF1QRSeSF2M= -github.com/sashabaranov/go-openai v1.32.2/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= +github.com/sashabaranov/go-openai v1.32.0 h1:Yk3iE9moX3RBXxrof3OBtUBrE7qZR0zF9ebsoO4zVzI= +github.com/sashabaranov/go-openai v1.32.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/sawka/txwrap v0.2.0 h1:V3LfvKVLULxcYSxdMguLwFyQFMEU9nFDJopg0ZkL+94= github.com/sawka/txwrap v0.2.0/go.mod h1:wwQ2SQiN4U+6DU/iVPhbvr7OzXAtgZlQCIGuvOswEfA= github.com/shirou/gopsutil/v4 v4.24.9 h1:KIV+/HaHD5ka5f570RZq+2SaeFsb/pq+fp2DGNWYoOI= From a2beb1e9ad5aa485c517bf7127e3b90bfc77304b Mon Sep 17 00:00:00 2001 From: "wave-builder[bot]" <181805596+wave-builder[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 19:55:27 +0000 Subject: [PATCH 29/34] chore: bump package version to 0.8.12-beta.5 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9d2e150c6..e7c47882e 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "productName": "Wave", "description": "Open-Source AI-Native Terminal Built for Seamless Workflows", "license": "Apache-2.0", - "version": "0.8.12-beta.4", + "version": "0.8.12-beta.5", "homepage": "https://waveterm.dev", "build": { "appId": "dev.commandline.waveterm" From 98400fe6fcdef7b24e7089d6e38b63cd12885a3e Mon Sep 17 00:00:00 2001 From: "wave-builder[bot]" <181805596+wave-builder[bot]@users.noreply.github.com> Date: Fri, 18 Oct 2024 21:01:00 +0000 Subject: [PATCH 30/34] chore: bump package version to 0.8.12 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e7c47882e..31baac886 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,7 @@ "productName": "Wave", "description": "Open-Source AI-Native Terminal Built for Seamless Workflows", "license": "Apache-2.0", - "version": "0.8.12-beta.5", + "version": "0.8.12", "homepage": "https://waveterm.dev", "build": { "appId": "dev.commandline.waveterm" From ab16baed3e6dfe2787741c943f2d80960630edd9 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Fri, 18 Oct 2024 14:27:48 -0700 Subject: [PATCH 31/34] Fix edge case with Wave Proxy AI preset (#1073) If a user has changed the global AI settings and added a different base url, the Wave Proxy preset would not work because it doesn't unset all the AI settings. --- pkg/wconfig/defaultconfig/presets.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/pkg/wconfig/defaultconfig/presets.json b/pkg/wconfig/defaultconfig/presets.json index 38d16d494..30dc05942 100644 --- a/pkg/wconfig/defaultconfig/presets.json +++ b/pkg/wconfig/defaultconfig/presets.json @@ -104,6 +104,11 @@ "display:name": "Wave Proxy - gpt-4o-mini", "display:order": 0, "ai:*": true, + "ai:apitype": "", + "ai:baseurl": "", + "ai:apitoken": "", + "ai:name": "", + "ai:orgid": "", "ai:model": "gpt-4o-mini", "ai:maxtokens": 2048, "ai:timeoutms": 60000 From f56fc982f6a2bf89238d9f9c54bbd4ee9f7b3899 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Fri, 18 Oct 2024 15:31:08 -0700 Subject: [PATCH 32/34] Revert "Revert "Bump github.com/sashabaranov/go-openai from 1.32.0 to 1.32.2"" (#1077) Reverts wavetermdev/waveterm#1069 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d1e5b4466..202dccedf 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/kevinburke/ssh_config v1.2.0 github.com/mattn/go-sqlite3 v1.14.24 github.com/mitchellh/mapstructure v1.5.0 - github.com/sashabaranov/go-openai v1.32.0 + github.com/sashabaranov/go-openai v1.32.2 github.com/sawka/txwrap v0.2.0 github.com/shirou/gopsutil/v4 v4.24.9 github.com/skeema/knownhosts v1.3.0 diff --git a/go.sum b/go.sum index ae94a83f4..590fed68d 100644 --- a/go.sum +++ b/go.sum @@ -56,8 +56,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= -github.com/sashabaranov/go-openai v1.32.0 h1:Yk3iE9moX3RBXxrof3OBtUBrE7qZR0zF9ebsoO4zVzI= -github.com/sashabaranov/go-openai v1.32.0/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= +github.com/sashabaranov/go-openai v1.32.2 h1:8z9PfYaLPbRzmJIYpwcWu6z3XU8F+RwVMF1QRSeSF2M= +github.com/sashabaranov/go-openai v1.32.2/go.mod h1:lj5b/K+zjTSFxVLijLSTDZuP7adOgerWeFyZLUhAKRg= github.com/sawka/txwrap v0.2.0 h1:V3LfvKVLULxcYSxdMguLwFyQFMEU9nFDJopg0ZkL+94= github.com/sawka/txwrap v0.2.0/go.mod h1:wwQ2SQiN4U+6DU/iVPhbvr7OzXAtgZlQCIGuvOswEfA= github.com/shirou/gopsutil/v4 v4.24.9 h1:KIV+/HaHD5ka5f570RZq+2SaeFsb/pq+fp2DGNWYoOI= From abb7c98d5699ac392d329d3599d60d24f5a799e8 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Fri, 18 Oct 2024 15:31:16 -0700 Subject: [PATCH 33/34] Revert "Revert "Bump the dev-dependencies group with 6 updates"" (#1076) Reverts wavetermdev/waveterm#1070 --- package.json | 12 +-- yarn.lock | 276 +++++++++++++++++++++++++-------------------------- 2 files changed, 143 insertions(+), 145 deletions(-) diff --git a/package.json b/package.json index 31baac886..1f00468ea 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "@types/css-tree": "^2", "@types/debug": "^4", "@types/electron": "^1.6.10", - "@types/node": "^22.7.5", + "@types/node": "^22.7.6", "@types/papaparse": "^5", "@types/pngjs": "^6.0.5", "@types/react": "^18.3.11", @@ -54,7 +54,7 @@ "@types/uuid": "^10.0.0", "@types/ws": "^8", "@vitejs/plugin-react-swc": "^3.7.1", - "@vitest/coverage-istanbul": "^2.1.2", + "@vitest/coverage-istanbul": "^2.1.3", "electron": "^32.2.0", "electron-builder": "^25.1.7", "electron-vite": "^2.3.0", @@ -69,16 +69,16 @@ "storybook": "^8.3.6", "storybook-dark-mode": "^4.0.2", "ts-node": "^10.9.2", - "tslib": "^2.6.3", + "tslib": "^2.8.0", "tsx": "^4.19.1", "typescript": "^5.6.3", - "typescript-eslint": "^8.8.1", - "vite": "^5.4.8", + "typescript-eslint": "^8.10.0", + "vite": "^5.4.9", "vite-plugin-image-optimizer": "^1.1.8", "vite-plugin-static-copy": "^2.0.0", "vite-plugin-svgr": "^4.2.0", "vite-tsconfig-paths": "^5.0.1", - "vitest": "^2.1.2" + "vitest": "^2.1.3" }, "dependencies": { "@floating-ui/react": "^0.26.24", diff --git a/yarn.lock b/yarn.lock index 5bc38825f..09d61851b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2714,12 +2714,12 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:^22.7.5": - version: 22.7.5 - resolution: "@types/node@npm:22.7.5" +"@types/node@npm:^22.7.6": + version: 22.7.6 + resolution: "@types/node@npm:22.7.6" dependencies: undici-types: "npm:~6.19.2" - checksum: 10c0/cf11f74f1a26053ec58066616e3a8685b6bcd7259bc569738b8f752009f9f0f7f85a1b2d24908e5b0f752482d1e8b6babdf1fbb25758711ec7bb9500bfcd6e60 + checksum: 10c0/d4406a63afce981c363fb1d1954aaf1759ad2d487c0833ebf667565ea4e45ff217d6fab4b5343badbdeccdf9d2e4a0841d633e0c929ceabcb33c288663dd0c73 languageName: node linkType: hard @@ -2950,15 +2950,15 @@ __metadata: languageName: node linkType: hard -"@typescript-eslint/eslint-plugin@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/eslint-plugin@npm:8.8.1" +"@typescript-eslint/eslint-plugin@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/eslint-plugin@npm:8.10.0" dependencies: "@eslint-community/regexpp": "npm:^4.10.0" - "@typescript-eslint/scope-manager": "npm:8.8.1" - "@typescript-eslint/type-utils": "npm:8.8.1" - "@typescript-eslint/utils": "npm:8.8.1" - "@typescript-eslint/visitor-keys": "npm:8.8.1" + "@typescript-eslint/scope-manager": "npm:8.10.0" + "@typescript-eslint/type-utils": "npm:8.10.0" + "@typescript-eslint/utils": "npm:8.10.0" + "@typescript-eslint/visitor-keys": "npm:8.10.0" graphemer: "npm:^1.4.0" ignore: "npm:^5.3.1" natural-compare: "npm:^1.4.0" @@ -2969,66 +2969,66 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/020a0a482202b34c6665a56ec5902e38ae1870b2600ec1b2092de352b23099dde553781ee8323974f63962ebe164a6304f0019e937afb5cf7854b0e0163ad1ca + checksum: 10c0/4b77ba9c865a2a14e238cd330b5901f0274b8ce1c13324fccd0339b8eea82a50a4709394c903fd8cd5bd0d3aebace0761ff9a4a19fa20b00bb61349b7671c035 languageName: node linkType: hard -"@typescript-eslint/parser@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/parser@npm:8.8.1" +"@typescript-eslint/parser@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/parser@npm:8.10.0" dependencies: - "@typescript-eslint/scope-manager": "npm:8.8.1" - "@typescript-eslint/types": "npm:8.8.1" - "@typescript-eslint/typescript-estree": "npm:8.8.1" - "@typescript-eslint/visitor-keys": "npm:8.8.1" + "@typescript-eslint/scope-manager": "npm:8.10.0" + "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/typescript-estree": "npm:8.10.0" + "@typescript-eslint/visitor-keys": "npm:8.10.0" debug: "npm:^4.3.4" peerDependencies: eslint: ^8.57.0 || ^9.0.0 peerDependenciesMeta: typescript: optional: true - checksum: 10c0/2afd147ccec6754316d6837d6108a5d822eb6071e1a7355073288c232530bc3e49901d3f08755ce02d497110c531f3b3658eb46d0ff875a69d4f360b5f938cb4 + checksum: 10c0/7becb2457c085c239838d301796074b790f46dd38c9fbc14ec1dec8e993c7115cd8a66cdc07983c3a68a2dd92e24e8acc49d69a4ebcc29e9869957eb52d1cb74 languageName: node linkType: hard -"@typescript-eslint/scope-manager@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/scope-manager@npm:8.8.1" +"@typescript-eslint/scope-manager@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/scope-manager@npm:8.10.0" dependencies: - "@typescript-eslint/types": "npm:8.8.1" - "@typescript-eslint/visitor-keys": "npm:8.8.1" - checksum: 10c0/6f697baf087aedc3f0f228ff964fd108a9dd33fe4e5cc6c914be6367c324cee55629e099832668042bedfec8cdc72c6ef2ca960ee26966dbcc75753059a1352f + "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/visitor-keys": "npm:8.10.0" + checksum: 10c0/b8bb8635c4d6c00a3578d6265e3ee0f5d96d0c9dee534ed588aa411c3f4497fd71cce730c3ae7571e52453d955b191bc9edcc47c9af21a20c90e9a20f2371108 languageName: node linkType: hard -"@typescript-eslint/type-utils@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/type-utils@npm:8.8.1" +"@typescript-eslint/type-utils@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/type-utils@npm:8.10.0" dependencies: - "@typescript-eslint/typescript-estree": "npm:8.8.1" - "@typescript-eslint/utils": "npm:8.8.1" + "@typescript-eslint/typescript-estree": "npm:8.10.0" + "@typescript-eslint/utils": "npm:8.10.0" debug: "npm:^4.3.4" ts-api-utils: "npm:^1.3.0" peerDependenciesMeta: typescript: optional: true - checksum: 10c0/6edfc2b9fca5233dd922141f080377b677db1093ec3e702a3ab52d58f77b91c0fb69479d4d42f125536b8fc0ffa85c07c7de2f17cc4c6fa1df1226ec01e5608c + checksum: 10c0/1af8fce8394279e6ac7bcef449a132072ee36e374c8d557564246ffe7150230844901ca0305e29525bf37c87010e03bf8bedec76fccbfe1e41931cb4f274e208 languageName: node linkType: hard -"@typescript-eslint/types@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/types@npm:8.8.1" - checksum: 10c0/4b44857332a0b1bfafbeccb8be157f8266d9e226ac723f6af1272b9b670b49444423ddac733655163eb3b90e8c88393a68ab2d7f326f5775371eaf4b9ca31d7b +"@typescript-eslint/types@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/types@npm:8.10.0" + checksum: 10c0/f27dd43c8383e02e914a254257627e393dfc0f08b0f74a253c106813ae361f090271b2f3f2ef588fa3ca1329897d873da595bb5641fe8e3091b25eddca24b5d2 languageName: node linkType: hard -"@typescript-eslint/typescript-estree@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/typescript-estree@npm:8.8.1" +"@typescript-eslint/typescript-estree@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/typescript-estree@npm:8.10.0" dependencies: - "@typescript-eslint/types": "npm:8.8.1" - "@typescript-eslint/visitor-keys": "npm:8.8.1" + "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/visitor-keys": "npm:8.10.0" debug: "npm:^4.3.4" fast-glob: "npm:^3.3.2" is-glob: "npm:^4.0.3" @@ -3038,31 +3038,31 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10c0/e3b9bc1e925c07833237044271cdc9bd8bdba3e2143dcfc5bf3bf481c89731b666a6fad25333a4b1980ac2f4c6f5e6e42c71206f73f3704e319f6b3b67463a6a + checksum: 10c0/535a740fe25be0e28fe68c41e3264273d1e5169c9f938e08cc0e3415c357726f43efa44621960108c318fc3305c425d29f3223b6e731d44d67f84058a8947304 languageName: node linkType: hard -"@typescript-eslint/utils@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/utils@npm:8.8.1" +"@typescript-eslint/utils@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/utils@npm:8.10.0" dependencies: "@eslint-community/eslint-utils": "npm:^4.4.0" - "@typescript-eslint/scope-manager": "npm:8.8.1" - "@typescript-eslint/types": "npm:8.8.1" - "@typescript-eslint/typescript-estree": "npm:8.8.1" + "@typescript-eslint/scope-manager": "npm:8.10.0" + "@typescript-eslint/types": "npm:8.10.0" + "@typescript-eslint/typescript-estree": "npm:8.10.0" peerDependencies: eslint: ^8.57.0 || ^9.0.0 - checksum: 10c0/954a2e85ae56a3ebefb6e41fb33c59ffa886963860536e9729a35ecea55eefdc58858c7aa126048c4a61f4fd9997b4f7601e7884ed2b3e4e7a46c9e4617a9f29 + checksum: 10c0/a21a2933517176abd00fcd5d8d80023e35dc3d89d5746bbac43790b4e984ab1f371117db08048bce7f42d54c64f4e0e35161149f8f34fd25a27bff9d1110fd16 languageName: node linkType: hard -"@typescript-eslint/visitor-keys@npm:8.8.1": - version: 8.8.1 - resolution: "@typescript-eslint/visitor-keys@npm:8.8.1" +"@typescript-eslint/visitor-keys@npm:8.10.0": + version: 8.10.0 + resolution: "@typescript-eslint/visitor-keys@npm:8.10.0" dependencies: - "@typescript-eslint/types": "npm:8.8.1" + "@typescript-eslint/types": "npm:8.10.0" eslint-visitor-keys: "npm:^3.4.3" - checksum: 10c0/6f917090b61277bd443aa851c532c4a9cc91ad57aedf185c5dff0c530f158cce84ef815833bd8deffa87f0bbf7a9f1abd1e02e30af2463c4e7f27c0c08f59080 + checksum: 10c0/14721c4ac939640d5fd1ee1b6eeb07604b11a6017e319e21dcc71e7aac2992341fc7ae1992d977bad4433b6a1d0d1c0c279e6927316b26245f6e333f922fa458 languageName: node linkType: hard @@ -3084,9 +3084,9 @@ __metadata: languageName: node linkType: hard -"@vitest/coverage-istanbul@npm:^2.1.2": - version: 2.1.2 - resolution: "@vitest/coverage-istanbul@npm:2.1.2" +"@vitest/coverage-istanbul@npm:^2.1.3": + version: 2.1.3 + resolution: "@vitest/coverage-istanbul@npm:2.1.3" dependencies: "@istanbuljs/schema": "npm:^0.1.3" debug: "npm:^4.3.6" @@ -3099,8 +3099,8 @@ __metadata: test-exclude: "npm:^7.0.1" tinyrainbow: "npm:^1.2.0" peerDependencies: - vitest: 2.1.2 - checksum: 10c0/38da5a0ec4f67e83a41b49c6c1861b9bfc4ca8458fd06d96735f2998a105ae42190dbfb41c75549e6b9268dc932dcde8c1323b4df20139fc49d1a42ffab65823 + vitest: 2.1.3 + checksum: 10c0/6b21eb219f45dc0f3bfb35049280658687b6b2f4ba5e17dc2c7e2c221f5d37e60c6962c5cfd77bd5f2848bb56debd26f82e5684b293f5775a8a416a0173f1803 languageName: node linkType: hard @@ -3116,27 +3116,27 @@ __metadata: languageName: node linkType: hard -"@vitest/expect@npm:2.1.2": - version: 2.1.2 - resolution: "@vitest/expect@npm:2.1.2" +"@vitest/expect@npm:2.1.3": + version: 2.1.3 + resolution: "@vitest/expect@npm:2.1.3" dependencies: - "@vitest/spy": "npm:2.1.2" - "@vitest/utils": "npm:2.1.2" + "@vitest/spy": "npm:2.1.3" + "@vitest/utils": "npm:2.1.3" chai: "npm:^5.1.1" tinyrainbow: "npm:^1.2.0" - checksum: 10c0/57233a60685f81ff5cb615156ac164608488c584cb62d7cc63d7ac28674e4c954133d4bb0948e88241c0f07d31803c0d1efd88562c4cac8e1bc5a2b24367ec0f + checksum: 10c0/0837adcbb938feebcc083664afc5c4d12e42f1f2442b6f1bedc6b5650a8ff2448b1f10713b45afb099c839fb5cf766c971736267fa9b0fe2ac87f3e2d7f782c2 languageName: node linkType: hard -"@vitest/mocker@npm:2.1.2": - version: 2.1.2 - resolution: "@vitest/mocker@npm:2.1.2" +"@vitest/mocker@npm:2.1.3": + version: 2.1.3 + resolution: "@vitest/mocker@npm:2.1.3" dependencies: - "@vitest/spy": "npm:^2.1.0-beta.1" + "@vitest/spy": "npm:2.1.3" estree-walker: "npm:^3.0.3" magic-string: "npm:^0.30.11" peerDependencies: - "@vitest/spy": 2.1.2 + "@vitest/spy": 2.1.3 msw: ^2.3.5 vite: ^5.0.0 peerDependenciesMeta: @@ -3144,7 +3144,7 @@ __metadata: optional: true vite: optional: true - checksum: 10c0/24824666d3045bdbbff77481b033d58fd07db6247846c6090cae44b75080e691f743f850300f27f9b0a790c9e3c918848a400cf7c024c9633084c1ad6311d201 + checksum: 10c0/03c80628d092244f21a0ba9041665fc75f987d0d11fab1ae0b7027ec21e503f65057e8c24b936602c5f852d83fbb183da13d05dba117c99785b41b3dafd105ce languageName: node linkType: hard @@ -3166,33 +3166,33 @@ __metadata: languageName: node linkType: hard -"@vitest/pretty-format@npm:2.1.2, @vitest/pretty-format@npm:^2.1.2": - version: 2.1.2 - resolution: "@vitest/pretty-format@npm:2.1.2" +"@vitest/pretty-format@npm:2.1.3, @vitest/pretty-format@npm:^2.1.3": + version: 2.1.3 + resolution: "@vitest/pretty-format@npm:2.1.3" dependencies: tinyrainbow: "npm:^1.2.0" - checksum: 10c0/e2c35dc424450f46794ff420b050e2ce77b3f3d2bdf2509c1adf51d327eeb5cc4ea42fc44919d63b3afdbfcc6da7d7e82962193d0a543c81e0f35ccdfc808835 + checksum: 10c0/5a6ee872a8adf5e2764f2b5b2276d8a2199be4ef14777ab693428caf359481851400af10b59721d4972289c955ffe7277954a662b04cfb10233824574c7074ba languageName: node linkType: hard -"@vitest/runner@npm:2.1.2": - version: 2.1.2 - resolution: "@vitest/runner@npm:2.1.2" +"@vitest/runner@npm:2.1.3": + version: 2.1.3 + resolution: "@vitest/runner@npm:2.1.3" dependencies: - "@vitest/utils": "npm:2.1.2" + "@vitest/utils": "npm:2.1.3" pathe: "npm:^1.1.2" - checksum: 10c0/c6008703ef7b9033b219690a84003c9c078e9de7ace63cefe7c9cd455667d5081c328645e3a538e23fcc221170901d1d1bb0430c4402391d74f8ffab8db62f81 + checksum: 10c0/d5b077643265d10025e22fa64a0e54c3d4fddc23e05f9fcd143dbcc4080851b0df31985986e57890a974577a18d3af624758b6062801d7dd96f9b4f2eaf591f1 languageName: node linkType: hard -"@vitest/snapshot@npm:2.1.2": - version: 2.1.2 - resolution: "@vitest/snapshot@npm:2.1.2" +"@vitest/snapshot@npm:2.1.3": + version: 2.1.3 + resolution: "@vitest/snapshot@npm:2.1.3" dependencies: - "@vitest/pretty-format": "npm:2.1.2" + "@vitest/pretty-format": "npm:2.1.3" magic-string: "npm:^0.30.11" pathe: "npm:^1.1.2" - checksum: 10c0/a05805e9eb9d460830d9f30fbdd488fee4e8bb87dc55e71f5c3541fcd4ef4d333f5c020fd26e8554771157e4e8037d164a63ab5ac0046f7640aca0b8b3fbc837 + checksum: 10c0/a3dcea6a5f7581b6a34dc3bf5f7bd42a05e2ccf6e1171d9f1b759688aebe650e6412564d066aeaa45e83ac549d453b6a3edcf774a8ac728c0c639f8dc919039f languageName: node linkType: hard @@ -3205,21 +3205,12 @@ __metadata: languageName: node linkType: hard -"@vitest/spy@npm:2.1.2": - version: 2.1.2 - resolution: "@vitest/spy@npm:2.1.2" +"@vitest/spy@npm:2.1.3": + version: 2.1.3 + resolution: "@vitest/spy@npm:2.1.3" dependencies: tinyspy: "npm:^3.0.0" - checksum: 10c0/28781abb8c33274bfcf7ab85d4ce47f1583b0a11575fecbdce7b88dac5df5de62c5e11b0b55043e610c0712258b66aee2a8ff2f55068352c61b4a5d2aa9d50ca - languageName: node - linkType: hard - -"@vitest/spy@npm:^2.1.0-beta.1": - version: 2.1.1 - resolution: "@vitest/spy@npm:2.1.1" - dependencies: - tinyspy: "npm:^3.0.0" - checksum: 10c0/b251be1390c105b68aa95270159c4583c3e1a0f7a2e1f82db8b7fadedc3cb459c5ef9286033a1ae764810e00715552fc80afe4507cd8b0065934fb1a64926e06 + checksum: 10c0/8d85a5c2848c5bd81892af989aebad65d0c7ae74094aa98ad4f35ecf80755259c7a748a8e7bf683b2906fac29a51fc0ffa82f8fc073b36dbd8a0418261fccdba languageName: node linkType: hard @@ -3235,14 +3226,14 @@ __metadata: languageName: node linkType: hard -"@vitest/utils@npm:2.1.2": - version: 2.1.2 - resolution: "@vitest/utils@npm:2.1.2" +"@vitest/utils@npm:2.1.3": + version: 2.1.3 + resolution: "@vitest/utils@npm:2.1.3" dependencies: - "@vitest/pretty-format": "npm:2.1.2" + "@vitest/pretty-format": "npm:2.1.3" loupe: "npm:^3.1.1" tinyrainbow: "npm:^1.2.0" - checksum: 10c0/ab1fac69f34c32eb229c4e5f14bec37f16211a77ba16b0e178678d5a67fd74a209c365df0cf7d27bfd6fd2572d563a6b28269d13f958dc083175a6ae2c269085 + checksum: 10c0/55a044e43b84c0f8f573d8578107f26440678b6f506c8d9fee88b7ef120d19efd27c9be77985c107113b0f3f3db298dcee57074e1c1c214bee7a097fd08a209b languageName: node linkType: hard @@ -10975,13 +10966,20 @@ __metadata: languageName: node linkType: hard -"tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.4.0, tslib@npm:^2.6.3": +"tslib@npm:^2.0.1, tslib@npm:^2.0.3, tslib@npm:^2.1.0, tslib@npm:^2.3.0, tslib@npm:^2.4.0": version: 2.7.0 resolution: "tslib@npm:2.7.0" checksum: 10c0/469e1d5bf1af585742128827000711efa61010b699cb040ab1800bcd3ccdd37f63ec30642c9e07c4439c1db6e46345582614275daca3e0f4abae29b0083f04a6 languageName: node linkType: hard +"tslib@npm:^2.8.0": + version: 2.8.0 + resolution: "tslib@npm:2.8.0" + checksum: 10c0/31e4d14dc1355e9b89e4d3c893a18abb7f90b6886b089c2da91224d0a7752c79f3ddc41bc1aa0a588ac895bd97bb99c5bc2bfdb2f86de849f31caeb3ba79bbe5 + languageName: node + linkType: hard + "tsx@npm:^4.19.1": version: 4.19.1 resolution: "tsx@npm:4.19.1" @@ -11038,17 +11036,17 @@ __metadata: languageName: node linkType: hard -"typescript-eslint@npm:^8.8.1": - version: 8.8.1 - resolution: "typescript-eslint@npm:8.8.1" +"typescript-eslint@npm:^8.10.0": + version: 8.10.0 + resolution: "typescript-eslint@npm:8.10.0" dependencies: - "@typescript-eslint/eslint-plugin": "npm:8.8.1" - "@typescript-eslint/parser": "npm:8.8.1" - "@typescript-eslint/utils": "npm:8.8.1" + "@typescript-eslint/eslint-plugin": "npm:8.10.0" + "@typescript-eslint/parser": "npm:8.10.0" + "@typescript-eslint/utils": "npm:8.10.0" peerDependenciesMeta: typescript: optional: true - checksum: 10c0/d6793697fce239ef8838ced6e1e59940c30579c8f62c49bc605fdeda9f3f7a5c24bfddd997b142f8c411859dc0b9985ecdae569814dd4f8e6775e1899d55e9cc + checksum: 10c0/9eca1bfdea4e108bea06f0053b57f8a9eaeb43bf3316a39c6d29631bd3217ec67611e46d361417c48a5f6eeb99c4a7fc81c020734b1b47d7b8e42fa67d74ea0f languageName: node linkType: hard @@ -11382,9 +11380,9 @@ __metadata: languageName: node linkType: hard -"vite-node@npm:2.1.2": - version: 2.1.2 - resolution: "vite-node@npm:2.1.2" +"vite-node@npm:2.1.3": + version: 2.1.3 + resolution: "vite-node@npm:2.1.3" dependencies: cac: "npm:^6.7.14" debug: "npm:^4.3.6" @@ -11392,7 +11390,7 @@ __metadata: vite: "npm:^5.0.0" bin: vite-node: vite-node.mjs - checksum: 10c0/7bef84ee757373cc3d171aba51299389e31cb39265df7beef3bb4b70edf1f99425577cd70b9048d357653a0247e8c20f2aa62579d57b2cfc8d74cd6945828b7f + checksum: 10c0/1b06139880a8170651e025e8c35aa92a917f8ec8f24507cda5bf4be09843f6447e1f494932a8d7eb98124f1c8c9fee02283ef318ddd57e2b861d2d85a409a206 languageName: node linkType: hard @@ -11494,9 +11492,9 @@ __metadata: languageName: node linkType: hard -"vite@npm:^5.4.8": - version: 5.4.8 - resolution: "vite@npm:5.4.8" +"vite@npm:^5.4.9": + version: 5.4.9 + resolution: "vite@npm:5.4.9" dependencies: esbuild: "npm:^0.21.3" fsevents: "npm:~2.3.3" @@ -11533,21 +11531,21 @@ __metadata: optional: true bin: vite: bin/vite.js - checksum: 10c0/af70af6d6316a3af71f44ebe3ab343bd66450d4157af73af3b32239e1b6ec43ff6f651d7cc4193b21ed3bff2e9356a3de9e96aee53857f39922e4a2d9fad75a1 + checksum: 10c0/e9c59f2c639047e37c79bbbb151c7a55a3dc27932957cf4cf0447ee0bdcc1ddfd9b1fb3ba0465371c01ba3616d62561327855794c2d652213c3a10a32e6d369d languageName: node linkType: hard -"vitest@npm:^2.1.2": - version: 2.1.2 - resolution: "vitest@npm:2.1.2" +"vitest@npm:^2.1.3": + version: 2.1.3 + resolution: "vitest@npm:2.1.3" dependencies: - "@vitest/expect": "npm:2.1.2" - "@vitest/mocker": "npm:2.1.2" - "@vitest/pretty-format": "npm:^2.1.2" - "@vitest/runner": "npm:2.1.2" - "@vitest/snapshot": "npm:2.1.2" - "@vitest/spy": "npm:2.1.2" - "@vitest/utils": "npm:2.1.2" + "@vitest/expect": "npm:2.1.3" + "@vitest/mocker": "npm:2.1.3" + "@vitest/pretty-format": "npm:^2.1.3" + "@vitest/runner": "npm:2.1.3" + "@vitest/snapshot": "npm:2.1.3" + "@vitest/spy": "npm:2.1.3" + "@vitest/utils": "npm:2.1.3" chai: "npm:^5.1.1" debug: "npm:^4.3.6" magic-string: "npm:^0.30.11" @@ -11558,13 +11556,13 @@ __metadata: tinypool: "npm:^1.0.0" tinyrainbow: "npm:^1.2.0" vite: "npm:^5.0.0" - vite-node: "npm:2.1.2" + vite-node: "npm:2.1.3" why-is-node-running: "npm:^2.3.0" peerDependencies: "@edge-runtime/vm": "*" "@types/node": ^18.0.0 || >=20.0.0 - "@vitest/browser": 2.1.2 - "@vitest/ui": 2.1.2 + "@vitest/browser": 2.1.3 + "@vitest/ui": 2.1.3 happy-dom: "*" jsdom: "*" peerDependenciesMeta: @@ -11582,7 +11580,7 @@ __metadata: optional: true bin: vitest: vitest.mjs - checksum: 10c0/79301678bb0207f4bfb16e155e1744ed0b9866c4e1913bb43a3821c01fcda033b7263dac8da87946f90dff6f8f1578a4f94f860409edf0332c3dbfa3a8202803 + checksum: 10c0/7688fdce37205e7f3b448039df216e103e3a52994af0201993e22decbb558d129a734001b991f3c3d80bf4a4ef91ca6a5665a7395d5b051249da60a0016eda36 languageName: node linkType: hard @@ -11658,7 +11656,7 @@ __metadata: "@types/css-tree": "npm:^2" "@types/debug": "npm:^4" "@types/electron": "npm:^1.6.10" - "@types/node": "npm:^22.7.5" + "@types/node": "npm:^22.7.6" "@types/papaparse": "npm:^5" "@types/pngjs": "npm:^6.0.5" "@types/react": "npm:^18.3.11" @@ -11671,7 +11669,7 @@ __metadata: "@types/uuid": "npm:^10.0.0" "@types/ws": "npm:^8" "@vitejs/plugin-react-swc": "npm:^3.7.1" - "@vitest/coverage-istanbul": "npm:^2.1.2" + "@vitest/coverage-istanbul": "npm:^2.1.3" "@xterm/addon-fit": "npm:^0.10.0" "@xterm/addon-serialize": "npm:^0.13.0" "@xterm/addon-web-links": "npm:^0.11.0" @@ -11729,17 +11727,17 @@ __metadata: throttle-debounce: "npm:^5.0.2" tinycolor2: "npm:^1.6.0" ts-node: "npm:^10.9.2" - tslib: "npm:^2.6.3" + tslib: "npm:^2.8.0" tsx: "npm:^4.19.1" typescript: "npm:^5.6.3" - typescript-eslint: "npm:^8.8.1" + typescript-eslint: "npm:^8.10.0" use-device-pixel-ratio: "npm:^1.1.2" - vite: "npm:^5.4.8" + vite: "npm:^5.4.9" vite-plugin-image-optimizer: "npm:^1.1.8" vite-plugin-static-copy: "npm:^2.0.0" vite-plugin-svgr: "npm:^4.2.0" vite-tsconfig-paths: "npm:^5.0.1" - vitest: "npm:^2.1.2" + vitest: "npm:^2.1.3" winston: "npm:^3.15.0" ws: "npm:^8.18.0" yaml: "npm:^2.5.1" From 26e389776b0774ac4677d30c3dbe66e80c18c948 Mon Sep 17 00:00:00 2001 From: Evan Simkowitz Date: Fri, 18 Oct 2024 15:31:23 -0700 Subject: [PATCH 34/34] Revert "Revert "Bump the prod-dependencies group with 2 updates"" (#1075) Reverts wavetermdev/waveterm#1071 --- package.json | 4 ++-- yarn.lock | 23 +++++++---------------- 2 files changed, 9 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 1f00468ea..f77e05cea 100644 --- a/package.json +++ b/package.json @@ -81,7 +81,7 @@ "vitest": "^2.1.3" }, "dependencies": { - "@floating-ui/react": "^0.26.24", + "@floating-ui/react": "^0.26.25", "@monaco-editor/loader": "^1.4.0", "@monaco-editor/react": "^4.6.0", "@observablehq/plot": "^0.6.16", @@ -136,7 +136,7 @@ "use-device-pixel-ratio": "^1.1.2", "winston": "^3.15.0", "ws": "^8.18.0", - "yaml": "^2.5.1" + "yaml": "^2.6.0" }, "resolutions": { "send@npm:0.18.0": "0.19.0", diff --git a/yarn.lock b/yarn.lock index 09d61851b..f63fa4aa4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -847,9 +847,9 @@ __metadata: languageName: node linkType: hard -"@floating-ui/react@npm:^0.26.24": - version: 0.26.24 - resolution: "@floating-ui/react@npm:0.26.24" +"@floating-ui/react@npm:^0.26.25": + version: 0.26.25 + resolution: "@floating-ui/react@npm:0.26.25" dependencies: "@floating-ui/react-dom": "npm:^2.1.2" "@floating-ui/utils": "npm:^0.2.8" @@ -857,7 +857,7 @@ __metadata: peerDependencies: react: ">=16.8.0" react-dom: ">=16.8.0" - checksum: 10c0/c5c3ac265802087673a69b0e08b3bea1ee02de9da4cdbc40bb1c9e06823be72628a82f1655b40d56a4383715b4ab3b6deddff4e69146f513970ee592e1dd8f92 + checksum: 10c0/5206b06a5963e795af2f0b0a6ac39230012263ffa38dd60158e0f0b82d43a24e6a1c005fc8556ee5fe26e6353546ffb72e54716f6bd584fdab516dc128a78995 languageName: node linkType: hard @@ -11635,7 +11635,7 @@ __metadata: dependencies: "@chromatic-com/storybook": "npm:^2.0.2" "@eslint/js": "npm:^9.12.0" - "@floating-ui/react": "npm:^0.26.24" + "@floating-ui/react": "npm:^0.26.25" "@monaco-editor/loader": "npm:^1.4.0" "@monaco-editor/react": "npm:^4.6.0" "@observablehq/plot": "npm:^0.6.16" @@ -11740,7 +11740,7 @@ __metadata: vitest: "npm:^2.1.3" winston: "npm:^3.15.0" ws: "npm:^8.18.0" - yaml: "npm:^2.5.1" + yaml: "npm:^2.6.0" languageName: unknown linkType: soft @@ -11939,7 +11939,7 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.0.0": +"yaml@npm:^2.0.0, yaml@npm:^2.6.0": version: 2.6.0 resolution: "yaml@npm:2.6.0" bin: @@ -11948,15 +11948,6 @@ __metadata: languageName: node linkType: hard -"yaml@npm:^2.5.1": - version: 2.5.1 - resolution: "yaml@npm:2.5.1" - bin: - yaml: bin.mjs - checksum: 10c0/40fba5682898dbeeb3319e358a968fe886509fab6f58725732a15f8dda3abac509f91e76817c708c9959a15f786f38ff863c1b88062d7c1162c5334a7d09cb4a - languageName: node - linkType: hard - "yargs-parser@npm:^21.1.1": version: 21.1.1 resolution: "yargs-parser@npm:21.1.1"