@workglow/cactus 0.3.3 → 0.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/dist/ai/CactusProvider.browser.d.ts +23 -0
  2. package/dist/ai/CactusProvider.browser.d.ts.map +1 -0
  3. package/dist/ai/CactusQueuedProvider.browser.d.ts +23 -0
  4. package/dist/ai/CactusQueuedProvider.browser.d.ts.map +1 -0
  5. package/dist/ai/common/Cactus_Download.browser.d.ts +9 -0
  6. package/dist/ai/common/Cactus_Download.browser.d.ts.map +1 -0
  7. package/dist/ai/common/Cactus_DownloadRemove.browser.d.ts +9 -0
  8. package/dist/ai/common/Cactus_DownloadRemove.browser.d.ts.map +1 -0
  9. package/dist/ai/common/Cactus_JobRunFns.browser.d.ts +12 -0
  10. package/dist/ai/common/Cactus_JobRunFns.browser.d.ts.map +1 -0
  11. package/dist/ai/common/Cactus_ModelInfo.browser.d.ts +9 -0
  12. package/dist/ai/common/Cactus_ModelInfo.browser.d.ts.map +1 -0
  13. package/dist/ai/common/Cactus_ModelInfo.d.ts.map +1 -1
  14. package/dist/ai/common/Cactus_Runtime.browser.d.ts +6 -0
  15. package/dist/ai/common/Cactus_Runtime.browser.d.ts.map +1 -1
  16. package/dist/ai/common/Cactus_Runtime.d.ts +6 -0
  17. package/dist/ai/common/Cactus_Runtime.d.ts.map +1 -1
  18. package/dist/ai/common/Cactus_ToolCalling.browser.d.ts +9 -0
  19. package/dist/ai/common/Cactus_ToolCalling.browser.d.ts.map +1 -0
  20. package/dist/ai/registerCactus.browser.d.ts +10 -0
  21. package/dist/ai/registerCactus.browser.d.ts.map +1 -0
  22. package/dist/ai/registerCactusInline.browser.d.ts +8 -0
  23. package/dist/ai/registerCactusInline.browser.d.ts.map +1 -0
  24. package/dist/ai/registerCactusWorker.browser.d.ts +7 -0
  25. package/dist/ai/registerCactusWorker.browser.d.ts.map +1 -0
  26. package/dist/ai-runtime.browser.d.ts +2 -2
  27. package/dist/ai-runtime.browser.d.ts.map +1 -1
  28. package/dist/ai-runtime.browser.js +86 -186
  29. package/dist/ai-runtime.browser.js.map +13 -14
  30. package/dist/ai-runtime.js +112 -9
  31. package/dist/ai-runtime.js.map +5 -5
  32. package/dist/ai.browser.d.ts +5 -5
  33. package/dist/ai.browser.d.ts.map +1 -1
  34. package/dist/ai.browser.js +92 -193
  35. package/dist/ai.browser.js.map +13 -14
  36. package/dist/ai.js +111 -9
  37. package/dist/ai.js.map +5 -5
  38. package/package.json +11 -11
@@ -2,7 +2,7 @@
2
2
  "version": 3,
3
3
  "sources": ["../src/ai/common/Cactus_Runtime.ts", "../src/ai/common/Cactus_Constants.ts", "../src/ai/common/Cactus_ModelCatalog.ts", "../src/ai/registerCactusInline.ts", "../src/ai/CactusQueuedProvider.ts", "../src/ai/common/Cactus_CapabilitySets.ts", "../src/ai/common/Cactus_Capabilities.ts", "../src/ai/common/Cactus_Download.ts", "../src/ai/common/Cactus_DownloadRemove.ts", "../src/ai/common/Cactus_ModelInfo.ts", "../src/ai/common/Cactus_ModelSearch.ts", "../src/ai/common/Cactus_ToolCalling.ts", "../src/ai/common/Cactus_JobRunFns.ts", "../src/ai/registerCactusWorker.ts", "../src/ai/CactusProvider.ts"],
