From e7e98255d9b2481831e3d5a3f9dd2ec90e36e4a2 Mon Sep 17 00:00:00 2001 From: Andrey Antukh Date: Mon, 30 Mar 2026 11:08:33 +0200 Subject: [PATCH] :zap: Add scroll and zoom raf throttling (#8812) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * :arrow_up: Update opencode and copilot deps * :bug: Decouple workspace-content from workspace-local to reduce scroll re-renders Move workspace-local subscription from workspace-content* (parent) into viewport* and viewport-classic* (children). workspace-content* now only subscribes to the new workspace-vport derived atom, which changes only on window resize — not on every scroll event. This prevents the sidebar, palette and other workspace-content children from re-rendering on scroll. * :bug: Throttle wheel events to one state update per animation frame Accumulate wheel event deltas in a mutable ref and flush them via requestAnimationFrame, so that multiple wheel events between frames produce a single state mutation instead of one per event. This prevents the cascade of synchronous React re-renders (via useSyncExternalStore) that can exceed the maximum update depth on rapid scrolling. Both panning (scroll) and zoom (ctrl/mod+wheel) are throttled. Scroll deltas are summed additively; zoom scales are compounded multiplicatively with the latest cursor point used as the zoom center. * :recycle: Extract schedule-zoom! and schedule-scroll! from on-mouse-wheel * :recycle: Avoid zoom dep on on-mouse-wheel by using a ref --- frontend/src/app/main/refs.cljs | 3 + frontend/src/app/main/ui/workspace.cljs | 3 +- .../src/app/main/ui/workspace/viewport.cljs | 8 +- .../main/ui/workspace/viewport/actions.cljs | 112 ++++++++---- .../app/main/ui/workspace/viewport/hooks.cljs | 9 +- .../app/main/ui/workspace/viewport_wasm.cljs | 10 +- package.json | 6 +- pnpm-lock.yaml | 164 +++++++++--------- 8 files changed, 184 insertions(+), 131 deletions(-) diff --git a/frontend/src/app/main/refs.cljs b/frontend/src/app/main/refs.cljs index b443af8b2e..c4e0faaecd 100644 --- a/frontend/src/app/main/refs.cljs +++ b/frontend/src/app/main/refs.cljs @@ -234,6 +234,9 @@ (def inspect-expanded (l/derived :inspect-expanded workspace-local)) +(def workspace-vport + (l/derived :vport workspace-local)) + (def vbox (l/derived :vbox workspace-local)) diff --git a/frontend/src/app/main/ui/workspace.cljs b/frontend/src/app/main/ui/workspace.cljs index 0e4bd1186f..e2366d6003 100644 --- a/frontend/src/app/main/ui/workspace.cljs +++ b/frontend/src/app/main/ui/workspace.cljs @@ -56,7 +56,7 @@ selected (mf/deref refs/selected-shapes) page-id (get page :id) - {:keys [vport] :as wlocal} (mf/deref refs/workspace-local) + vport (mf/deref refs/workspace-vport) {:keys [options-mode]} wglobal @@ -105,7 +105,6 @@ [:> viewport* {:file file :page page - :wlocal wlocal :wglobal wglobal :selected selected :layout layout diff --git a/frontend/src/app/main/ui/workspace/viewport.cljs b/frontend/src/app/main/ui/workspace/viewport.cljs index 7d08054fb4..b0e540ac71 100644 --- a/frontend/src/app/main/ui/workspace/viewport.cljs +++ b/frontend/src/app/main/ui/workspace/viewport.cljs @@ -81,10 +81,8 @@ selected)) (mf/defc viewport-classic* - [{:keys [selected wglobal wlocal layout file page palete-size]}] - (let [;; When adding data from workspace-local revisit `app.main.ui.workspace` to check - ;; that the new parameter is sent - {:keys [edit-path + [{:keys [selected wglobal layout file page palete-size]}] + (let [{:keys [edit-path panning selrect transform @@ -94,7 +92,7 @@ zoom zoom-inverse edition]} - wlocal + (mf/deref refs/workspace-local) {:keys [options-mode tooltip diff --git a/frontend/src/app/main/ui/workspace/viewport/actions.cljs b/frontend/src/app/main/ui/workspace/viewport/actions.cljs index f0a3bc3600..454fc282b4 100644 --- a/frontend/src/app/main/ui/workspace/viewport/actions.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/actions.cljs @@ -403,46 +403,94 @@ (kbd/alt? event) (kbd/meta? event)))))))) -(defn on-mouse-wheel [zoom] - (mf/use-callback - (mf/deps zoom) - (fn [event] - (let [event (.getBrowserEvent ^js event) +(defn- schedule-zoom! + "Accumulate a compound zoom scale and a cursor point into `state`, scheduling + a single requestAnimationFrame flush if one is not already pending. On the + next frame the accumulated scale is applied via `dw/set-zoom` and the state + is reset to its idle values." + [^js state scale pt] + (let [pending? (pos? (.-zoomRafId state))] + (set! (.-scale state) (* (.-scale state) scale)) + (set! (.-zoomPt state) pt) + (when-not pending? + (set! (.-zoomRafId state) + (ts/raf + (fn [] + (let [s (.-scale state) + zp (.-zoomPt state)] + (set! (.-scale state) 1) + (set! (.-zoomPt state) nil) + (set! (.-zoomRafId state) 0) + (st/emit! (dw/set-zoom zp s))))))))) - target (dom/get-target event) - mod? (kbd/mod? event) - ctrl? (kbd/ctrl? event) +(defn- schedule-scroll! + "Accumulate scroll deltas into `state`, scheduling a single + requestAnimationFrame flush if one is not already pending. On the next + frame the accumulated dx/dy are applied via `dw/update-viewport-position` + and the state is reset to its idle values." + [^js state zoom event delta-x delta-y] + (let [pending? (pos? (.-rafId state))] + (if (and (not (cfg/check-platform? :macos)) (kbd/shift? event)) + ;; macOS sends delta-x automatically, so on other platforms we + ;; remap shift+scroll-y to horizontal panning. + (set! (.-dx state) (+ (.-dx state) (/ delta-y zoom))) + (do + (set! (.-dx state) (+ (.-dx state) (/ delta-x zoom))) + (set! (.-dy state) (+ (.-dy state) (/ delta-y zoom))))) + (when-not pending? + (set! (.-rafId state) + (ts/raf + (fn [] + (let [dx (.-dx state) + dy (.-dy state)] + (set! (.-dx state) 0) + (set! (.-dy state) 0) + (set! (.-rafId state) 0) + (st/emit! (dw/update-viewport-position + {:x #(+ % dx) + :y #(+ % dy)}))))))))) - picking-color? (= "pixel-overlay" (.-id target)) - comments-layer? (dom/is-child? (dom/get-element "comments") target) +(defn on-mouse-wheel [zoom-ref] + (let [;; Mutable accumulator for scroll/zoom deltas, throttled to one + ;; state update per animation frame. This prevents rapid wheel + ;; events from causing cascading synchronous React re-renders + ;; that can exceed the maximum update depth. + scroll-state (mf/use-ref #js {:dx 0 :dy 0 :rafId 0 + :scale 1 :zoomPt nil :zoomRafId 0})] + (mf/use-callback + (fn [event] + (let [event (.getBrowserEvent ^js event) - raw-pt (dom/get-client-position event) - pt (uwvv/point->viewport raw-pt) + target (dom/get-target event) + mod? (kbd/mod? event) + ctrl? (kbd/ctrl? event) - norm-event ^js (nw/normalize-wheel event) + picking-color? (= "pixel-overlay" (.-id target)) + comments-layer? (dom/is-child? (dom/get-element "comments") target) - delta-y (.-pixelY norm-event) - delta-x (.-pixelX norm-event) - delta-zoom (+ delta-y delta-x) + raw-pt (dom/get-client-position event) + pt (uwvv/point->viewport raw-pt) - scale (+ 1 (mth/abs (* scale-per-pixel delta-zoom))) - scale (if (pos? delta-zoom) (/ 1 scale) scale)] + norm-event ^js (nw/normalize-wheel event) - (when (or (uwvv/inside-viewport? target) picking-color?) - (dom/prevent-default event) - (dom/stop-propagation event) - (if (or ctrl? mod?) - (st/emit! (dw/set-zoom pt scale)) - (if (and (not (cfg/check-platform? :macos)) (kbd/shift? event)) - ;; macos sends delta-x automatically, don't need to do it - (st/emit! (dw/update-viewport-position {:x #(+ % (/ delta-y zoom))})) - (st/emit! (dw/update-viewport-position {:x #(+ % (/ delta-x zoom)) - :y #(+ % (/ delta-y zoom))}))))) + delta-y (.-pixelY norm-event) + delta-x (.-pixelX norm-event) + delta-zoom (+ delta-y delta-x) - (when (and comments-layer? (or ctrl? mod?)) - (dom/prevent-default event) - (dom/stop-propagation event) - (st/emit! (dw/set-zoom pt scale))))))) + scale (+ 1 (mth/abs (* scale-per-pixel delta-zoom))) + scale (if (pos? delta-zoom) (/ 1 scale) scale)] + + (when (or (uwvv/inside-viewport? target) picking-color?) + (dom/prevent-default event) + (dom/stop-propagation event) + (if (or ctrl? mod?) + (schedule-zoom! (mf/ref-val scroll-state) scale pt) + (schedule-scroll! (mf/ref-val scroll-state) (mf/ref-val zoom-ref) event delta-x delta-y))) + + (when (and comments-layer? (or ctrl? mod?)) + (dom/prevent-default event) + (dom/stop-propagation event) + (schedule-zoom! (mf/ref-val scroll-state) scale pt))))))) (defn on-drag-enter [comp-inst-ref] diff --git a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs index b615fc4aa7..225dde4fd9 100644 --- a/frontend/src/app/main/ui/workspace/viewport/hooks.cljs +++ b/frontend/src/app/main/ui/workspace/viewport/hooks.cljs @@ -44,9 +44,12 @@ (defn setup-dom-events [zoom disable-paste-ref in-viewport-ref workspace-read-only? drawing-tool drawing-path?] - (let [on-key-down (actions/on-key-down) + (let [zoom-ref (mf/use-ref zoom) + _ (mf/with-effect [zoom] + (mf/set-ref-val! zoom-ref zoom)) + on-key-down (actions/on-key-down) on-key-up (actions/on-key-up) - on-mouse-wheel (actions/on-mouse-wheel zoom) + on-mouse-wheel (actions/on-mouse-wheel zoom-ref) on-paste (actions/on-paste disable-paste-ref in-viewport-ref workspace-read-only?) on-pointer-down (mf/use-fn (mf/deps drawing-tool drawing-path?) @@ -67,7 +70,7 @@ #(events/unlistenByKey key))) - (mf/with-layout-effect [on-key-down on-key-up on-mouse-wheel on-paste workspace-read-only?] + (mf/with-layout-effect [on-key-down on-key-up on-paste workspace-read-only?] (let [keys [(events/listen js/document EventType.KEYDOWN on-key-down) (events/listen js/document EventType.KEYUP on-key-up) ;; bind with passive=false to allow the event to be cancelled diff --git a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs index 3edbe19c21..be88366ae4 100644 --- a/frontend/src/app/main/ui/workspace/viewport_wasm.cljs +++ b/frontend/src/app/main/ui/workspace/viewport_wasm.cljs @@ -73,9 +73,10 @@ objects))) (mf/defc viewport* - [{:keys [selected wglobal wlocal layout file page palete-size]}] + [{:keys [selected wglobal layout file page palete-size]}] (let [;; When adding data from workspace-local revisit `app.main.ui.workspace` to check ;; that the new parameter is sent + {:keys [edit-path panning selrect @@ -85,17 +86,18 @@ vport zoom zoom-inverse - edition]} wlocal + edition]} + (mf/deref refs/workspace-local) {:keys [options-mode tooltip show-distances? - picking-color?]} wglobal + picking-color?]} + wglobal permissions (mf/use-ctx ctx/permissions) read-only? (mf/use-ctx ctx/workspace-read-only?) - ;; DEREFS drawing (mf/deref refs/workspace-drawing) focus (mf/deref refs/workspace-focus-selected) wasm-modifiers (mf/deref refs/workspace-wasm-modifiers) diff --git a/package.json b/package.json index f6028d0a2f..0a04064cc8 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,7 @@ "license": "MPL-2.0", "author": "Kaleidos INC", "private": true, - "packageManager": "pnpm@10.28.2+sha512.41872f037ad22f7348e3b1debbaf7e867cfd448f2726d9cf74c08f19507c31d2c8e7a11525b983febc2df640b5438dee6023ebb1f84ed43cc2d654d2bc326264", + "packageManager": "pnpm@10.33.0+sha512.10568bb4a6afb58c9eb3630da90cc9516417abebd3fabbe6739f0ae795728da1491e9db5a544c76ad8eb7570f5c4bb3d6c637b2cb41bfdcdb47fa823c8649319", "repository": { "type": "git", "url": "https://github.com/penpot/penpot" @@ -16,9 +16,9 @@ "fmt": "./scripts/fmt" }, "devDependencies": { - "@github/copilot": "^1.0.11", + "@github/copilot": "^1.0.12", "@types/node": "^20.12.7", "esbuild": "^0.27.4", - "opencode-ai": "^1.3.2" + "opencode-ai": "^1.3.7" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 44c73fd54e..419ae0a178 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -9,8 +9,8 @@ importers: .: devDependencies: '@github/copilot': - specifier: ^1.0.11 - version: 1.0.11 + specifier: ^1.0.12 + version: 1.0.12 '@types/node': specifier: ^20.12.7 version: 20.19.37 @@ -18,8 +18,8 @@ importers: specifier: ^0.27.4 version: 0.27.4 opencode-ai: - specifier: ^1.3.2 - version: 1.3.2 + specifier: ^1.3.7 + version: 1.3.7 packages: @@ -179,44 +179,44 @@ packages: cpu: [x64] os: [win32] - '@github/copilot-darwin-arm64@1.0.11': - resolution: {integrity: sha512-wdKimjtbsVeXqMqQSnGpGBPFEYHljxXNuWeH8EIJTNRgFpAsimcivsFgql3Twq4YOp0AxfsH36icG4IEen30mA==} + '@github/copilot-darwin-arm64@1.0.12': + resolution: {integrity: sha512-fjbwRIUZAH06Eyg5ZkfZXg8SVXpqI3HaFhtXZ803CZs9mfIgfOSR3URZxUnv7SIv6aI/7f6ws8RxKnPGavJ/tg==} cpu: [arm64] os: [darwin] hasBin: true - '@github/copilot-darwin-x64@1.0.11': - resolution: {integrity: sha512-VeuPv8rzBVGBB8uDwMEhcHBpldoKaq26yZ5YQm+G9Ka5QIF+1DMah8ZNRMVsTeNKkb1ji9G8vcuCsaPbnG3fKg==} + '@github/copilot-darwin-x64@1.0.12': + resolution: {integrity: sha512-/tJGJEEm8kpTW/sJRNnvhMSHKIHApNun14biuIkC5CXDqVgFakbKlckn/FlIkT48eEUysc0YbEatrHIDz/8XbA==} cpu: [x64] os: [darwin] hasBin: true - '@github/copilot-linux-arm64@1.0.11': - resolution: {integrity: sha512-/d8p6RlFYKj1Va2hekFIcYNMHWagcEkaxgcllUNXSyQLnmEtXUkaWtz62VKGWE+n/UMkEwCB6vI2xEwPTlUNBQ==} + '@github/copilot-linux-arm64@1.0.12': + resolution: {integrity: sha512-4977LVJi3/9Yc+ivj+VKDVtHg0kT5yqOrN8F35/jgqerx4Mdtk1pOMlWztXxLicBHN4y2V7/EY/wc0WqFW0Zvg==} cpu: [arm64] os: [linux] hasBin: true - '@github/copilot-linux-x64@1.0.11': - resolution: {integrity: sha512-UujTRO3xkPFC1CybchBbCnaTEAG6JrH0etIst07JvfekMWgvRxbiCHQPpDPSzBCPiBcGu0gba0/IT+vUCORuIw==} + '@github/copilot-linux-x64@1.0.12': + resolution: {integrity: sha512-9QevJZD29PVltYDV4xHWbdN6ud/966clERL5Frh2+9D3+spaVDO1hFllzoFiEwD/M4f2GkSh7/fT3hV0LKl9Ag==} cpu: [x64] os: [linux] hasBin: true - '@github/copilot-win32-arm64@1.0.11': - resolution: {integrity: sha512-EOW8HUM+EmnHEZEa+iUMl4pP1+2eZUk2XCbynYiMehwX9sidc4BxEHp2RuxADSzFPTieQEWzgjQmHWrtet8pQg==} + '@github/copilot-win32-arm64@1.0.12': + resolution: {integrity: sha512-RLAbAsLniI8vA2utgZdIsvD8slZpz1fb8l6cmIiQvDE/BwQb2zNV9VepZ+CwzYtNx9ifxBtgIwYwUJq5bxeSaQ==} cpu: [arm64] os: [win32] hasBin: true - '@github/copilot-win32-x64@1.0.11': - resolution: {integrity: sha512-fKGkSNamzs3h9AbmswNvPYJBORCb2Y8CbusijU3C7fT3ohvqnHJwKo5iHhJXLOKZNOpFZgq9YKha410u9sIs6Q==} + '@github/copilot-win32-x64@1.0.12': + resolution: {integrity: sha512-4SYV09F4Sw20DAib1do26+ALZmCZrghzo+5e6IZbQOsm4B7NhBFaLpKFU+kEijfmWacLlh/at5CpGGGKlwlbcg==} cpu: [x64] os: [win32] hasBin: true - '@github/copilot@1.0.11': - resolution: {integrity: sha512-cptVopko/tNKEXyBP174yBjHQBEwg6CqaKN2S0M3J+5LEB8u31bLL75ioOPd+5vubqBrA0liyTdcHeZ8UTRbmg==} + '@github/copilot@1.0.12': + resolution: {integrity: sha512-GpmoJbs1ECyLLKtY4PcFzO8Cz6GgDTOKkrzwNdkirNdfsB+o6x0OOlFyrOdNXNPII7pk9+GcpIjF87sLwWzpPQ==} hasBin: true '@types/node@20.19.37': @@ -227,67 +227,67 @@ packages: engines: {node: '>=18'} hasBin: true - opencode-ai@1.3.2: - resolution: {integrity: sha512-InyDAXKoh+fVxWrBMJZaf1xIYpASZ2zX4O/u7nwtiYzxy/kqHySvQe9jDVrhMgbMdb4CXzACid7M2HDUa+vz2Q==} + opencode-ai@1.3.7: + resolution: {integrity: sha512-AtqTOcPvHkAF/zPGs/08/8m2DeiWADCGhT/WAJ1drGem4WdPOt45jkJLPdOCheN1gqmLxTcNV0veKFVHmbjKKQ==} hasBin: true - opencode-darwin-arm64@1.3.2: - resolution: {integrity: sha512-/7V+J3XZGF/sCdMbEb5E3mUvuOIVvGkVjgYH1k/pnTfdGaPW/C7RgW2dU2HedXvkw4Y3CplUS+5VfA/F5kufXw==} + opencode-darwin-arm64@1.3.7: + resolution: {integrity: sha512-TRglBnrSzeR9pEFV8Z1ACqhD3r3WYl8v1y9TkgvHviTD/EXGL3Nu7f/fy3XOQprPGSLPyrlOwZXb1i9XrfTo1A==} cpu: [arm64] os: [darwin] - opencode-darwin-x64-baseline@1.3.2: - resolution: {integrity: sha512-jBusp8Vb1wsGKHD2AOD+Cr4qL4zSDut80Sy0CnMH8AwnSCNzaSVi2wnE/7vPrgCa44Xr0MknSE2S0wHQ5SbLaw==} + opencode-darwin-x64-baseline@1.3.7: + resolution: {integrity: sha512-YLl+peZIC1m295JNSMzM/NM5uNs2GVewZply2GV3P6WApS5JuRIaMNvzOk7jpL90yt6pur6oEwC8g0WWwP8G4A==} cpu: [x64] os: [darwin] - opencode-darwin-x64@1.3.2: - resolution: {integrity: sha512-J7HgNBUoDpsKHAiky18aUm4xMKmUIJqlvVMkvL9NVjwDRMuAKnbYcxpRK8O+NKzeVx29IWwX8zizUwCuqXAAlA==} + opencode-darwin-x64@1.3.7: + resolution: {integrity: sha512-Nsyh3vLAqqfVyWD4qrcyRJit+CmZZpm6IdXTk9wo1hUAE/RmYIBDz1To99ZBwA3SJB1fLrciYicMN2uq8r1XNw==} cpu: [x64] os: [darwin] - opencode-linux-arm64-musl@1.3.2: - resolution: {integrity: sha512-ZOB6+NvkZ19mzi6j4VAHtQDAeTXvQJqg4YtclT3wbMof8y3jn5S8vUmaXLk9d9FryEcdIoMK/oFLkcLkS1OXpA==} + opencode-linux-arm64-musl@1.3.7: + resolution: {integrity: sha512-D4gCn7oVLCc3xN0BSJOfYerCr1E1ktUkixfHQEmkoR1CLZ77Z/aHSgcm0Ln01Q+ie6MsVukvuyUQn9GEY1Dn/A==} cpu: [arm64] os: [linux] - opencode-linux-arm64@1.3.2: - resolution: {integrity: sha512-+q0PJ86LPitMIGf9sGXdtOcwpdiwbzdw91zXAHFe7rXZZm4Cvu9qjvt6WT/lKJqL8f6pyJs9Kbt4XJ/C20swQA==} + opencode-linux-arm64@1.3.7: + resolution: {integrity: sha512-72OnT20wIhkXMGclmw7S+d8JjIb9lx8pPIW8pkyI79+qxLTp6AuTHsmUG/qDhw3NMtVDs9efAb0C/FjLXATeAA==} cpu: [arm64] os: [linux] - opencode-linux-x64-baseline-musl@1.3.2: - resolution: {integrity: sha512-8XYcAqZBcUgYHfae9qoTT8erqFjd6AKTrSu60gRgzTN8cUybG4iPyAVt4GUcXCzUw44Qo++d/8I9hwpUTCoFYg==} + opencode-linux-x64-baseline-musl@1.3.7: + resolution: {integrity: sha512-DE8eqPF2benmdzUdMG+rnr0J3DtrP+x8sUzq7gecuNnU4iHo4s8Itx+gCLP978ZBdYwTkNRtNZ5BKN0ePT5KYQ==} cpu: [x64] os: [linux] - opencode-linux-x64-baseline@1.3.2: - resolution: {integrity: sha512-QXiF1+PJH5AOHMSTdYngOB7yWULFQKJpIbx77ZHM1MKyxiBweIrZ03nG86iXIZIVGBxEfH1CcKDU28lFGUJdNg==} + opencode-linux-x64-baseline@1.3.7: + resolution: {integrity: sha512-Aztdiq0U6H8Nww7mmARK/ZGkllTrePuyEEdzg2+0LWfUpDO5Cl/pMJ8btqVtTjfb/pLw+BU3JtYxw8oOhRkl/A==} cpu: [x64] os: [linux] - opencode-linux-x64-musl@1.3.2: - resolution: {integrity: sha512-o4aXgcWQidxQ6cJMsgLcCMv9MSKtLEqm3OAFm6eN7hVgHV9m7rz035BICNZ1YLltIEdQYAHXx5MGM21J4/vBdw==} + opencode-linux-x64-musl@1.3.7: + resolution: {integrity: sha512-L0ohQAbw1Ib1koawV/yJAYIGIel2zMPafbdeMXELIvpes3Sq9qIfCSRB/2ROu8gjN8P1TGnUU6Vx1F3MtJOvIA==} cpu: [x64] os: [linux] - opencode-linux-x64@1.3.2: - resolution: {integrity: sha512-/+OtuHr2O0/QKpBrZBnutr0ZLe+LmOx003Z99b21BgG9wsVo7gFuNpfLPVXnqcEY6D5DuWl4aEJW4+w+K0urYw==} + opencode-linux-x64@1.3.7: + resolution: {integrity: sha512-rCFXrgDLhPuHazomDgzBXGLE0wJ4VRHrIe26WCHm4iqmGu9O6ExZd612Y07/CGQm4bVBHlaalcWh7N/z6GOPkA==} cpu: [x64] os: [linux] - opencode-windows-arm64@1.3.2: - resolution: {integrity: sha512-3xJEjSLdk7I5Z6yyrT4LCQeK4VCj6mo/l4JdUa0zocV8wCzUtY1lSHeipDAaNr8TwD6NeTxr1iomIjuatKAFOA==} + opencode-windows-arm64@1.3.7: + resolution: {integrity: sha512-s6emZ28ORIMtKyrBKvo96q2qanRwbjPHK/rOMinZ22SW7DLzNKKf1p92JMkSni0dXXGL64jsy1se5IvELc7Mvg==} cpu: [arm64] os: [win32] - opencode-windows-x64-baseline@1.3.2: - resolution: {integrity: sha512-RVx9e1KBNTSWjrtfRpGIIcJDsM13OUY/lYqJXI1oj34lMOEj5G57fypjk9yBqUHBR+7tolGmewwJJU6SDgyPXQ==} + opencode-windows-x64-baseline@1.3.7: + resolution: {integrity: sha512-CGbhvn9rMXV4xEjw1lxPFbsWuOPf/xJ1AAblqKsF2VmSbqe25QG5VIf88hsJo8YmYIHz6U7tNGI4lTF1zVx9cw==} cpu: [x64] os: [win32] - opencode-windows-x64@1.3.2: - resolution: {integrity: sha512-pJMpptERqz8pjnW1pTQf5Ru2WbJz7P2BPM5De5gdUd10y0yUoGvY7uzyJYuGpsrCqeWrEYokERnbv8A/4V3Yaw==} + opencode-windows-x64@1.3.7: + resolution: {integrity: sha512-q7V9p10Q7BH03tnYMG4k6B1ZXLDriDMtXkkw+NW1p22F7dQ22WmaMoCWnv3d4b2vNyjMjIYuPm97q0v02QI08w==} cpu: [x64] os: [win32] @@ -374,32 +374,32 @@ snapshots: '@esbuild/win32-x64@0.27.4': optional: true - '@github/copilot-darwin-arm64@1.0.11': + '@github/copilot-darwin-arm64@1.0.12': optional: true - '@github/copilot-darwin-x64@1.0.11': + '@github/copilot-darwin-x64@1.0.12': optional: true - '@github/copilot-linux-arm64@1.0.11': + '@github/copilot-linux-arm64@1.0.12': optional: true - '@github/copilot-linux-x64@1.0.11': + '@github/copilot-linux-x64@1.0.12': optional: true - '@github/copilot-win32-arm64@1.0.11': + '@github/copilot-win32-arm64@1.0.12': optional: true - '@github/copilot-win32-x64@1.0.11': + '@github/copilot-win32-x64@1.0.12': optional: true - '@github/copilot@1.0.11': + '@github/copilot@1.0.12': optionalDependencies: - '@github/copilot-darwin-arm64': 1.0.11 - '@github/copilot-darwin-x64': 1.0.11 - '@github/copilot-linux-arm64': 1.0.11 - '@github/copilot-linux-x64': 1.0.11 - '@github/copilot-win32-arm64': 1.0.11 - '@github/copilot-win32-x64': 1.0.11 + '@github/copilot-darwin-arm64': 1.0.12 + '@github/copilot-darwin-x64': 1.0.12 + '@github/copilot-linux-arm64': 1.0.12 + '@github/copilot-linux-x64': 1.0.12 + '@github/copilot-win32-arm64': 1.0.12 + '@github/copilot-win32-x64': 1.0.12 '@types/node@20.19.37': dependencies: @@ -434,55 +434,55 @@ snapshots: '@esbuild/win32-ia32': 0.27.4 '@esbuild/win32-x64': 0.27.4 - opencode-ai@1.3.2: + opencode-ai@1.3.7: optionalDependencies: - opencode-darwin-arm64: 1.3.2 - opencode-darwin-x64: 1.3.2 - opencode-darwin-x64-baseline: 1.3.2 - opencode-linux-arm64: 1.3.2 - opencode-linux-arm64-musl: 1.3.2 - opencode-linux-x64: 1.3.2 - opencode-linux-x64-baseline: 1.3.2 - opencode-linux-x64-baseline-musl: 1.3.2 - opencode-linux-x64-musl: 1.3.2 - opencode-windows-arm64: 1.3.2 - opencode-windows-x64: 1.3.2 - opencode-windows-x64-baseline: 1.3.2 + opencode-darwin-arm64: 1.3.7 + opencode-darwin-x64: 1.3.7 + opencode-darwin-x64-baseline: 1.3.7 + opencode-linux-arm64: 1.3.7 + opencode-linux-arm64-musl: 1.3.7 + opencode-linux-x64: 1.3.7 + opencode-linux-x64-baseline: 1.3.7 + opencode-linux-x64-baseline-musl: 1.3.7 + opencode-linux-x64-musl: 1.3.7 + opencode-windows-arm64: 1.3.7 + opencode-windows-x64: 1.3.7 + opencode-windows-x64-baseline: 1.3.7 - opencode-darwin-arm64@1.3.2: + opencode-darwin-arm64@1.3.7: optional: true - opencode-darwin-x64-baseline@1.3.2: + opencode-darwin-x64-baseline@1.3.7: optional: true - opencode-darwin-x64@1.3.2: + opencode-darwin-x64@1.3.7: optional: true - opencode-linux-arm64-musl@1.3.2: + opencode-linux-arm64-musl@1.3.7: optional: true - opencode-linux-arm64@1.3.2: + opencode-linux-arm64@1.3.7: optional: true - opencode-linux-x64-baseline-musl@1.3.2: + opencode-linux-x64-baseline-musl@1.3.7: optional: true - opencode-linux-x64-baseline@1.3.2: + opencode-linux-x64-baseline@1.3.7: optional: true - opencode-linux-x64-musl@1.3.2: + opencode-linux-x64-musl@1.3.7: optional: true - opencode-linux-x64@1.3.2: + opencode-linux-x64@1.3.7: optional: true - opencode-windows-arm64@1.3.2: + opencode-windows-arm64@1.3.7: optional: true - opencode-windows-x64-baseline@1.3.2: + opencode-windows-x64-baseline@1.3.7: optional: true - opencode-windows-x64@1.3.2: + opencode-windows-x64@1.3.7: optional: true undici-types@6.21.0: {}