From 0ce792d7f9e4cb0062707e23313549146a5c5172 Mon Sep 17 00:00:00 2001 From: Carles Andres Date: Mon, 30 Mar 2026 21:15:01 +0100 Subject: [PATCH 1/3] Update models-dev extension - chore: ignore local debug files - fix: replace useCachedPromise with direct fetch to prevent OOM on first launch - Pull contributions --- extensions/models-dev/.gitignore | 4 ++ extensions/models-dev/CHANGELOG.md | 11 +++ extensions/models-dev/package-lock.json | 30 +------- extensions/models-dev/package.json | 3 +- .../models-dev/src/hooks/useModelsData.ts | 70 +++++++++++++++---- 5 files changed, 74 insertions(+), 44 deletions(-) diff --git a/extensions/models-dev/.gitignore b/extensions/models-dev/.gitignore index 84fc7188f51..8df5b042ec0 100644 --- a/extensions/models-dev/.gitignore +++ b/extensions/models-dev/.gitignore @@ -12,3 +12,7 @@ compiled_raycast_rust # misc .DS_Store + +# Local files +.claude/ +GITHUB_ISSUE.md diff --git a/extensions/models-dev/CHANGELOG.md b/extensions/models-dev/CHANGELOG.md index f4055f4e065..e6f9dbc07ba 100644 --- a/extensions/models-dev/CHANGELOG.md +++ b/extensions/models-dev/CHANGELOG.md @@ -1,5 +1,16 @@ # models.dev Changelog +## [Bug Fix] - {PR_MERGE_DATE} + +### Fixed + +- Fixed JS heap out of memory crash on first launch caused by `useCachedPromise` memory overhead +- Replaced `useCachedPromise` with direct fetch + Cache API to reduce peak memory usage + +### Changed + +- Removed `@raycast/utils` dependency (no longer needed) + ## [Bug Fixes] - 2026-03-16 ### Changed diff --git a/extensions/models-dev/package-lock.json b/extensions/models-dev/package-lock.json index a0d3e0dfbcd..07f2586bc5f 100644 --- a/extensions/models-dev/package-lock.json +++ b/extensions/models-dev/package-lock.json @@ -7,8 +7,7 @@ "name": "models-dev", "license": "MIT", "dependencies": { - "@raycast/api": "^1.104.3", - "@raycast/utils": "^2.2.2" + "@raycast/api": "^1.104.3" }, "devDependencies": { "@raycast/eslint-config": "^2.1.1", @@ -1209,24 +1208,6 @@ "eslint": ">=8.23.0" } }, - "node_modules/@raycast/utils": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/@raycast/utils/-/utils-2.2.3.tgz", - "integrity": "sha512-YwqleVl0Wk/FOq+672gtvswuwMqjNqIr+c63FhouTEHc1LJ3zaohLSkW4+UcfBjPU8HySKQm+kJqZW1iOM9fnA==", - "license": "MIT", - "dependencies": { - "dequal": "^2.0.3" - }, - "peerDependencies": { - "@raycast/api": ">=1.99.4", - "react": ">=19.0.0" - }, - "peerDependenciesMeta": { - "react": { - "optional": true - } - } - }, "node_modules/@types/estree": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", @@ -1788,15 +1769,6 @@ "dev": true, "license": "MIT" }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/ejs": { "version": "3.1.10", "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz", diff --git a/extensions/models-dev/package.json b/extensions/models-dev/package.json index be29d046059..50736d8fafe 100644 --- a/extensions/models-dev/package.json +++ b/extensions/models-dev/package.json @@ -120,8 +120,7 @@ } ], "dependencies": { - "@raycast/api": "^1.104.3", - "@raycast/utils": "^2.2.2" + "@raycast/api": "^1.104.3" }, "devDependencies": { "@raycast/eslint-config": "^2.1.1", diff --git a/extensions/models-dev/src/hooks/useModelsData.ts b/extensions/models-dev/src/hooks/useModelsData.ts index 57aa7dbf956..bc897ead95c 100644 --- a/extensions/models-dev/src/hooks/useModelsData.ts +++ b/extensions/models-dev/src/hooks/useModelsData.ts @@ -1,21 +1,65 @@ -import { showToast, Toast } from "@raycast/api"; -import { useCachedPromise } from "@raycast/utils"; +import { Cache, showToast, Toast } from "@raycast/api"; +import { useState, useEffect, useRef } from "react"; import { fetchModelsData } from "../lib/api"; +import type { ModelsData } from "../lib/types"; + +const cache = new Cache(); +const CACHE_KEY = "models-data"; /** * Hook to fetch models data from models.dev - * useCachedPromise persists the last successful result to disk automatically, - * serving stale-while-revalidate on subsequent opens with no extra heap allocation. + * + * Uses direct fetch + Cache API instead of useCachedPromise to avoid + * memory spikes during fresh cache population. See: + * https://github.com/raycast/utils/issues/XXX */ export function useModelsData() { - return useCachedPromise(fetchModelsData, [], { - keepPreviousData: true, - onError: (error) => { - showToast({ - style: Toast.Style.Failure, - title: "Failed to load models", - message: error instanceof Error ? error.message : "Unknown error", - }); - }, + const [data, setData] = useState(() => { + const cached = cache.get(CACHE_KEY); + if (cached) { + try { + return JSON.parse(cached) as ModelsData; + } catch { + cache.remove(CACHE_KEY); + } + } + return null; }); + + const [isLoading, setIsLoading] = useState(!data); + const fetchedRef = useRef(false); + + useEffect(() => { + // Already have cached data or already fetching + if (fetchedRef.current) return; + fetchedRef.current = true; + + // If we have cached data, still revalidate in background + const shouldRevalidate = !!data; + + if (!shouldRevalidate) { + setIsLoading(true); + } + + fetchModelsData() + .then((result) => { + setData(result); + setIsLoading(false); + // Cache write happens after state update to reduce peak memory + cache.set(CACHE_KEY, JSON.stringify(result)); + }) + .catch((error) => { + setIsLoading(false); + // Only show error if we don't have cached data to fall back on + if (!data) { + showToast({ + style: Toast.Style.Failure, + title: "Failed to load models", + message: error instanceof Error ? error.message : "Unknown error", + }); + } + }); + }, []); + + return { data, isLoading }; } From 190a8937e16c6eaf80b74ca15845043b2e47fdd3 Mon Sep 17 00:00:00 2001 From: Carles Andres Date: Mon, 30 Mar 2026 22:58:54 +0100 Subject: [PATCH 2/3] Update extensions/models-dev/src/hooks/useModelsData.ts Co-authored-by: greptile-apps[bot] <165735046+greptile-apps[bot]@users.noreply.github.com> --- extensions/models-dev/src/hooks/useModelsData.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/extensions/models-dev/src/hooks/useModelsData.ts b/extensions/models-dev/src/hooks/useModelsData.ts index bc897ead95c..01326d73cea 100644 --- a/extensions/models-dev/src/hooks/useModelsData.ts +++ b/extensions/models-dev/src/hooks/useModelsData.ts @@ -10,8 +10,9 @@ const CACHE_KEY = "models-data"; * Hook to fetch models data from models.dev * * Uses direct fetch + Cache API instead of useCachedPromise to avoid + * Uses direct fetch + Cache API instead of useCachedPromise to avoid * memory spikes during fresh cache population. See: - * https://github.com/raycast/utils/issues/XXX + * https://github.com/raycast/utils/issues/65 */ export function useModelsData() { const [data, setData] = useState(() => { From db6fd6f2ddf41aef65ff182e4ababe7eae528aa5 Mon Sep 17 00:00:00 2001 From: raycastbot Date: Tue, 31 Mar 2026 09:08:34 +0000 Subject: [PATCH 3/3] Update CHANGELOG.md --- extensions/models-dev/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extensions/models-dev/CHANGELOG.md b/extensions/models-dev/CHANGELOG.md index e6f9dbc07ba..d7f0dab52ec 100644 --- a/extensions/models-dev/CHANGELOG.md +++ b/extensions/models-dev/CHANGELOG.md @@ -1,6 +1,6 @@ # models.dev Changelog -## [Bug Fix] - {PR_MERGE_DATE} +## [Bug Fix] - 2026-03-31 ### Fixed