4
4
  "sourcesContent": [
5
- "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { CACTUS_CACHE_NAME, CACTUS_DEFAULT_MODELS_DIR } from \"./Cactus_Constants\";\nimport {\n cactusAssetUrl,\n getCactusCatalogEntry,\n type CactusCatalogEntry,\n} from \"./Cactus_ModelCatalog\";\nimport type { CactusModelConfig } from \"./Cactus_ModelSchema\";\n\ntype NeedleSdkModule = typeof import(\"needle-rs\");\n// `NeedleWasm` has a private constructor so `InstanceType<...>` cannot be used.\n// Recover the instance type from the static `load` method's non-undefined return.\ntype NeedleEngine = NonNullable<ReturnType<NeedleSdkModule[\"NeedleWasm\"][\"load\"]>>;\n\nlet _sdk: NeedleSdkModule | undefined;\nlet _sdkInitPromise: Promise<NeedleSdkModule> | undefined;\n\n/** Lazily load needle-rs and run its WASM `init()` exactly once. */\nexport async function loadSdk(): Promise<NeedleSdkModule> {\n _sdkInitPromise ??= import(\"needle-rs\")\n .then(async (mod) => {\n const init = (mod as unknown as { default?: () => Promise<unknown> }).default;\n if (typeof init === \"function\") {\n await init();\n }\n _sdk = mod;\n return mod;\n })\n .catch((err: unknown) => {\n _sdkInitPromise = undefined;\n _sdk = undefined;\n throw new Error(\n `needle-rs is required for LOCAL_CACTUS tasks. Install it with: bun add needle-rs (cause: ${String(err)})`\n );\n });\n return _sdkInitPromise;\n}\n\nexport function getCactusSdk(): NeedleSdkModule {\n if (!_sdk) throw new Error(\"Cactus SDK not loaded; call loadSdk() first\");\n return _sdk;\n}\n\n// ============================================================================\n// Asset fetch + cache\n// ============================================================================\n\nfunction hasBrowserCacheStorage(): boolean {\n return (\n typeof globalThis !== \"undefined\" &&\n \"caches\" in globalThis &&\n typeof (globalThis as unknown as { caches?: CacheStorage }).caches?.open === \"function\"\n );\n}\n\nfunction modelsDirOf(model: CactusModelConfig): string {\n return model.provider_config.models_dir ?? CACTUS_DEFAULT_MODELS_DIR;\n}\n\nasync function fetchAssetBytesBrowser(url: string): Promise<Uint8Array> {\n const cachesApi = (globalThis as unknown as { caches: CacheStorage }).caches;\n const cache = await cachesApi.open(CACTUS_CACHE_NAME);\n const hit = await cache.match(url);\n if (hit) {\n return new Uint8Array(await hit.arrayBuffer());\n }\n const resp = await fetch(url);\n if (!resp.ok) throw new Error(`Cactus asset fetch failed (${resp.status}) for ${url}`);\n // Clone first — Response bodies can only be consumed once.\n await cache.put(url, resp.clone());\n return new Uint8Array(await resp.arrayBuffer());\n}\n\nasync function fetchAssetBytesNode(\n url: string,\n models_dir: string,\n model_id: string,\n filename: string\n): Promise<Uint8Array> {\n const resolvedDir = models_dir.startsWith(\"~/\")\n ? path.join(process.env.HOME ?? process.env.USERPROFILE ?? \".\", models_dir.slice(2), model_id)\n : path.resolve(models_dir, model_id);\n const filePath = path.join(resolvedDir, filename);\n try {\n const buf = await fs.readFile(filePath);\n return new Uint8Array(buf);\n } catch {\n // fall through to fetch\n }\n const resp = await fetch(url);\n if (!resp.ok) throw new Error(`Cactus asset fetch failed (${resp.status}) for ${url}`);\n const bytes = new Uint8Array(await resp.arrayBuffer());\n await fs.mkdir(resolvedDir, { recursive: true });\n const tmpPath = `${filePath}.tmp`;\n await fs.writeFile(tmpPath, bytes);\n await fs.rename(tmpPath, filePath);\n return bytes;\n}\n\nexport async function fetchAssetBytes(\n model: CactusModelConfig,\n filename: string\n): Promise<Uint8Array> {\n const model_id = model.provider_config.model_id;\n const entry = getCactusCatalogEntry(model_id);\n if (!entry) throw new Error(`Unknown Cactus model_id: ${model_id}`);\n const url = cactusAssetUrl(entry, filename);\n if (hasBrowserCacheStorage()) {\n return fetchAssetBytesBrowser(url);\n }\n return fetchAssetBytesNode(url, modelsDirOf(model), model_id, filename);\n}\n\n// ============================================================================\n// Engine cache (in-memory, per worker/process)\n// ============================================================================\n\n/** @internal Exported for tests. */\nexport const cactusEngines: Map<string, NeedleEngine> = new Map();\n/** @internal Exported for tests. */\nexport const cactusConfigJson: Map<string, unknown> = new Map();\n/** Tracks models whose assets have been persisted (downloaded) but not necessarily loaded. */\nconst cactusCachedModelIds: Set<string> = new Set();\n\nconst cactusEngineLoadsInFlight = new Map<string, Promise<NeedleEngine>>();\n\nexport async function getOrLoadEngine(model: CactusModelConfig): Promise<NeedleEngine> {\n const model_id = model.provider_config.model_id;\n const cached = cactusEngines.get(model_id);\n if (cached) return cached;\n\n const inFlight = cactusEngineLoadsInFlight.get(model_id);\n if (inFlight) return inFlight;\n\n const loadPromise = (async (): Promise<NeedleEngine> => {\n const sdk = await loadSdk();\n const entry = getCactusCatalogEntry(model_id);\n if (!entry) throw new Error(`Unknown Cactus model_id: ${model_id}`);\n\n const [weightsBytes, vocabBytes, configBytes] = await Promise.all([\n fetchAssetBytes(model, entry.assets.weights),\n fetchAssetBytes(model, entry.assets.vocab),\n fetchAssetBytes(model, entry.assets.config),\n ]);\n\n try {\n const text = new TextDecoder().decode(configBytes);\n cactusConfigJson.set(model_id, JSON.parse(text));\n } catch {\n cactusConfigJson.set(model_id, null);\n }\n\n // needle-rs `NeedleWasm.load(weights_bytes: Uint8Array, vocab_text: string)` — vocab is a string.\n const vocabText = new TextDecoder().decode(vocabBytes);\n const engine = sdk.NeedleWasm.load(weightsBytes, vocabText);\n if (!engine) {\n throw new Error(`needle-rs NeedleWasm.load returned undefined for model ${model_id}`);\n }\n cactusEngines.set(model_id, engine);\n return engine;\n })().finally(() => {\n cactusEngineLoadsInFlight.delete(model_id);\n });\n\n cactusEngineLoadsInFlight.set(model_id, loadPromise);\n return loadPromise;\n}\n\nexport function isModelLoaded(model_id: string): boolean {\n return cactusEngines.has(model_id);\n}\n\n/** Mark a model_id as having its assets persisted on disk / in Cache Storage. */\nexport function markModelCached(model_id: string): void {\n cactusCachedModelIds.add(model_id);\n}\n\n/** Returns true if the model's assets have been downloaded or the engine is currently loaded. */\nexport function isModelCached(model_id: string): boolean {\n return cactusEngines.has(model_id) || cactusCachedModelIds.has(model_id);\n}\n\n// ============================================================================\n// Sessions (no-op — needle-rs is stateless across calls)\n// ============================================================================\n\n/** @internal Exported for tests. */\nexport const cactusSessions: Map<string, Record<string, never>> = new Map();\n\nexport async function deleteCactusSession(id: string): Promise<boolean> {\n return cactusSessions.delete(id);\n}\n\n// ============================================================================\n// Eviction\n// ============================================================================\n\nasync function removeBrowserCacheEntries(entry: CactusCatalogEntry): Promise<void> {\n if (!hasBrowserCacheStorage()) return;\n const cachesApi = (globalThis as unknown as { caches: CacheStorage }).caches;\n const cache = await cachesApi.open(CACTUS_CACHE_NAME);\n for (const filename of [entry.assets.weights, entry.assets.vocab, entry.assets.config]) {\n const url = cactusAssetUrl(entry, filename);\n try {\n await cache.delete(url);\n } catch {\n /* ignore */\n }\n }\n}\n\nasync function removeNodeCacheDir(model: CactusModelConfig, model_id: string): Promise<void> {\n if (hasBrowserCacheStorage()) return;\n const models_dir = modelsDirOf(model);\n const resolvedDir = models_dir.startsWith(\"~/\")\n ? path.join(process.env.HOME ?? process.env.USERPROFILE ?? \".\", models_dir.slice(2), model_id)\n : path.resolve(models_dir, model_id);\n await fs.rm(resolvedDir, { recursive: true, force: true });\n}\n\nfunction disposeCactusEngine(model_id: string): void {\n const engine = cactusEngines.get(model_id);\n if (engine) {\n try {\n (engine as unknown as { free?: () => void }).free?.();\n } catch {\n /* best effort */\n }\n }\n cactusEngines.delete(model_id);\n cactusConfigJson.delete(model_id);\n cactusCachedModelIds.delete(model_id);\n}\n\nexport async function removeCachedAssets(model: CactusModelConfig): Promise<void> {\n const model_id = model.provider_config.model_id;\n const entry = getCactusCatalogEntry(model_id);\n if (!entry) return;\n await Promise.all([removeBrowserCacheEntries(entry), removeNodeCacheDir(model, model_id)]);\n disposeCactusEngine(model_id);\n}\n\n/** Best-effort cleanup on shutdown. */\nexport async function disposeCactusResources(): Promise<void> {\n for (const id of Array.from(cactusEngines.keys())) {\n disposeCactusEngine(id);\n }\n cactusEngines.clear();\n cactusConfigJson.clear();\n cactusCachedModelIds.clear();\n cactusSessions.clear();\n}\n",
5
+ "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport fs from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { CACTUS_CACHE_NAME, CACTUS_DEFAULT_MODELS_DIR } from \"./Cactus_Constants\";\nimport {\n cactusAssetUrl,\n getCactusCatalogEntry,\n type CactusCatalogEntry,\n} from \"./Cactus_ModelCatalog\";\nimport type { CactusModelConfig } from \"./Cactus_ModelSchema\";\n\ntype NeedleSdkModule = typeof import(\"needle-rs\");\n// `NeedleWasm` has a private constructor so `InstanceType<...>` cannot be used.\n// Recover the instance type from the static `load` method's non-undefined return.\ntype NeedleEngine = NonNullable<ReturnType<NeedleSdkModule[\"NeedleWasm\"][\"load\"]>>;\n\nexport interface CactusModelCacheInfo {\n readonly allCached: boolean;\n readonly file_sizes: Record<string, number> | null;\n}\n\nlet _sdk: NeedleSdkModule | undefined;\nlet _sdkInitPromise: Promise<NeedleSdkModule> | undefined;\n\n/** Lazily load needle-rs and run its WASM `init()` exactly once. */\nexport async function loadSdk(): Promise<NeedleSdkModule> {\n _sdkInitPromise ??= import(\"needle-rs\")\n .then(async (mod) => {\n const init = (mod as unknown as { default?: () => Promise<unknown> }).default;\n if (typeof init === \"function\") {\n await init();\n }\n _sdk = mod;\n return mod;\n })\n .catch((err: unknown) => {\n _sdkInitPromise = undefined;\n _sdk = undefined;\n throw new Error(\n `needle-rs is required for LOCAL_CACTUS tasks. Install it with: bun add needle-rs (cause: ${String(err)})`\n );\n });\n return _sdkInitPromise;\n}\n\nexport function getCactusSdk(): NeedleSdkModule {\n if (!_sdk) throw new Error(\"Cactus SDK not loaded; call loadSdk() first\");\n return _sdk;\n}\n\n// ============================================================================\n// Asset fetch + cache\n// ============================================================================\n\nfunction hasBrowserCacheStorage(): boolean {\n return (\n typeof globalThis !== \"undefined\" &&\n \"caches\" in globalThis &&\n typeof (globalThis as unknown as { caches?: CacheStorage }).caches?.open === \"function\"\n );\n}\n\nfunction modelsDirOf(model: CactusModelConfig): string {\n return model.provider_config.models_dir ?? CACTUS_DEFAULT_MODELS_DIR;\n}\n\nfunction resolveModelDir(models_dir: string, model_id: string): string {\n return models_dir.startsWith(\"~/\")\n ? path.join(process.env.HOME ?? process.env.USERPROFILE ?? \".\", models_dir.slice(2), model_id)\n : path.resolve(models_dir, model_id);\n}\n\nfunction assetFilenames(entry: CactusCatalogEntry): string[] {\n return [entry.assets.weights, entry.assets.vocab, entry.assets.config];\n}\n\nasync function getRemoteAssetSize(\n url: string,\n signal: AbortSignal | undefined\n): Promise<number | undefined> {\n try {\n const response = await fetch(url, { method: \"HEAD\", signal });\n if (!response.ok) return undefined;\n const contentLength = response.headers.get(\"content-length\");\n if (!contentLength) return undefined;\n const size = Number(contentLength);\n return Number.isFinite(size) ? size : undefined;\n } catch {\n return undefined;\n }\n}\n\nasync function getNodeAssetCacheInfo(\n model: CactusModelConfig,\n entry: CactusCatalogEntry,\n detail: string | undefined,\n signal: AbortSignal | undefined\n): Promise<CactusModelCacheInfo> {\n const filenames = assetFilenames(entry);\n const resolvedDir = resolveModelDir(modelsDirOf(model), entry.model_id);\n const stats = await Promise.all(\n filenames.map(async (filename) => {\n try {\n const stat = await fs.stat(path.join(resolvedDir, filename));\n return { filename, size: stat.size, cached: true };\n } catch {\n return { filename, size: undefined, cached: false };\n }\n })\n );\n const allCached = stats.every((stat) => stat.cached);\n\n if (detail === \"files\") {\n return {\n allCached,\n file_sizes: Object.fromEntries(filenames.map((filename) => [filename, 0])),\n };\n }\n\n if (detail !== \"files_with_metadata\") {\n return { allCached, file_sizes: null };\n }\n\n const file_sizes: Record<string, number> = {};\n await Promise.all(\n stats.map(async (stat) => {\n if (stat.size !== undefined) {\n file_sizes[stat.filename] = stat.size;\n return;\n }\n const remoteSize = await getRemoteAssetSize(cactusAssetUrl(entry, stat.filename), signal);\n if (remoteSize !== undefined) {\n file_sizes[stat.filename] = remoteSize;\n }\n })\n );\n\n return {\n allCached,\n file_sizes: Object.keys(file_sizes).length > 0 ? file_sizes : null,\n };\n}\n\nasync function fetchAssetBytesBrowser(url: string): Promise<Uint8Array> {\n const cachesApi = (globalThis as unknown as { caches: CacheStorage }).caches;\n const cache = await cachesApi.open(CACTUS_CACHE_NAME);\n const hit = await cache.match(url);\n if (hit) {\n return new Uint8Array(await hit.arrayBuffer());\n }\n const resp = await fetch(url);\n if (!resp.ok) throw new Error(`Cactus asset fetch failed (${resp.status}) for ${url}`);\n // Clone first — Response bodies can only be consumed once.\n await cache.put(url, resp.clone());\n return new Uint8Array(await resp.arrayBuffer());\n}\n\nasync function fetchAssetBytesNode(\n url: string,\n models_dir: string,\n model_id: string,\n filename: string\n): Promise<Uint8Array> {\n const resolvedDir = resolveModelDir(models_dir, model_id);\n const filePath = path.join(resolvedDir, filename);\n try {\n const buf = await fs.readFile(filePath);\n return new Uint8Array(buf);\n } catch {\n // fall through to fetch\n }\n const resp = await fetch(url);\n if (!resp.ok) throw new Error(`Cactus asset fetch failed (${resp.status}) for ${url}`);\n const bytes = new Uint8Array(await resp.arrayBuffer());\n await fs.mkdir(resolvedDir, { recursive: true });\n const tmpPath = `${filePath}.tmp`;\n await fs.writeFile(tmpPath, bytes);\n await fs.rename(tmpPath, filePath);\n return bytes;\n}\n\nexport async function fetchAssetBytes(\n model: CactusModelConfig,\n filename: string\n): Promise<Uint8Array> {\n const model_id = model.provider_config.model_id;\n const entry = getCactusCatalogEntry(model_id);\n if (!entry) throw new Error(`Unknown Cactus model_id: ${model_id}`);\n const url = cactusAssetUrl(entry, filename);\n if (hasBrowserCacheStorage()) {\n return fetchAssetBytesBrowser(url);\n }\n return fetchAssetBytesNode(url, modelsDirOf(model), model_id, filename);\n}\n\n// ============================================================================\n// Engine cache (in-memory, per worker/process)\n// ============================================================================\n\n/** @internal Exported for tests. */\nexport const cactusEngines: Map<string, NeedleEngine> = new Map();\n/** @internal Exported for tests. */\nexport const cactusConfigJson: Map<string, unknown> = new Map();\n/** Tracks models whose assets have been persisted (downloaded) but not necessarily loaded. */\nconst cactusCachedModelIds: Set<string> = new Set();\n\nconst cactusEngineLoadsInFlight = new Map<string, Promise<NeedleEngine>>();\n\nexport async function getOrLoadEngine(model: CactusModelConfig): Promise<NeedleEngine> {\n const model_id = model.provider_config.model_id;\n const cached = cactusEngines.get(model_id);\n if (cached) return cached;\n\n const inFlight = cactusEngineLoadsInFlight.get(model_id);\n if (inFlight) return inFlight;\n\n const loadPromise = (async (): Promise<NeedleEngine> => {\n const sdk = await loadSdk();\n const entry = getCactusCatalogEntry(model_id);\n if (!entry) throw new Error(`Unknown Cactus model_id: ${model_id}`);\n\n const [weightsBytes, vocabBytes, configBytes] = await Promise.all([\n fetchAssetBytes(model, entry.assets.weights),\n fetchAssetBytes(model, entry.assets.vocab),\n fetchAssetBytes(model, entry.assets.config),\n ]);\n\n try {\n const text = new TextDecoder().decode(configBytes);\n cactusConfigJson.set(model_id, JSON.parse(text));\n } catch {\n cactusConfigJson.set(model_id, null);\n }\n\n // needle-rs `NeedleWasm.load(weights_bytes: Uint8Array, vocab_text: string)` — vocab is a string.\n const vocabText = new TextDecoder().decode(vocabBytes);\n const engine = sdk.NeedleWasm.load(weightsBytes, vocabText);\n if (!engine) {\n throw new Error(`needle-rs NeedleWasm.load returned undefined for model ${model_id}`);\n }\n cactusEngines.set(model_id, engine);\n return engine;\n })().finally(() => {\n cactusEngineLoadsInFlight.delete(model_id);\n });\n\n cactusEngineLoadsInFlight.set(model_id, loadPromise);\n return loadPromise;\n}\n\nexport function isModelLoaded(model_id: string): boolean {\n return cactusEngines.has(model_id);\n}\n\n/** Mark a model_id as having its assets persisted on disk / in Cache Storage. */\nexport function markModelCached(model_id: string): void {\n cactusCachedModelIds.add(model_id);\n}\n\n/** Returns true if the model's assets have been downloaded or the engine is currently loaded. */\nexport function isModelCached(model_id: string): boolean {\n return cactusEngines.has(model_id) || cactusCachedModelIds.has(model_id);\n}\n\nexport async function getCactusModelCacheInfo(\n model: CactusModelConfig,\n entry: CactusCatalogEntry,\n detail: string | undefined,\n signal: AbortSignal | undefined\n): Promise<CactusModelCacheInfo> {\n if (hasBrowserCacheStorage()) {\n const cachesApi = (globalThis as unknown as { caches: CacheStorage }).caches;\n const cache = await cachesApi.open(CACTUS_CACHE_NAME);\n const filenames = assetFilenames(entry);\n const cacheHits = await Promise.all(\n filenames.map(async (filename) => {\n const url = cactusAssetUrl(entry, filename);\n const hit = await cache.match(url);\n return { filename, url, hit };\n })\n );\n const allCached = cacheHits.every(({ hit }) => Boolean(hit));\n\n if (detail === \"files\") {\n return {\n allCached,\n file_sizes: Object.fromEntries(filenames.map((filename) => [filename, 0])),\n };\n }\n\n if (detail !== \"files_with_metadata\") {\n return { allCached, file_sizes: null };\n }\n\n const file_sizes: Record<string, number> = {};\n await Promise.all(\n cacheHits.map(async ({ filename, url, hit }) => {\n if (hit) {\n const contentLength = hit.headers.get(\"content-length\");\n const contentLengthSize = contentLength ? Number(contentLength) : undefined;\n if (contentLengthSize !== undefined && Number.isFinite(contentLengthSize)) {\n file_sizes[filename] = contentLengthSize;\n } else {\n file_sizes[filename] = (await hit.clone().arrayBuffer()).byteLength;\n }\n return;\n }\n const remoteSize = await getRemoteAssetSize(url, signal);\n if (remoteSize !== undefined) {\n file_sizes[filename] = remoteSize;\n }\n })\n );\n\n return {\n allCached,\n file_sizes: Object.keys(file_sizes).length > 0 ? file_sizes : null,\n };\n }\n\n return getNodeAssetCacheInfo(model, entry, detail, signal);\n}\n\n// ============================================================================\n// Sessions (no-op — needle-rs is stateless across calls)\n// ============================================================================\n\n/** @internal Exported for tests. */\nexport const cactusSessions: Map<string, Record<string, never>> = new Map();\n\nexport async function deleteCactusSession(id: string): Promise<boolean> {\n return cactusSessions.delete(id);\n}\n\n// ============================================================================\n// Eviction\n// ============================================================================\n\nasync function removeBrowserCacheEntries(entry: CactusCatalogEntry): Promise<void> {\n if (!hasBrowserCacheStorage()) return;\n const cachesApi = (globalThis as unknown as { caches: CacheStorage }).caches;\n const cache = await cachesApi.open(CACTUS_CACHE_NAME);\n for (const filename of [entry.assets.weights, entry.assets.vocab, entry.assets.config]) {\n const url = cactusAssetUrl(entry, filename);\n try {\n await cache.delete(url);\n } catch {\n /* ignore */\n }\n }\n}\n\nasync function removeNodeCacheDir(model: CactusModelConfig, model_id: string): Promise<void> {\n if (hasBrowserCacheStorage()) return;\n const models_dir = modelsDirOf(model);\n const resolvedDir = resolveModelDir(models_dir, model_id);\n await fs.rm(resolvedDir, { recursive: true, force: true });\n}\n\nfunction disposeCactusEngine(model_id: string): void {\n const engine = cactusEngines.get(model_id);\n if (engine) {\n try {\n (engine as unknown as { free?: () => void }).free?.();\n } catch {\n /* best effort */\n }\n }\n cactusEngines.delete(model_id);\n cactusConfigJson.delete(model_id);\n cactusCachedModelIds.delete(model_id);\n}\n\nexport async function removeCachedAssets(model: CactusModelConfig): Promise<void> {\n const model_id = model.provider_config.model_id;\n const entry = getCactusCatalogEntry(model_id);\n if (!entry) return;\n await Promise.all([removeBrowserCacheEntries(entry), removeNodeCacheDir(model, model_id)]);\n disposeCactusEngine(model_id);\n}\n\n/** Best-effort cleanup on shutdown. */\nexport async function disposeCactusResources(): Promise<void> {\n for (const id of Array.from(cactusEngines.keys())) {\n disposeCactusEngine(id);\n }\n cactusEngines.clear();\n cactusConfigJson.clear();\n cactusCachedModelIds.clear();\n cactusSessions.clear();\n}\n",
6
6
  "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nexport const LOCAL_CACTUS = \"LOCAL_CACTUS\";\nexport const CACTUS_NEEDLE_26M = \"needle-26m\";\nexport const CACTUS_DEFAULT_HF_REPO = \"Abdalrahman/needle-rs-safetensors\";\nexport const CACTUS_DEFAULT_REVISION = \"main\";\n\n/** Browser Cache Storage name used by `fetchAssetBytes` and `removeCachedAssets`. */\nexport const CACTUS_CACHE_NAME = \"cactus-models-v1\";\n\n/** Node/Bun on-disk cache root. */\nexport const CACTUS_DEFAULT_MODELS_DIR = \"~/.cache/cactus-models\";\n",
7
7
  "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Capability } from \"@workglow/ai/worker\";\nimport {\n CACTUS_DEFAULT_HF_REPO,\n CACTUS_DEFAULT_REVISION,\n CACTUS_NEEDLE_26M,\n} from \"./Cactus_Constants\";\n\nexport interface CactusCatalogEntry {\n readonly model_id: string;\n readonly title: string;\n readonly description: string;\n readonly hf_repo: string;\n readonly revision: string;\n readonly assets: {\n readonly weights: string;\n readonly vocab: string;\n readonly config: string;\n };\n readonly capabilities: readonly Capability[];\n}\n\nexport const CACTUS_CATALOG: readonly CactusCatalogEntry[] = [\n {\n model_id: CACTUS_NEEDLE_26M,\n title: \"Needle 26M\",\n description:\n \"Specialized 26M-parameter tool-routing transformer. INT4 SafeTensors, 22 MB. Runs via WASM in browser and Node/Bun.\",\n hf_repo: CACTUS_DEFAULT_HF_REPO,\n revision: CACTUS_DEFAULT_REVISION,\n assets: {\n weights: \"needle.safetensors\",\n vocab: \"vocab.txt\",\n config: \"config.json\",\n },\n capabilities: [\"tool-use\"],\n },\n] as const;\n\nexport function getCactusCatalogEntry(model_id: string): CactusCatalogEntry | undefined {\n return CACTUS_CATALOG.find((e) => e.model_id === model_id);\n}\n\nexport function cactusAssetUrl(entry: CactusCatalogEntry, filename: string): string {\n return `https://huggingface.co/${entry.hf_repo}/resolve/${entry.revision}/${filename}`;\n}\n",
8
8
  "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { AiProviderRegisterOptions } from \"@workglow/ai\";\nimport { registerProviderInline } from \"@workglow/ai/provider-utils\";\nimport { CactusQueuedProvider } from \"./CactusQueuedProvider\";\nimport { CACTUS_PREVIEW_TASKS, CACTUS_RUN_FNS } from \"./common/Cactus_JobRunFns\";\n\nexport async function registerCactusInline(options?: AiProviderRegisterOptions): Promise<void> {\n await registerProviderInline(\n new CactusQueuedProvider(CACTUS_RUN_FNS, CACTUS_PREVIEW_TASKS),\n \"Cactus\",\n options\n );\n}\n",
@@ -11,14 +11,14 @@
11
11
  "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { Capability, ModelRecord } from \"@workglow/ai/worker\";\nimport { CACTUS_CAPABILITY_SETS } from \"./Cactus_CapabilitySets\";\n\nexport const CACTUS_RUN_FN_SPECS = CACTUS_CAPABILITY_SETS.map((serves) => ({ serves }));\n\nexport function cactusWorkerRunFnSpecs(): readonly {\n readonly serves: readonly Capability[];\n}[] {\n return CACTUS_RUN_FN_SPECS;\n}\n\ntype CapabilityHints = Pick<ModelRecord, \"model_id\" | \"provider_config\" | \"capabilities\">;\n\n/**\n * needle-rs ships a single model architecture; capability inference is constant.\n */\nexport function inferCactusCapabilities(_model: CapabilityHints): readonly Capability[] {\n return [\"tool-use\", \"model.download\", \"model.download-remove\", \"model.search\", \"model.info\"];\n}\n",
12
12
  "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {\n AiProviderRunFn,\n ModelDownloadTaskRunInput,\n ModelDownloadTaskRunOutput,\n} from \"@workglow/ai\";\nimport { getCactusCatalogEntry } from \"./Cactus_ModelCatalog\";\nimport type { CactusModelConfig } from \"./Cactus_ModelSchema\";\nimport { fetchAssetBytes, markModelCached } from \"./Cactus_Runtime\";\n\nexport const Cactus_Download: AiProviderRunFn<\n ModelDownloadTaskRunInput,\n ModelDownloadTaskRunOutput,\n CactusModelConfig\n> = async (input, model, _signal, emit) => {\n if (!model) throw new Error(\"Model config is required for ModelDownloadTask.\");\n const model_id = model.provider_config.model_id;\n const entry = getCactusCatalogEntry(model_id);\n if (!entry) throw new Error(`Unknown Cactus model_id: ${model_id}`);\n\n const assets = [entry.assets.weights, entry.assets.vocab, entry.assets.config];\n for (let i = 0; i < assets.length; i++) {\n emit({\n type: \"phase\",\n message: `Downloading ${assets[i]}`,\n progress: Math.round(((i + 0.5) / assets.length) * 99),\n });\n await fetchAssetBytes(model, assets[i]);\n }\n markModelCached(model_id);\n emit({ type: \"finish\", data: { model: input.model! } });\n};\n",
13
13
  "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {\n AiProviderRunFn,\n ModelDownloadRemoveTaskRunInput,\n ModelDownloadRemoveTaskRunOutput,\n} from \"@workglow/ai\";\nimport type { CactusModelConfig } from \"./Cactus_ModelSchema\";\nimport { removeCachedAssets } from \"./Cactus_Runtime\";\n\nexport const Cactus_DownloadRemove: AiProviderRunFn<\n ModelDownloadRemoveTaskRunInput,\n ModelDownloadRemoveTaskRunOutput,\n CactusModelConfig\n> = async (input, model, _signal, emit) => {\n if (!model) throw new Error(\"Model config is required for ModelDownloadRemoveTask.\");\n await removeCachedAssets(model);\n emit({ type: \"finish\", data: { model: input.model } });\n};\n",
14
- "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { AiProviderRunFn, ModelInfoTaskInput, ModelInfoTaskOutput } from \"@workglow/ai\";\nimport { getCactusCatalogEntry } from \"./Cactus_ModelCatalog\";\nimport type { CactusModelConfig } from \"./Cactus_ModelSchema\";\nimport { isModelCached, isModelLoaded } from \"./Cactus_Runtime\";\n\nexport const Cactus_ModelInfo: AiProviderRunFn<\n ModelInfoTaskInput,\n ModelInfoTaskOutput,\n CactusModelConfig\n> = async (input, model, _signal, emit) => {\n if (!model) throw new Error(\"Model config is required for ModelInfoTask.\");\n const model_id = model.provider_config.model_id;\n const entry = getCactusCatalogEntry(model_id);\n if (!entry) throw new Error(`Unknown Cactus model_id: ${model_id}`);\n\n const is_loaded = isModelLoaded(model_id);\n const is_cached = isModelCached(model_id);\n\n emit({\n type: \"finish\",\n data: {\n model: input.model,\n is_local: true,\n is_remote: false,\n supports_browser: true,\n supports_node: true,\n is_cached,\n is_loaded,\n file_sizes: null,\n },\n });\n};\n",
14
+ "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { AiProviderRunFn, ModelInfoTaskInput, ModelInfoTaskOutput } from \"@workglow/ai\";\nimport { getCactusCatalogEntry } from \"./Cactus_ModelCatalog\";\nimport type { CactusModelConfig } from \"./Cactus_ModelSchema\";\nimport { getCactusModelCacheInfo, isModelCached, isModelLoaded } from \"./Cactus_Runtime\";\n\nexport const Cactus_ModelInfo: AiProviderRunFn<\n ModelInfoTaskInput,\n ModelInfoTaskOutput,\n CactusModelConfig\n> = async (input, model, signal, emit) => {\n if (!model) throw new Error(\"Model config is required for ModelInfoTask.\");\n const model_id = model.provider_config.model_id;\n const entry = getCactusCatalogEntry(model_id);\n if (!entry) throw new Error(`Unknown Cactus model_id: ${model_id}`);\n\n const is_loaded = isModelLoaded(model_id);\n const cacheInfo = await getCactusModelCacheInfo(model, entry, input.detail, signal);\n const is_cached = is_loaded || isModelCached(model_id) || cacheInfo.allCached;\n\n emit({\n type: \"finish\",\n data: {\n model: input.model,\n is_local: true,\n is_remote: false,\n supports_browser: true,\n supports_node: true,\n is_cached,\n is_loaded,\n file_sizes: cacheInfo.file_sizes,\n },\n });\n};\n",
15
15
  "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {\n AiProviderRunFn,\n ModelSearchResultItem,\n ModelSearchTaskInput,\n ModelSearchTaskOutput,\n} from \"@workglow/ai\";\nimport { LOCAL_CACTUS } from \"./Cactus_Constants\";\nimport { CACTUS_CATALOG } from \"./Cactus_ModelCatalog\";\n\nexport const Cactus_ModelSearch: AiProviderRunFn<\n ModelSearchTaskInput,\n ModelSearchTaskOutput\n> = async (input, _model, _signal, emit) => {\n const query = (input.query ?? \"\").trim().toLowerCase();\n const results: ModelSearchResultItem[] = CACTUS_CATALOG.filter(\n (e) =>\n !query || e.model_id.toLowerCase().includes(query) || e.title.toLowerCase().includes(query)\n ).map((e) => ({\n id: e.model_id,\n label: e.title,\n description: e.description,\n record: {\n model_id: e.model_id,\n title: e.title,\n description: e.description,\n provider: LOCAL_CACTUS,\n provider_config: { model_id: e.model_id },\n capabilities: [...e.capabilities],\n metadata: {},\n },\n raw: e,\n }));\n emit({ type: \"finish\", data: { results } });\n};\n",
16
- "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {\n AiProviderRunFn,\n ToolCallingTaskInput,\n ToolCallingTaskOutput,\n ToolCalls,\n ToolDefinition,\n} from \"@workglow/ai\";\nimport { extractMessageText } from \"@workglow/ai/provider-utils\";\nimport { filterValidToolCalls } from \"@workglow/ai/worker\";\nimport type { CactusModelConfig } from \"./Cactus_ModelSchema\";\nimport { getOrLoadEngine } from \"./Cactus_Runtime\";\n\nfunction buildToolsJson(tools: ReadonlyArray<ToolDefinition>): string {\n return JSON.stringify(\n tools.map((t) => ({\n name: t.name,\n ...(t.description ? { description: t.description } : {}),\n ...(t.inputSchema ? { parameters: t.inputSchema } : {}),\n }))\n );\n}\n\nfunction promptText(input: ToolCallingTaskInput): string {\n if (typeof input.prompt === \"string\") return input.prompt;\n if (input.prompt) return extractMessageText(input.prompt);\n if (input.messages && input.messages.length > 0) {\n const last = input.messages[input.messages.length - 1];\n return extractMessageText(last.content);\n }\n return \"\";\n}\n\nfunction parseToolCalls(raw: string): ToolCalls {\n if (!raw) return [];\n try {\n const obj = JSON.parse(raw);\n if (Array.isArray(obj)) {\n return obj.map((o, i) => ({\n id: `call_${i}`,\n name: String(o.name ?? \"\"),\n input: (o.arguments ?? o.params ?? {}) as Record<string, unknown>,\n }));\n }\n if (obj && typeof obj === \"object\" && typeof obj.name === \"string\") {\n return [\n {\n id: \"call_0\",\n name: obj.name,\n input: (obj.arguments ?? obj.params ?? {}) as Record<string, unknown>,\n },\n ];\n }\n } catch {\n /* fall through */\n }\n return [];\n}\n\nexport const Cactus_ToolCalling: AiProviderRunFn<\n ToolCallingTaskInput,\n ToolCallingTaskOutput,\n CactusModelConfig\n> = async (input, model, signal, emit) => {\n if (!model) throw new Error(\"Model config is required for ToolCallingTask.\");\n if (signal.aborted) throw signal.reason ?? new Error(\"The operation was aborted\");\n\n const engine = await getOrLoadEngine(model);\n const query = promptText(input);\n const toolsJson = buildToolsJson(input.tools);\n\n let raw = \"\";\n const engineWithStream = engine as unknown as {\n run_stream?: (q: string, t: string, cb: (chunk: string) => void) => Promise<string>;\n run: (q: string, t: string) => Promise<string> | string;\n };\n\n if (typeof engineWithStream.run_stream === \"function\") {\n raw = await engineWithStream.run_stream(query, toolsJson, (chunk) => {\n emit({ type: \"text-delta\", port: \"text\", textDelta: chunk });\n });\n } else {\n const out = await engineWithStream.run(query, toolsJson);\n raw = typeof out === \"string\" ? out : String(out);\n }\n\n const parsed: ToolCalls = parseToolCalls(raw);\n const validToolCalls = filterValidToolCalls(parsed, input.tools);\n if (validToolCalls.length > 0) {\n emit({ type: \"object-delta\", port: \"toolCalls\", objectDelta: [...validToolCalls] });\n }\n emit({ type: \"finish\", data: { text: raw, toolCalls: validToolCalls } });\n};\n",
16
+ "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {\n AiProviderRunFn,\n ToolCallingTaskInput,\n ToolCallingTaskOutput,\n ToolCalls,\n ToolDefinition,\n} from \"@workglow/ai\";\nimport { extractMessageText } from \"@workglow/ai/provider-utils\";\nimport { filterValidToolCalls, sanitizeToolArgs } from \"@workglow/ai/worker\";\nimport type { CactusModelConfig } from \"./Cactus_ModelSchema\";\nimport { getOrLoadEngine } from \"./Cactus_Runtime\";\n\nfunction buildToolsJson(tools: ReadonlyArray<ToolDefinition>): string {\n return JSON.stringify(\n tools.map((t) => ({\n name: t.name,\n ...(t.description ? { description: t.description } : {}),\n ...(t.inputSchema ? { parameters: t.inputSchema } : {}),\n }))\n );\n}\n\nfunction promptText(input: ToolCallingTaskInput): string {\n if (typeof input.prompt === \"string\") return input.prompt;\n if (input.prompt) return extractMessageText(input.prompt);\n if (input.messages && input.messages.length > 0) {\n const last = input.messages[input.messages.length - 1];\n return extractMessageText(last.content);\n }\n return \"\";\n}\n\nfunction parseToolCalls(raw: string): ToolCalls {\n if (!raw) return [];\n try {\n const obj = JSON.parse(raw);\n if (Array.isArray(obj)) {\n return obj.map((o, i) => ({\n id: `call_${i}`,\n name: String(o.name ?? \"\"),\n input: sanitizeToolArgs(o.arguments ?? o.params ?? {}) as Record<string, unknown>,\n }));\n }\n if (obj && typeof obj === \"object\" && typeof obj.name === \"string\") {\n return [\n {\n id: \"call_0\",\n name: obj.name,\n input: sanitizeToolArgs(obj.arguments ?? obj.params ?? {}) as Record<string, unknown>,\n },\n ];\n }\n } catch {\n /* fall through */\n }\n return [];\n}\n\nexport const Cactus_ToolCalling: AiProviderRunFn<\n ToolCallingTaskInput,\n ToolCallingTaskOutput,\n CactusModelConfig\n> = async (input, model, signal, emit) => {\n if (!model) throw new Error(\"Model config is required for ToolCallingTask.\");\n if (signal.aborted) throw signal.reason ?? new Error(\"The operation was aborted\");\n\n const engine = await getOrLoadEngine(model);\n const query = promptText(input);\n const toolsJson = buildToolsJson(input.tools);\n\n let raw = \"\";\n const engineWithStream = engine as unknown as {\n run_stream?: (q: string, t: string, cb: (chunk: string) => void) => Promise<string>;\n run: (q: string, t: string) => Promise<string> | string;\n };\n\n if (typeof engineWithStream.run_stream === \"function\") {\n raw = await engineWithStream.run_stream(query, toolsJson, (chunk) => {\n emit({ type: \"text-delta\", port: \"text\", textDelta: chunk });\n });\n } else {\n const out = await engineWithStream.run(query, toolsJson);\n raw = typeof out === \"string\" ? out : String(out);\n }\n\n const parsed: ToolCalls = parseToolCalls(raw);\n const validToolCalls = filterValidToolCalls(parsed, input.tools);\n if (validToolCalls.length > 0) {\n emit({ type: \"object-delta\", port: \"toolCalls\", objectDelta: [...validToolCalls] });\n }\n emit({ type: \"finish\", data: { text: raw, toolCalls: validToolCalls } });\n};\n",
17
17
  "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type { AiProviderRunFnRegistration } from \"@workglow/ai\";\nimport {\n CACTUS_MODEL_DOWNLOAD,\n CACTUS_MODEL_DOWNLOAD_REMOVE,\n CACTUS_MODEL_INFO,\n CACTUS_MODEL_SEARCH,\n CACTUS_TOOL_USE,\n} from \"./Cactus_CapabilitySets\";\nimport { Cactus_Download } from \"./Cactus_Download\";\nimport { Cactus_DownloadRemove } from \"./Cactus_DownloadRemove\";\nimport { Cactus_ModelInfo } from \"./Cactus_ModelInfo\";\nimport type { CactusModelConfig } from \"./Cactus_ModelSchema\";\nimport { Cactus_ModelSearch } from \"./Cactus_ModelSearch\";\nimport { Cactus_ToolCalling } from \"./Cactus_ToolCalling\";\n\nexport {\n cactusConfigJson,\n cactusEngines,\n deleteCactusSession,\n disposeCactusResources,\n getOrLoadEngine,\n loadSdk,\n removeCachedAssets,\n} from \"./Cactus_Runtime\";\n\nexport const CACTUS_RUN_FNS: readonly AiProviderRunFnRegistration<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any,\n CactusModelConfig\n>[] = [\n { serves: CACTUS_TOOL_USE, runFn: Cactus_ToolCalling },\n { serves: CACTUS_MODEL_DOWNLOAD, runFn: Cactus_Download },\n { serves: CACTUS_MODEL_DOWNLOAD_REMOVE, runFn: Cactus_DownloadRemove },\n { serves: CACTUS_MODEL_SEARCH, runFn: Cactus_ModelSearch },\n { serves: CACTUS_MODEL_INFO, runFn: Cactus_ModelInfo },\n];\n\n/** No preview-only tasks for Cactus today. */\nexport const CACTUS_PREVIEW_TASKS = {} as const;\n",
18
18
  "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport { registerProviderWorker } from \"@workglow/ai/provider-utils\";\nimport { CactusProvider } from \"./CactusProvider\";\nimport { CACTUS_PREVIEW_TASKS, CACTUS_RUN_FNS } from \"./common/Cactus_JobRunFns\";\n\nexport async function registerCactusWorker(): Promise<void> {\n await registerProviderWorker(\n (ws) => new CactusProvider(CACTUS_RUN_FNS, CACTUS_PREVIEW_TASKS).registerOnWorkerServer(ws),\n \"Cactus\"\n );\n}\n",
19
19
  "/**\n * @license\n * Copyright 2026 Steven Roussey <sroussey@gmail.com>\n * SPDX-License-Identifier: Apache-2.0\n */\n\nimport type {\n AiProviderPreviewRunFn,\n AiProviderRunFnRegistration,\n Capability,\n ModelConfig,\n ModelRecord,\n} from \"@workglow/ai/worker\";\nimport { AiProvider } from \"@workglow/ai/worker\";\nimport { cactusWorkerRunFnSpecs, inferCactusCapabilities } from \"./common/Cactus_Capabilities\";\nimport { LOCAL_CACTUS } from \"./common/Cactus_Constants\";\nimport type { CactusModelConfig } from \"./common/Cactus_ModelSchema\";\nimport { deleteCactusSession } from \"./common/Cactus_Runtime\";\n\n/** Worker-server registration for Cactus (browser + Node/Bun via WASM). */\nexport class CactusProvider extends AiProvider<CactusModelConfig> {\n readonly name = LOCAL_CACTUS;\n readonly displayName = \"Cactus (Needle)\";\n readonly isLocal = true;\n readonly supportsBrowser = true;\n\n constructor(\n promiseRunFns?: readonly AiProviderRunFnRegistration<\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n any,\n CactusModelConfig\n >[],\n previewTasks?: Record<\n string,\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n AiProviderPreviewRunFn<any, any, CactusModelConfig>\n >\n ) {\n super(promiseRunFns, previewTasks);\n }\n\n override inferCapabilities(model: ModelRecord): readonly Capability[] {\n return inferCactusCapabilities(model);\n }\n\n protected override workerRunFnSpecs(): readonly { serves: readonly Capability[] }[] {\n return cactusWorkerRunFnSpecs();\n }\n\n override createSession(_model: ModelConfig): string {\n return crypto.randomUUID();\n }\n\n override async disposeSession(sessionId: string): Promise<void> {\n await deleteCactusSession(sessionId);\n }\n}\n"
20
20
  ],
21
- "mappings": "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",
22
- "debugId": "47067466D3EDE65A64756E2164756E21",
21
+ "mappings": "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",
22
+ "debugId": "625B2696DC38FBF764756E2164756E21",
23
23
  "names": []
24
24
  }
@@ -6,17 +6,17 @@
6
6
  export * from "./ai/common/Cactus_Constants";
7
7
  export * from "./ai/common/Cactus_ModelCatalog";
8
8
  export * from "./ai/common/Cactus_ModelSchema";
9
- export * from "./ai/CactusProvider";
10
- export * from "./ai/CactusQueuedProvider";
11
- export * from "./ai/registerCactus";
12
- import { CactusQueuedProvider } from "./ai/CactusQueuedProvider";
9
+ export * from "./ai/CactusProvider.browser";
10
+ export * from "./ai/CactusQueuedProvider.browser";
11
+ export * from "./ai/registerCactus.browser";
12
+ import { CactusQueuedProvider } from "./ai/CactusQueuedProvider.browser";
13
13
  /**
14
14
  * @internal Symbols exported only for use by `@workglow/test`. Not part of the stable public API.
15
15
  *
16
16
  * `cactusEngines` and `cactusConfigJson` are re-exported here so that tests can
17
17
  * seed and inspect the runtime state used by the run-fns bundled into the `./ai`
18
18
  * entry point. The `./ai` and `./ai-runtime` entry points are bundled separately
19
- * their copies of `Cactus_Runtime.ts` are distinct module instances. Reading
19
+ * and their runtime state copies are distinct module instances. Reading
20
20
  * the runtime state via `_testOnly` (rather than `@workglow/cactus/ai-runtime`)
21
21
  * guarantees the test observes the same Map that the run-fns mutate.
22
22
  */
@@ -1 +1 @@
1
- {"version":3,"file":"ai.browser.d.ts","sourceRoot":"","sources":["../src/ai.browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAO/C,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,qBAAqB,CAAC;AAEpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAKjE;;;;;;;;;GASG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;CAMZ,CAAC"}
1
+ {"version":3,"file":"ai.browser.d.ts","sourceRoot":"","sources":["../src/ai.browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH,cAAc,8BAA8B,CAAC;AAC7C,cAAc,iCAAiC,CAAC;AAChD,cAAc,gCAAgC,CAAC;AAO/C,cAAc,6BAA6B,CAAC;AAC5C,cAAc,mCAAmC,CAAC;AAClD,cAAc,6BAA6B,CAAC;AAE5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,mCAAmC,CAAC;AAKzE;;;;;;;;;GASG;AACH,eAAO,MAAM,SAAS;;;;;;;;;;;;;;;;;;;;;CAMZ,CAAC"}
@@ -84,7 +84,7 @@ var CactusModelConfigSchema = {
84
84
  required: [...ModelConfigSchema.required, ...CactusModelSchema.required],
85
85
  additionalProperties: false
86
86
  };
87
- // src/ai/CactusProvider.ts
87
+ // src/ai/CactusProvider.browser.ts
88
88
  import { AiProvider } from "@workglow/ai/worker";
89
89
 
90
90
  // src/ai/common/Cactus_CapabilitySets.ts
@@ -112,9 +112,7 @@ function inferCactusCapabilities(_model) {
112
112
  return ["tool-use", "model.download", "model.download-remove", "model.search", "model.info"];
113
113
  }
114
114
 
115
- // src/ai/common/Cactus_Runtime.ts
116
- import fs from "node:fs/promises";
117
- import path from "node:path";
115
+ // src/ai/common/Cactus_Runtime.browser.ts
118
116
  var _sdk;
119
117
  var _sdkInitPromise;
120
118
  async function loadSdk() {
@@ -132,11 +130,27 @@ async function loadSdk() {
132
130
  });
133
131
  return _sdkInitPromise;
134
132
  }
135
- function hasBrowserCacheStorage() {
136
- return typeof globalThis !== "undefined" && "caches" in globalThis && typeof globalThis.caches?.open === "function";
133
+ function getCactusSdk() {
134
+ if (!_sdk)
135
+ throw new Error("Cactus SDK not loaded; call loadSdk() first");
136
+ return _sdk;
137
+ }
138
+ function assetFilenames(entry) {
139
+ return [entry.assets.weights, entry.assets.vocab, entry.assets.config];
137
140
  }
138
- function modelsDirOf(model) {
139
- return model.provider_config.models_dir ?? CACTUS_DEFAULT_MODELS_DIR;
141
+ async function getRemoteAssetSize(url, signal) {
142
+ try {
143
+ const response = await fetch(url, { method: "HEAD", signal });
144
+ if (!response.ok)
145
+ return;
146
+ const contentLength = response.headers.get("content-length");
147
+ if (!contentLength)
148
+ return;
149
+ const size = Number(contentLength);
150
+ return Number.isFinite(size) ? size : undefined;
151
+ } catch {
152
+ return;
153
+ }
140
154
  }
141
155
  async function fetchAssetBytesBrowser(url) {
142
156
  const cachesApi = globalThis.caches;
@@ -151,33 +165,13 @@ async function fetchAssetBytesBrowser(url) {
151
165
  await cache.put(url, resp.clone());
152
166
  return new Uint8Array(await resp.arrayBuffer());
153
167
  }
154
- async function fetchAssetBytesNode(url, models_dir, model_id, filename) {
155
- const resolvedDir = models_dir.startsWith("~/") ? path.join(process.env.HOME ?? process.env.USERPROFILE ?? ".", models_dir.slice(2), model_id) : path.resolve(models_dir, model_id);
156
- const filePath = path.join(resolvedDir, filename);
157
- try {
158
- const buf = await fs.readFile(filePath);
159
- return new Uint8Array(buf);
160
- } catch {}
161
- const resp = await fetch(url);
162
- if (!resp.ok)
163
- throw new Error(`Cactus asset fetch failed (${resp.status}) for ${url}`);
164
- const bytes = new Uint8Array(await resp.arrayBuffer());
165
- await fs.mkdir(resolvedDir, { recursive: true });
166
- const tmpPath = `${filePath}.tmp`;
167
- await fs.writeFile(tmpPath, bytes);
168
- await fs.rename(tmpPath, filePath);
169
- return bytes;
170
- }
171
168
  async function fetchAssetBytes(model, filename) {
172
169
  const model_id = model.provider_config.model_id;
173
170
  const entry = getCactusCatalogEntry(model_id);
174
171
  if (!entry)
175
172
  throw new Error(`Unknown Cactus model_id: ${model_id}`);
176
173
  const url = cactusAssetUrl(entry, filename);
177
- if (hasBrowserCacheStorage()) {
178
- return fetchAssetBytesBrowser(url);
179
- }
180
- return fetchAssetBytesNode(url, modelsDirOf(model), model_id, filename);
174
+ return fetchAssetBytesBrowser(url);
181
175
  }
182
176
  var cactusEngines = new Map;
183
177
  var cactusConfigJson = new Map;
@@ -229,13 +223,52 @@ function markModelCached(model_id) {
229
223
  function isModelCached(model_id) {
230
224
  return cactusEngines.has(model_id) || cactusCachedModelIds.has(model_id);
231
225
  }
226
+ async function getCactusModelCacheInfo(_model, entry, detail, signal) {
227
+ const cachesApi = globalThis.caches;
228
+ const cache = await cachesApi.open(CACTUS_CACHE_NAME);
229
+ const filenames = assetFilenames(entry);
230
+ const cacheHits = await Promise.all(filenames.map(async (filename) => {
231
+ const url = cactusAssetUrl(entry, filename);
232
+ const hit = await cache.match(url);
233
+ return { filename, url, hit };
234
+ }));
235
+ const allCached = cacheHits.every(({ hit }) => Boolean(hit));
236
+ if (detail === "files") {
237
+ return {
238
+ allCached,
239
+ file_sizes: Object.fromEntries(filenames.map((filename) => [filename, 0]))
240
+ };
241
+ }
242
+ if (detail !== "files_with_metadata") {
243
+ return { allCached, file_sizes: null };
244
+ }
245
+ const file_sizes = {};
246
+ await Promise.all(cacheHits.map(async ({ filename, url, hit }) => {
247
+ if (hit) {
248
+ const contentLength = hit.headers.get("content-length");
249
+ const contentLengthSize = contentLength ? Number(contentLength) : undefined;
250
+ if (contentLengthSize !== undefined && Number.isFinite(contentLengthSize)) {
251
+ file_sizes[filename] = contentLengthSize;
252
+ } else {
253
+ file_sizes[filename] = (await hit.clone().arrayBuffer()).byteLength;
254
+ }
255
+ return;
256
+ }
257
+ const remoteSize = await getRemoteAssetSize(url, signal);
258
+ if (remoteSize !== undefined) {
259
+ file_sizes[filename] = remoteSize;
260
+ }
261
+ }));
262
+ return {
263
+ allCached,
264
+ file_sizes: Object.keys(file_sizes).length > 0 ? file_sizes : null
265
+ };
266
+ }
232
267
  var cactusSessions = new Map;
233
268
  async function deleteCactusSession(id) {
234
269
  return cactusSessions.delete(id);
235
270
  }
236
271
  async function removeBrowserCacheEntries(entry) {
237
- if (!hasBrowserCacheStorage())
238
- return;
239
272
  const cachesApi = globalThis.caches;
240
273
  const cache = await cachesApi.open(CACTUS_CACHE_NAME);
241
274
  for (const filename of [entry.assets.weights, entry.assets.vocab, entry.assets.config]) {
@@ -245,13 +278,6 @@ async function removeBrowserCacheEntries(entry) {
245
278
  } catch {}
246
279
  }
247
280
  }
248
- async function removeNodeCacheDir(model, model_id) {
249
- if (hasBrowserCacheStorage())
250
- return;
251
- const models_dir = modelsDirOf(model);
252
- const resolvedDir = models_dir.startsWith("~/") ? path.join(process.env.HOME ?? process.env.USERPROFILE ?? ".", models_dir.slice(2), model_id) : path.resolve(models_dir, model_id);
253
- await fs.rm(resolvedDir, { recursive: true, force: true });
254
- }
255
281
  function disposeCactusEngine(model_id) {
256
282
  const engine = cactusEngines.get(model_id);
257
283
  if (engine) {
@@ -268,11 +294,20 @@ async function removeCachedAssets(model) {
268
294
  const entry = getCactusCatalogEntry(model_id);
269
295
  if (!entry)
270
296
  return;
271
- await Promise.all([removeBrowserCacheEntries(entry), removeNodeCacheDir(model, model_id)]);
297
+ await removeBrowserCacheEntries(entry);
272
298
  disposeCactusEngine(model_id);
273
299
  }
300
+ async function disposeCactusResources() {
301
+ for (const id of Array.from(cactusEngines.keys())) {
302
+ disposeCactusEngine(id);
303
+ }
304
+ cactusEngines.clear();
305
+ cactusConfigJson.clear();
306
+ cactusCachedModelIds.clear();
307
+ cactusSessions.clear();
308
+ }
274
309
 
275
- // src/ai/CactusProvider.ts
310
+ // src/ai/CactusProvider.browser.ts
276
311
  class CactusProvider extends AiProvider {
277
312
  name = LOCAL_CACTUS;
278
313
  displayName = "Cactus (Needle)";
@@ -294,7 +329,7 @@ class CactusProvider extends AiProvider {
294
329
  await deleteCactusSession(sessionId);
295
330
  }
296
331
  }
297
- // src/ai/CactusQueuedProvider.ts
332
+ // src/ai/CactusQueuedProvider.browser.ts
298
333
  import { QueuedAiProvider } from "@workglow/ai";
299
334
  class CactusQueuedProvider extends QueuedAiProvider {
300
335
  name = LOCAL_CACTUS;
@@ -317,12 +352,12 @@ class CactusQueuedProvider extends QueuedAiProvider {
317
352
  await deleteCactusSession(sessionId);
318
353
  }
319
354
  }
320
- // src/ai/registerCactus.ts
355
+ // src/ai/registerCactus.browser.ts
321
356
  import { registerProviderWithWorker } from "@workglow/ai/provider-utils";
322
357
  async function registerCactus(options) {
323
358
  await registerProviderWithWorker(new CactusQueuedProvider, "Cactus", options);
324
359
  }
325
- // src/ai/common/Cactus_Download.ts
360
+ // src/ai/common/Cactus_Download.browser.ts
326
361
  var Cactus_Download = async (input, model, _signal, emit) => {
327
362
  if (!model)
328
363
  throw new Error("Model config is required for ModelDownloadTask.");
@@ -343,7 +378,7 @@ var Cactus_Download = async (input, model, _signal, emit) => {
343
378
  emit({ type: "finish", data: { model: input.model } });
344
379
  };
345
380
 
346
- // src/ai/common/Cactus_DownloadRemove.ts
381
+ // src/ai/common/Cactus_DownloadRemove.browser.ts
347
382
  var Cactus_DownloadRemove = async (input, model, _signal, emit) => {
348
383
  if (!model)
349
384
  throw new Error("Model config is required for ModelDownloadRemoveTask.");
@@ -351,8 +386,8 @@ var Cactus_DownloadRemove = async (input, model, _signal, emit) => {
351
386
  emit({ type: "finish", data: { model: input.model } });
352
387
  };
353
388
 
354
- // src/ai/common/Cactus_ModelInfo.ts
355
- var Cactus_ModelInfo = async (input, model, _signal, emit) => {
389
+ // src/ai/common/Cactus_ModelInfo.browser.ts
390
+ var Cactus_ModelInfo = async (input, model, signal, emit) => {
356
391
  if (!model)
357
392
  throw new Error("Model config is required for ModelInfoTask.");
358
393
  const model_id = model.provider_config.model_id;
@@ -360,7 +395,8 @@ var Cactus_ModelInfo = async (input, model, _signal, emit) => {
360
395
  if (!entry)
361
396
  throw new Error(`Unknown Cactus model_id: ${model_id}`);
362
397
  const is_loaded = isModelLoaded(model_id);
363
- const is_cached = isModelCached(model_id);
398
+ const cacheInfo = await getCactusModelCacheInfo(model, entry, input.detail, signal);
399
+ const is_cached = is_loaded || isModelCached(model_id) || cacheInfo.allCached;
364
400
  emit({
365
401
  type: "finish",
366
402
  data: {
@@ -371,7 +407,7 @@ var Cactus_ModelInfo = async (input, model, _signal, emit) => {
371
407
  supports_node: true,
372
408
  is_cached,
373
409
  is_loaded,
374
- file_sizes: null
410
+ file_sizes: cacheInfo.file_sizes
375
411
  }
376
412
  });
377
413
  };
@@ -397,9 +433,9 @@ var Cactus_ModelSearch = async (input, _model, _signal, emit) => {
397
433
  emit({ type: "finish", data: { results } });
398
434
  };
399
435
 
400
- // src/ai/common/Cactus_ToolCalling.ts
436
+ // src/ai/common/Cactus_ToolCalling.browser.ts
401
437
  import { extractMessageText } from "@workglow/ai/provider-utils";
402
- import { filterValidToolCalls } from "@workglow/ai/worker";
438
+ import { filterValidToolCalls, sanitizeToolArgs } from "@workglow/ai/worker";
403
439
  function buildToolsJson(tools) {
404
440
  return JSON.stringify(tools.map((t) => ({
405
441
  name: t.name,
@@ -427,7 +463,7 @@ function parseToolCalls(raw) {
427
463
  return obj.map((o, i) => ({
428
464
  id: `call_${i}`,
429
465
  name: String(o.name ?? ""),
430
- input: o.arguments ?? o.params ?? {}
466
+ input: sanitizeToolArgs(o.arguments ?? o.params ?? {})
431
467
  }));
432
468
  }
433
469
  if (obj && typeof obj === "object" && typeof obj.name === "string") {
@@ -435,7 +471,7 @@ function parseToolCalls(raw) {
435
471
  {
436
472
  id: "call_0",
437
473
  name: obj.name,
438
- input: obj.arguments ?? obj.params ?? {}
474
+ input: sanitizeToolArgs(obj.arguments ?? obj.params ?? {})
439
475
  }
440
476
  ];
441
477
  }
@@ -468,7 +504,7 @@ var Cactus_ToolCalling = async (input, model, signal, emit) => {
468
504
  emit({ type: "finish", data: { text: raw, toolCalls: validToolCalls } });
469
505
  };
470
506
 
471
- // src/ai/common/Cactus_JobRunFns.ts
507
+ // src/ai/common/Cactus_JobRunFns.browser.ts
472
508
  var CACTUS_RUN_FNS = [
473
509
  { serves: CACTUS_TOOL_USE, runFn: Cactus_ToolCalling },
474
510
  { serves: CACTUS_MODEL_DOWNLOAD, runFn: Cactus_Download },
@@ -478,150 +514,13 @@ var CACTUS_RUN_FNS = [
478
514
  ];
479
515
  var CACTUS_PREVIEW_TASKS = {};
480
516
 
481
- // src/ai/common/Cactus_Runtime.browser.ts
482
- var _sdk2;
483
- var _sdkInitPromise2;
484
- async function loadSdk2() {
485
- _sdkInitPromise2 ??= import("needle-rs").then(async (mod) => {
486
- const init = mod.default;
487
- if (typeof init === "function") {
488
- await init();
489
- }
490
- _sdk2 = mod;
491
- return mod;
492
- }).catch((err) => {
493
- _sdkInitPromise2 = undefined;
494
- _sdk2 = undefined;
495
- throw new Error(`needle-rs is required for LOCAL_CACTUS tasks. Install it with: bun add needle-rs (cause: ${String(err)})`);
496
- });
497
- return _sdkInitPromise2;
498
- }
499
- function getCactusSdk() {
500
- if (!_sdk2)
501
- throw new Error("Cactus SDK not loaded; call loadSdk() first");
502
- return _sdk2;
503
- }
504
- async function fetchAssetBytesBrowser2(url) {
505
- const cachesApi = globalThis.caches;
506
- const cache = await cachesApi.open(CACTUS_CACHE_NAME);
507
- const hit = await cache.match(url);
508
- if (hit) {
509
- return new Uint8Array(await hit.arrayBuffer());
510
- }
511
- const resp = await fetch(url);
512
- if (!resp.ok)
513
- throw new Error(`Cactus asset fetch failed (${resp.status}) for ${url}`);
514
- await cache.put(url, resp.clone());
515
- return new Uint8Array(await resp.arrayBuffer());
516
- }
517
- async function fetchAssetBytes2(model, filename) {
518
- const model_id = model.provider_config.model_id;
519
- const entry = getCactusCatalogEntry(model_id);
520
- if (!entry)
521
- throw new Error(`Unknown Cactus model_id: ${model_id}`);
522
- const url = cactusAssetUrl(entry, filename);
523
- return fetchAssetBytesBrowser2(url);
524
- }
525
- var cactusEngines2 = new Map;
526
- var cactusConfigJson2 = new Map;
527
- var cactusCachedModelIds2 = new Set;
528
- var cactusEngineLoadsInFlight2 = new Map;
529
- async function getOrLoadEngine2(model) {
530
- const model_id = model.provider_config.model_id;
531
- const cached = cactusEngines2.get(model_id);
532
- if (cached)
533
- return cached;
534
- const inFlight = cactusEngineLoadsInFlight2.get(model_id);
535
- if (inFlight)
536
- return inFlight;
537
- const loadPromise = (async () => {
538
- const sdk = await loadSdk2();
539
- const entry = getCactusCatalogEntry(model_id);
540
- if (!entry)
541
- throw new Error(`Unknown Cactus model_id: ${model_id}`);
542
- const [weightsBytes, vocabBytes, configBytes] = await Promise.all([
543
- fetchAssetBytes2(model, entry.assets.weights),
544
- fetchAssetBytes2(model, entry.assets.vocab),
545
- fetchAssetBytes2(model, entry.assets.config)
546
- ]);
547
- try {
548
- const text = new TextDecoder().decode(configBytes);
549
- cactusConfigJson2.set(model_id, JSON.parse(text));
550
- } catch {
551
- cactusConfigJson2.set(model_id, null);
552
- }
553
- const vocabText = new TextDecoder().decode(vocabBytes);
554
- const engine = sdk.NeedleWasm.load(weightsBytes, vocabText);
555
- if (!engine) {
556
- throw new Error(`needle-rs NeedleWasm.load returned undefined for model ${model_id}`);
557
- }
558
- cactusEngines2.set(model_id, engine);
559
- return engine;
560
- })().finally(() => {
561
- cactusEngineLoadsInFlight2.delete(model_id);
562
- });
563
- cactusEngineLoadsInFlight2.set(model_id, loadPromise);
564
- return loadPromise;
565
- }
566
- function isModelLoaded2(model_id) {
567
- return cactusEngines2.has(model_id);
568
- }
569
- function markModelCached2(model_id) {
570
- cactusCachedModelIds2.add(model_id);
571
- }
572
- function isModelCached2(model_id) {
573
- return cactusEngines2.has(model_id) || cactusCachedModelIds2.has(model_id);
574
- }
575
- var cactusSessions2 = new Map;
576
- async function deleteCactusSession2(id) {
577
- return cactusSessions2.delete(id);
578
- }
579
- async function removeBrowserCacheEntries2(entry) {
580
- const cachesApi = globalThis.caches;
581
- const cache = await cachesApi.open(CACTUS_CACHE_NAME);
582
- for (const filename of [entry.assets.weights, entry.assets.vocab, entry.assets.config]) {
583
- const url = cactusAssetUrl(entry, filename);
584
- try {
585
- await cache.delete(url);
586
- } catch {}
587
- }
588
- }
589
- function disposeCactusEngine2(model_id) {
590
- const engine = cactusEngines2.get(model_id);
591
- if (engine) {
592
- try {
593
- engine.free?.();
594
- } catch {}
595
- }
596
- cactusEngines2.delete(model_id);
597
- cactusConfigJson2.delete(model_id);
598
- cactusCachedModelIds2.delete(model_id);
599
- }
600
- async function removeCachedAssets2(model) {
601
- const model_id = model.provider_config.model_id;
602
- const entry = getCactusCatalogEntry(model_id);
603
- if (!entry)
604
- return;
605
- await removeBrowserCacheEntries2(entry);
606
- disposeCactusEngine2(model_id);
607
- }
608
- async function disposeCactusResources() {
609
- for (const id of Array.from(cactusEngines2.keys())) {
610
- disposeCactusEngine2(id);
611
- }
612
- cactusEngines2.clear();
613
- cactusConfigJson2.clear();
614
- cactusCachedModelIds2.clear();
615
- cactusSessions2.clear();
616
- }
617
-
618
517
  // src/ai.browser.ts
619
518
  var _testOnly = {
620
519
  CactusQueuedProvider,
621
520
  CACTUS_RUN_FN_SPECS,
622
521
  CACTUS_RUN_FNS,
623
- cactusEngines: cactusEngines2,
624
- cactusConfigJson: cactusConfigJson2
522
+ cactusEngines,
523
+ cactusConfigJson
625
524
  };
626
525
  export {
627
526
  registerCactus,
@@ -642,4 +541,4 @@ export {
642
541
  CACTUS_CACHE_NAME
643
542
  };
644
543
 
645
- //# debugId=BDAB0F3966E4588C64756E2164756E21
544
+ //# debugId=1687A0C66520950464756E2164756E21