From bf073c465c9fe21b147e5edd97a5350c60505db4 Mon Sep 17 00:00:00 2001 From: EyJunge1 Date: Sun, 2 Aug 2026 18:43:06 +0200 Subject: [PATCH] fix(embedding): avoid Intel macOS shutdown crash Pin the last Intel-compatible ONNX Runtime version before the teardown regression and exercise natural process shutdown after real inference. Co-authored-by: Cursor --- .github/dependabot.yml | 3 +- .github/workflows/embedding-backend.yml | 7 ++- README.md | 4 +- bun.lock | 60 +++++-------------- package.json | 6 +- scripts/fixtures/compiled-host-entry.mjs | 58 +++++++++++++++--- scripts/verify-embedding-backend.mjs | 4 +- scripts/verify-nested-onnxruntime-fixture.mjs | 28 +++++---- src/services/embedding.ts | 4 +- src/services/onnxruntime-resolve.ts | 57 +++++++++++++++--- tests/onnxruntime-resolve.test.ts | 16 ++++- tests/package-dependencies.test.ts | 8 ++- 12 files changed, 165 insertions(+), 90 deletions(-) diff --git a/.github/dependabot.yml b/.github/dependabot.yml index f095c70..3c0788d 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -18,7 +18,8 @@ updates: - "minor" - "patch" ignore: - # Keep this pin until https://github.com/microsoft/onnxruntime/issues/27961 is resolved. + # Keep this pin until onnxruntime ships a darwin/x64 build after the + # macOS Ort::Env teardown fix (#27961 / #24579) and OpenCode embeds Bun >1.3.14. - dependency-name: "onnxruntime-node" - package-ecosystem: "github-actions" diff --git a/.github/workflows/embedding-backend.yml b/.github/workflows/embedding-backend.yml index fe62f32..3b8a17f 100644 --- a/.github/workflows/embedding-backend.yml +++ b/.github/workflows/embedding-backend.yml @@ -31,7 +31,7 @@ jobs: matrix: # Intel: macos-15-intel / macos-26-intel (darwin/x64). # Apple Silicon: macos-15 / macos-26 (darwin/arm64). - # Intel must keep resolving onnxruntime-node@1.22.0 (#184 / #210). + # Intel must keep resolving onnxruntime-node@1.20.1 (#184 / #210 / #225). os: [ ubuntu-latest, @@ -87,8 +87,9 @@ jobs: - name: Embedding smoke (Node) run: node scripts/verify-embedding-backend.mjs - # Targeted #210 regression: OpenCode-shaped nested install on the oldest + # Targeted #210 / #225 regression: OpenCode-shaped nested install on the oldest # available standard Intel runner, using the reporter's Bun/Node versions. + # Compiled host must run real inference and exit 0 (no Ort::Env SIGILL). nested-intel-regression: name: macos-15-intel / nested OpenCode fixture runs-on: macos-15-intel @@ -114,7 +115,7 @@ jobs: - name: Build package run: bun run build - - name: Nested fixture + compiled host + embedding (Bun 1.3.14) + - name: Nested fixture + compiled host inference/exit (Bun 1.3.14) run: bun scripts/verify-nested-onnxruntime-fixture.mjs - name: Nested fixture + embedding (Node 22) diff --git a/README.md b/README.md index 529fe7f..fec9d81 100644 --- a/README.md +++ b/README.md @@ -230,7 +230,7 @@ Example — remote OpenAI embeddings: Changing `embeddingModel` (or dimensions) can trigger re-embedding of stored memories on next startup. Prefer picking a model once and sticking with it for a given data directory. -**Intel Mac (`darwin/x64`):** newer `onnxruntime-node` builds may ship without an x64 native binding, so local embedding init can fail. `opencode-mem` pins `onnxruntime-node@1.22.0` and loads transformers through a CJS resolve shim so OpenCode nested installs keep that binding. Transformers is resolved to an absolute path before that shim is installed so OpenCode's Bun `--compile` host does not fail with `Cannot find module '@huggingface/transformers' from ''`. If init still fails after a plugin upgrade, clear OpenCode's nested plugin cache (`~/.cache/opencode/packages/opencode-mem@*`) and reinstall, or use a remote endpoint via `embeddingApiUrl` + `embeddingApiKey` (example above). +**Intel Mac (`darwin/x64`):** `onnxruntime-node@1.21.0` through `1.23.2` can crash OpenCode's embedded Bun `1.3.14` during process exit after successful local embeddings (`Ort::Env` teardown / SIGILL). The fix shipped in `1.24.1`, but fixed releases still lack an x64 native binding. `opencode-mem` therefore pins `onnxruntime-node@1.20.1` and loads transformers through a CJS resolve shim so OpenCode nested installs keep that binding. Transformers is resolved to an absolute path before that shim is installed so OpenCode's Bun `--compile` host does not fail with `Cannot find module '@huggingface/transformers' from ''`. After upgrading, clear OpenCode's nested plugin cache (`~/.cache/opencode/packages/opencode-mem@*`) and reinstall, or use a remote endpoint via `embeddingApiUrl` + `embeddingApiKey` (example above). This pin stays until onnxruntime publishes a post-teardown-fix darwin/x64 build. ### Memory Scope @@ -351,7 +351,7 @@ Troubleshooting: - If auto-capture reports that a provider is not connected, confirm the provider name with `opencode providers list` and configure that provider in opencode first. - If a proxy or custom provider returns plain text instead of structured/tool output, choose another model/provider or use one of the manual provider modes above. - For models that reject `temperature`, add `"memoryTemperature": false` when using manual API configuration. -- **Intel Mac (darwin/x64) local embedding:** if embedding init fails, clear `~/.cache/opencode/packages/opencode-mem@*` after upgrading so the nested install picks up the pinned `onnxruntime-node@1.22.0`, or switch to a remote embedding endpoint via `embeddingApiUrl` + `embeddingApiKey`. See [Choosing / configuring embeddings](#choosing-configuring-embeddings). MLX is not supported. +- **Intel Mac (darwin/x64) local embedding:** if embedding init fails or OpenCode exits with SIGILL after local memory use, clear `~/.cache/opencode/packages/opencode-mem@*` after upgrading so the nested install picks up the pinned `onnxruntime-node@1.20.1`, or switch to a remote embedding endpoint via `embeddingApiUrl` + `embeddingApiKey`. See [Choosing / configuring embeddings](#choosing-configuring-embeddings). MLX is not supported. ## Public Subpath Exports diff --git a/bun.lock b/bun.lock index 4b0d597..fab2540 100644 --- a/bun.lock +++ b/bun.lock @@ -12,7 +12,7 @@ "franc-min": "^6.2.0", "hono": "^4.12.32", "iso-639-3": "^3.0.1", - "onnxruntime-node": "1.22.0", + "onnxruntime-node": "1.20.1", "zod": "^4.4.3", }, "devDependencies": { @@ -25,7 +25,7 @@ }, }, "overrides": { - "onnxruntime-node": "1.22.0", + "onnxruntime-node": "1.20.1", }, "packages": { "@ai-sdk/provider": ["@ai-sdk/provider@3.0.8", "", { "dependencies": { "json-schema": "^0.4.0" } }, "sha512-oGMAgGoQdBXbZqNG0Ze56CHjDZ1IDYOwGYxYjO5KLSlz5HiNQ9udIXsPZ61VWaHGZ5XW/jyjmr6t2xz2jGVwbQ=="], @@ -88,6 +88,8 @@ "@img/sharp-win32-x64": ["@img/sharp-win32-x64@0.34.5", "", { "os": "win32", "cpu": "x64" }, "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw=="], + "@isaacs/fs-minipass": ["@isaacs/fs-minipass@4.0.1", "", { "dependencies": { "minipass": "^7.0.4" } }, "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w=="], + "@libsql/client": ["@libsql/client@0.17.4", "", { "dependencies": { "@libsql/core": "^0.17.4", "@libsql/hrana-client": "^0.10.0", "js-base64": "^3.7.5", "libsql": "^0.5.28", "promise-limit": "^2.7.0" } }, "sha512-lYayFWasDV78A+TjlEhr6ubb3odBV6OHjb+wdp8VQcyWWAEIjuwbCHaraEUS4m4yWoo0BvZo96It4VdzZRmRWw=="], "@libsql/core": ["@libsql/core@0.17.4", "", { "dependencies": { "js-base64": "^3.7.5" } }, "sha512-LqF9gIvnJ38nmAH1y/ChizHqDO/MO1wLgA96XrraulEEbqXxLjleSH92YWTolbuJKgPUmGu4aJk9W3UnAcxLOQ=="], @@ -200,34 +202,18 @@ "@typescript/typescript-win32-x64": ["@typescript/typescript-win32-x64@7.0.2", "", { "os": "win32", "cpu": "x64" }, "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g=="], - "adm-zip": ["adm-zip@0.5.17", "", {}, "sha512-+Ut8d9LLqwEvHHJl1+PIHqoyDxFgVN847JTVM3Izi3xHDWPE4UtzzXysMZQs64DMcrJfBeS/uoEP4AD3HQHnQQ=="], - - "boolean": ["boolean@3.2.0", "", {}, "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw=="], - "bun-types": ["bun-types@1.3.14", "", { "dependencies": { "@types/node": "*" } }, "sha512-4N0ig0fEomHt5R0KCFWjovxow98rIoRwKolrYdCcknNwMekCXRnWEUvgu5soYV8QXtVsrUD8B95MBOZGPvr6KQ=="], + "chownr": ["chownr@3.0.0", "", {}, "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g=="], + "collapse-white-space": ["collapse-white-space@2.1.0", "", {}, "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw=="], "cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="], - "define-data-property": ["define-data-property@1.1.4", "", { "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", "gopd": "^1.0.1" } }, "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A=="], - - "define-properties": ["define-properties@1.2.1", "", { "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } }, "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg=="], - "detect-libc": ["detect-libc@2.1.2", "", {}, "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ=="], - "detect-node": ["detect-node@2.1.0", "", {}, "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g=="], - "effect": ["effect@4.0.0-beta.83", "", { "dependencies": { "@standard-schema/spec": "^1.1.0", "fast-check": "^4.8.0", "find-my-way-ts": "^0.1.6", "ini": "^7.0.0", "kubernetes-types": "^1.30.0", "msgpackr": "^2.0.1", "multipasta": "^0.2.7", "toml": "^4.1.1", "uuid": "^14.0.0", "yaml": "^2.9.0" } }, "sha512-0wsak8RtgGAr9UWSbVDgJHZcUqMSvicHcvaZv1MbMM7MCGgW4Rn/137J1MHQbwYPcwYGxT/IqehFd+UbYuj78w=="], - "es-define-property": ["es-define-property@1.0.1", "", {}, "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g=="], - - "es-errors": ["es-errors@1.3.0", "", {}, "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="], - - "es6-error": ["es6-error@4.1.1", "", {}, "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg=="], - - "escape-string-regexp": ["escape-string-regexp@4.0.0", "", {}, "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA=="], - "fast-check": ["fast-check@4.9.0", "", { "dependencies": { "pure-rand": "^8.0.0" } }, "sha512-7ms6T7SybUev/PQITciI0yLM2pOSFy5zpG8Ty7tQofcVaQUvrMXp6CBwqF6fThLCLOrfBtuHAtwq6Yu4XPCllg=="], "find-my-way-ts": ["find-my-way-ts@0.1.6", "", {}, "sha512-a85L9ZoXtNAey3Y6Z+eBWW658kO/MwR7zIafkIUPUMf3isZG0NCs2pjW2wtjxAKuJPxMAsHUIP4ZPGv0o5gyTA=="], @@ -236,16 +222,8 @@ "franc-min": ["franc-min@6.2.0", "", { "dependencies": { "trigram-utils": "^2.0.0" } }, "sha512-1uDIEUSlUZgvJa2AKYR/dmJC66v/PvGQ9mWfI9nOr/kPpMFyvswK0gPXOwpYJYiYD008PpHLkGfG58SPjQJFxw=="], - "global-agent": ["global-agent@3.0.0", "", { "dependencies": { "boolean": "^3.0.1", "es6-error": "^4.1.1", "matcher": "^3.0.0", "roarr": "^2.15.3", "semver": "^7.3.2", "serialize-error": "^7.0.1" } }, "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q=="], - - "globalthis": ["globalthis@1.0.4", "", { "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" } }, "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ=="], - - "gopd": ["gopd@1.2.0", "", {}, "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg=="], - "guid-typescript": ["guid-typescript@1.0.9", "", {}, "sha512-Y8T4vYhEfwJOTbouREvG+3XDsjr8E3kIr7uf+JZ0BYloFsttiHU0WfvANVsR7TxNUJa/WpCnw/Ino/p+DeBhBQ=="], - "has-property-descriptors": ["has-property-descriptors@1.0.2", "", { "dependencies": { "es-define-property": "^1.0.0" } }, "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg=="], - "hono": ["hono@4.12.32", "", {}, "sha512-XcuyW9qE2kJn07PkecMOBd5Vq/hMy7mmGw+idz1yblbg9N17ijJODrvPkn7/dwL3Kulj8LcRJ69DLOWf91dRUg=="], "husky": ["husky@9.1.7", "", { "bin": { "husky": "bin.js" } }, "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA=="], @@ -260,8 +238,6 @@ "json-schema": ["json-schema@0.4.0", "", {}, "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="], - "json-stringify-safe": ["json-stringify-safe@5.0.1", "", {}, "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="], - "kubernetes-types": ["kubernetes-types@1.30.0", "", {}, "sha512-Dew1okvhM/SQcIa2rcgujNndZwU8VnSapDgdxlYoB84ZlpAD43U6KLAFqYo17ykSFGHNPrg0qry0bP+GJd9v7Q=="], "libsql": ["libsql@0.5.29", "", { "dependencies": { "@neon-rs/load": "^0.0.4", "detect-libc": "2.0.2" }, "optionalDependencies": { "@libsql/darwin-arm64": "0.5.29", "@libsql/darwin-x64": "0.5.29", "@libsql/linux-arm-gnueabihf": "0.5.29", "@libsql/linux-arm-musleabihf": "0.5.29", "@libsql/linux-arm64-gnu": "0.5.29", "@libsql/linux-arm64-musl": "0.5.29", "@libsql/linux-x64-gnu": "0.5.29", "@libsql/linux-x64-musl": "0.5.29", "@libsql/win32-x64-msvc": "0.5.29" }, "os": [ "linux", "win32", "darwin", ], "cpu": [ "arm", "x64", "arm64", ] }, "sha512-8lMP8iMgiBzzoNbAPQ59qdVcj6UaE/Vnm+fiwX4doX4Narook0a4GPKWBEv+CR8a1OwbfkgL18uBfBjWdF0Fzg=="], @@ -270,7 +246,9 @@ "long": ["long@5.3.2", "", {}, "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA=="], - "matcher": ["matcher@3.0.0", "", { "dependencies": { "escape-string-regexp": "^4.0.0" } }, "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng=="], + "minipass": ["minipass@7.1.3", "", {}, "sha512-tEBHqDnIoM/1rXME1zgka9g6Q2lcoCkxHLuc7ODJ5BxbP5d4c2Z5cGgtXAku59200Cx7diuHTOYfSBD8n6mm8A=="], + + "minizlib": ["minizlib@3.1.0", "", { "dependencies": { "minipass": "^7.1.2" } }, "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw=="], "msgpackr": ["msgpackr@2.0.4", "", { "optionalDependencies": { "msgpackr-extract": "^3.0.4" } }, "sha512-o1C5KRmuRt+apqMr1HuGSqWStZoRBUpEsCsl15uM9VdAF1qHLtvMOU2En747EnTyEl6c4pzPewRMFF31s1CNbA=="], @@ -282,11 +260,9 @@ "node-gyp-build-optional-packages": ["node-gyp-build-optional-packages@5.2.2", "", { "dependencies": { "detect-libc": "^2.0.1" }, "bin": { "node-gyp-build-optional-packages": "bin.js", "node-gyp-build-optional-packages-optional": "optional.js", "node-gyp-build-optional-packages-test": "build-test.js" } }, "sha512-s+w+rBWnpTMwSFbaE0UXsRlg7hU4FjekKU4eyAih5T8nJuNZT1nNsskXpxmeqSK9UzkBl6UgRlnKc8hz8IEqOw=="], - "object-keys": ["object-keys@1.1.1", "", {}, "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA=="], - - "onnxruntime-common": ["onnxruntime-common@1.22.0", "", {}, "sha512-vcuaNWgtF2dGQu/EP5P8UI5rEPEYqXG2sPPe5j9lg2TY/biJF8eWklTMwlDO08iuXq48xJo0awqIpK5mPG+IxA=="], + "onnxruntime-common": ["onnxruntime-common@1.20.1", "", {}, "sha512-YiU0s0IzYYC+gWvqD1HzLc46Du1sXpSiwzKb63PACIJr6LfL27VsXSXQvt68EzD3V0D5Bc0vyJTjmMxp0ylQiw=="], - "onnxruntime-node": ["onnxruntime-node@1.22.0", "", { "dependencies": { "adm-zip": "^0.5.16", "global-agent": "^3.0.0", "onnxruntime-common": "1.22.0" }, "os": [ "linux", "win32", "darwin", ] }, "sha512-QaAqr7PFekrmEsmu1rpw7OxJYyG+iACjNHoNtQIVt9Oh7st8WDPIIUe6KhF9l35HVJTJd9CV1rePoPmKhSV26g=="], + "onnxruntime-node": ["onnxruntime-node@1.20.1", "", { "dependencies": { "onnxruntime-common": "1.20.1", "tar": "^7.0.1" }, "os": [ "linux", "win32", "darwin", ] }, "sha512-di/I4HDXRw+FLgq+TyHmQEDd3cEp9iFFZm0r4uJ1Wd7b/WE1VXtKWo8yemex347c6GNF/3Pv86ZfPhIWxORr0w=="], "onnxruntime-web": ["onnxruntime-web@1.26.0-dev.20260416-b7804b056c", "", { "dependencies": { "flatbuffers": "^25.1.24", "guid-typescript": "^1.0.9", "long": "^5.2.3", "onnxruntime-common": "1.24.0-dev.20251116-b39e144322", "platform": "^1.3.6", "protobufjs": "^7.2.4" } }, "sha512-MD6Ss4GSpQBo6zqoJzyT9LRbKYs7x/JVN23FT24EcEvlqF4VuzPOeH6X38orZPKHQDbprn7K+SBpu0/mj2CQiw=="], @@ -304,24 +280,18 @@ "pure-rand": ["pure-rand@8.4.2", "", {}, "sha512-vvuOGgcuPJAirlHvuQw1TrOiw7ptaIXXmIbNuiNOY6lNGJJH49PQ1Kj4nd783nPdQhQdicgOjVI2yI/9BD6/Ng=="], - "roarr": ["roarr@2.15.4", "", { "dependencies": { "boolean": "^3.0.1", "detect-node": "^2.0.4", "globalthis": "^1.0.1", "json-stringify-safe": "^5.0.1", "semver-compare": "^1.0.0", "sprintf-js": "^1.1.2" } }, "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A=="], - "semver": ["semver@7.7.3", "", { "bin": { "semver": "bin/semver.js" } }, "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q=="], - "semver-compare": ["semver-compare@1.0.0", "", {}, "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow=="], - - "serialize-error": ["serialize-error@7.0.1", "", { "dependencies": { "type-fest": "^0.13.1" } }, "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw=="], - "sharp": ["sharp@0.34.5", "", { "dependencies": { "@img/colour": "^1.0.0", "detect-libc": "^2.1.2", "semver": "^7.7.3" }, "optionalDependencies": { "@img/sharp-darwin-arm64": "0.34.5", "@img/sharp-darwin-x64": "0.34.5", "@img/sharp-libvips-darwin-arm64": "1.2.4", "@img/sharp-libvips-darwin-x64": "1.2.4", "@img/sharp-libvips-linux-arm": "1.2.4", "@img/sharp-libvips-linux-arm64": "1.2.4", "@img/sharp-libvips-linux-ppc64": "1.2.4", "@img/sharp-libvips-linux-riscv64": "1.2.4", "@img/sharp-libvips-linux-s390x": "1.2.4", "@img/sharp-libvips-linux-x64": "1.2.4", "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", "@img/sharp-libvips-linuxmusl-x64": "1.2.4", "@img/sharp-linux-arm": "0.34.5", "@img/sharp-linux-arm64": "0.34.5", "@img/sharp-linux-ppc64": "0.34.5", "@img/sharp-linux-riscv64": "0.34.5", "@img/sharp-linux-s390x": "0.34.5", "@img/sharp-linux-x64": "0.34.5", "@img/sharp-linuxmusl-arm64": "0.34.5", "@img/sharp-linuxmusl-x64": "0.34.5", "@img/sharp-wasm32": "0.34.5", "@img/sharp-win32-arm64": "0.34.5", "@img/sharp-win32-ia32": "0.34.5", "@img/sharp-win32-x64": "0.34.5" } }, "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg=="], "shebang-command": ["shebang-command@2.0.0", "", { "dependencies": { "shebang-regex": "^3.0.0" } }, "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA=="], "shebang-regex": ["shebang-regex@3.0.0", "", {}, "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A=="], - "sprintf-js": ["sprintf-js@1.1.3", "", {}, "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA=="], - "string-argv": ["string-argv@0.3.2", "", {}, "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q=="], + "tar": ["tar@7.5.22", "", { "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", "minipass": "^7.1.2", "minizlib": "^3.1.0", "yallist": "^5.0.0" } }, "sha512-MFO/QzvtAOmJbkhOaCTvbGcFN9L9b+JunIsDwaKljSOdcLMea3NJ1k9Usz/rjdfSXTq4dfzfeS7W4p4YOAAHeA=="], + "tinyexec": ["tinyexec@1.2.4", "", {}, "sha512-SHf/r48b7vOrjve9PxJo3MN5v5yuyjHvdUcrQffT3WXMUfnGmHDVbC4k3sHJaJTgZCwpUplIaAo5ANtMyp3YHg=="], "toml": ["toml@4.3.0", "", {}, "sha512-lVb8X9BsPVuH0M4BKeS91tXAmJvCjQ5UIyAbQFaxkKGyUFK2RPkhwaFSQH8vbpl1d23eu/IBH+dwVMHWaq9A5A=="], @@ -330,8 +300,6 @@ "tslib": ["tslib@2.8.1", "", {}, "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w=="], - "type-fest": ["type-fest@0.13.1", "", {}, "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg=="], - "typescript": ["typescript@7.0.2", "", { "optionalDependencies": { "@typescript/typescript-aix-ppc64": "7.0.2", "@typescript/typescript-darwin-arm64": "7.0.2", "@typescript/typescript-darwin-x64": "7.0.2", "@typescript/typescript-freebsd-arm64": "7.0.2", "@typescript/typescript-freebsd-x64": "7.0.2", "@typescript/typescript-linux-arm": "7.0.2", "@typescript/typescript-linux-arm64": "7.0.2", "@typescript/typescript-linux-loong64": "7.0.2", "@typescript/typescript-linux-mips64el": "7.0.2", "@typescript/typescript-linux-ppc64": "7.0.2", "@typescript/typescript-linux-riscv64": "7.0.2", "@typescript/typescript-linux-s390x": "7.0.2", "@typescript/typescript-linux-x64": "7.0.2", "@typescript/typescript-netbsd-arm64": "7.0.2", "@typescript/typescript-netbsd-x64": "7.0.2", "@typescript/typescript-openbsd-arm64": "7.0.2", "@typescript/typescript-openbsd-x64": "7.0.2", "@typescript/typescript-sunos-x64": "7.0.2", "@typescript/typescript-win32-arm64": "7.0.2", "@typescript/typescript-win32-x64": "7.0.2" }, "bin": { "tsc": "bin/tsc" } }, "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA=="], "undici-types": ["undici-types@7.16.0", "", {}, "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw=="], @@ -342,6 +310,8 @@ "ws": ["ws@8.21.1", "", { "peerDependencies": { "bufferutil": "^4.0.1", "utf-8-validate": ">=5.0.2" }, "optionalPeers": ["bufferutil", "utf-8-validate"] }, "sha512-+0NTnW77fFN/DjQi6k/Sq/Yvk4Sgajw7urW8V+asjXnRgDs9gyGkdb7EzgfhA4goXsRIZKE28fzIXBHEzhuiWw=="], + "yallist": ["yallist@5.0.0", "", {}, "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw=="], + "yaml": ["yaml@2.9.0", "", { "bin": { "yaml": "bin.mjs" } }, "sha512-2AvhNX3mb8zd6Zy7INTtSpl1F15HW6Wnqj0srWlkKLcpYl/gMIMJiyuGq2KeI2YFxUPjdlB+3Lc10seMLtL4cA=="], "zod": ["zod@4.4.3", "", {}, "sha512-ytENFjIJFl2UwYglde2jchW2Hwm4GJFLDiSXWdTrJQBIN9Fcyp7n4DhxJEiWNAJMV1/BqWfW/kkg71UDcHJyTQ=="], diff --git a/package.json b/package.json index 66a7948..f244da1 100644 --- a/package.json +++ b/package.json @@ -57,12 +57,12 @@ "franc-min": "^6.2.0", "hono": "^4.12.32", "iso-639-3": "^3.0.1", - "onnxruntime-node": "1.22.0", + "onnxruntime-node": "1.20.1", "zod": "^4.4.3" }, - "//": "Pin onnxruntime-node@1.22.0 (direct + override) until https://github.com/microsoft/onnxruntime/issues/27961 is resolved. Direct dep is required because OpenCode installs plugins nested and npm ignores nested package overrides (#184).", + "//": "Pin onnxruntime-node@1.20.1 (direct + override): nested OpenCode installs ignore package overrides (#184); 1.21.0–1.23.2 can SIGILL on macOS process exit (#225); fixed releases still lack darwin/x64 (microsoft/onnxruntime#27961).", "overrides": { - "onnxruntime-node": "1.22.0" + "onnxruntime-node": "1.20.1" }, "devDependencies": { "@types/bun": "^1.3.14", diff --git a/scripts/fixtures/compiled-host-entry.mjs b/scripts/fixtures/compiled-host-entry.mjs index f8d486f..db28313 100644 --- a/scripts/fixtures/compiled-host-entry.mjs +++ b/scripts/fixtures/compiled-host-entry.mjs @@ -1,13 +1,21 @@ #!/usr/bin/env bun /** - * Minimal OpenCode-shaped Bun host entry for #210. + * Minimal OpenCode-shaped Bun host entry for #210 / #225. * * OpenCode is shipped via Bun.build({ compile: { autoloadPackageJson: true, ... }}) - * and dynamically imports external plugins. This entry mimics that load path. + * and dynamically imports external plugins. This entry mimics that load path, + * runs a real local embedding, and exits normally so Bun 1.3.14 + onnxruntime + * teardown regressions (#225) are caught by the parent fixture. * * Env: * OPENCODE_MEM_PLUGIN_ENTRY — absolute file URL or path to embedding.js + * OPENCODE_MEM_EMBEDDING_MODEL — optional feature-extraction model id + * OPENCODE_MEM_EMBEDDING_DIMS — expected trailing embedding dimension */ +const PINNED = "1.20.1"; +const MODEL = process.env.OPENCODE_MEM_EMBEDDING_MODEL || "Xenova/all-MiniLM-L6-v2"; +const EXPECTED_DIMS = Number(process.env.OPENCODE_MEM_EMBEDDING_DIMS || "384"); + const entry = process.env.OPENCODE_MEM_PLUGIN_ENTRY; if (!entry) { console.error("OPENCODE_MEM_PLUGIN_ENTRY is required"); @@ -34,8 +42,9 @@ const { fileURLToPath, pathToFileURL } = await import("node:url"); const entryPath = entry.startsWith("file:") ? fileURLToPath(entry) : entry; const pluginRequire = createRequire(entryPath); const resolveUrl = pathToFileURL(join(dirname(entryPath), "onnxruntime-resolve.js")).href; -const { getPinnedOnnxruntimePackageRoot, prepareOnnxruntimeForTransformers } = - await import(resolveUrl); +const { getPinnedOnnxruntimePackageRoot, prepareOnnxruntimeForTransformers } = await import( + resolveUrl +); prepareOnnxruntimeForTransformers(); function pkgVersion(entryFile) { @@ -59,12 +68,38 @@ const nodeVersion = pkgVersion(nodeEntry); const commonVersion = pkgVersion(commonEntry); const pinnedRoot = getPinnedOnnxruntimePackageRoot(); -if (nodeVersion !== "1.22.0") { - console.error(`expected onnxruntime-node@1.22.0, got ${nodeVersion} at ${nodeEntry}`); +if (nodeVersion !== PINNED) { + console.error(`expected onnxruntime-node@${PINNED}, got ${nodeVersion} at ${nodeEntry}`); + process.exit(1); +} +if (commonVersion !== PINNED) { + console.error(`expected onnxruntime-common@${PINNED}, got ${commonVersion} at ${commonEntry}`); + process.exit(1); +} + +transformers.env.allowLocalModels = true; +transformers.env.allowRemoteModels = true; +try { + transformers.env.backends.onnx.wasm.numThreads = 1; +} catch { + /* wasm backend optional */ +} + +const extractor = await transformers.pipeline("feature-extraction", MODEL); +const out = await extractor("compiled-host onnx shutdown regression", { + pooling: "mean", + normalize: true, +}); +const dims = out.dims?.[out.dims.length - 1]; +if (dims !== EXPECTED_DIMS) { + console.error(`expected ${EXPECTED_DIMS} dims, got ${dims}`); process.exit(1); } -if (commonVersion !== "1.22.0") { - console.error(`expected onnxruntime-common@1.22.0, got ${commonVersion} at ${commonEntry}`); +const vec = Array.from(out.data); +const allFinite = vec.every((x) => Number.isFinite(x)); +const norm = Math.sqrt(vec.reduce((s, x) => s + x * x, 0)); +if (!allFinite || !(norm > 0.9 && norm < 1.1)) { + console.error(`bad embedding vector (finite=${allFinite}, norm=${norm})`); process.exit(1); } @@ -76,5 +111,12 @@ console.log( nodeVersion, commonVersion, pinnedRoot, + model: MODEL, + embeddingDims: dims, + embeddingNorm: Number(norm.toFixed(4)), }) ); + +// Let the process exit naturally. Bun 1.3.14 + onnxruntime-node@1.21.0–1.23.2 +// crashed during Ort::Env teardown after successful inference (#225). Exit code +// 0 is asserted by the parent fixture via spawnSync status/signal. diff --git a/scripts/verify-embedding-backend.mjs b/scripts/verify-embedding-backend.mjs index 28ebcfb..b16e293 100644 --- a/scripts/verify-embedding-backend.mjs +++ b/scripts/verify-embedding-backend.mjs @@ -5,7 +5,7 @@ * crashing on the host platform. * * Mirrors the production loader: prefer the CJS export so OpenCode nested - * installs can pin onnxruntime-node@1.22.0 via Module._resolveFilename (#210). + * installs can pin onnxruntime-node@1.20.1 via Module._resolveFilename (#210 / #225). * This script deliberately does not import prepareOnnxruntimeForTransformers() * because the embedding-backend workflow runs without a TypeScript build. * @@ -22,7 +22,7 @@ import { existsSync, readFileSync } from "node:fs"; const MODEL = "Xenova/all-MiniLM-L6-v2"; const EXPECTED_DIMS = 384; -const PINNED_ONNX_VERSION = "1.22.0"; +const PINNED_ONNX_VERSION = "1.20.1"; const runtime = typeof globalThis.Bun !== "undefined" ? "bun" : "node"; console.log( diff --git a/scripts/verify-nested-onnxruntime-fixture.mjs b/scripts/verify-nested-onnxruntime-fixture.mjs index 5437fad..3f2bd64 100644 --- a/scripts/verify-nested-onnxruntime-fixture.mjs +++ b/scripts/verify-nested-onnxruntime-fixture.mjs @@ -4,7 +4,7 @@ * * Installs the packed plugin into a temporary consumer without root overrides, * so @huggingface/transformers may keep nested onnxruntime-node@1.24.3. - * Then verifies the production CJS prepare+load path pins the direct 1.22.0 stack. + * Then verifies the production CJS prepare+load path pins the direct 1.20.1 stack. * * Unlike earlier revisions, Transformers is loaded through the production * `loadLocalTransformersBackend()` export (createRuntimeRequire + shim), not via @@ -16,7 +16,7 @@ * * npm may hoist dependencies to the consumer root (fixture/node_modules/...) while * OpenCode keeps them under the plugin package. Both layouts are accepted as long as - * transformers can resolve a nested 1.24.x copy and the production shim pins 1.22.0. + * transformers can resolve a nested 1.24.x copy and the production shim pins 1.20.1. * * Usage (from a built repo checkout): * node scripts/verify-nested-onnxruntime-fixture.mjs @@ -37,7 +37,7 @@ import { tmpdir } from "node:os"; import { dirname, join, resolve } from "node:path"; import { fileURLToPath, pathToFileURL } from "node:url"; -const PINNED = "1.22.0"; +const PINNED = "1.20.1"; const NESTED_BAD = "1.24.3"; const runtime = typeof globalThis.Bun !== "undefined" ? "bun" : "node"; const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), ".."); @@ -59,8 +59,9 @@ function run(cmd, args, cwd, env = process.env) { env, }); if (result.status !== 0) { + const signal = result.signal ? ` (signal ${result.signal})` : ""; fail( - `${cmd} ${args.join(" ")} exited ${result.status}\nstdout:\n${result.stdout}\nstderr:\n${result.stderr}` + `${cmd} ${args.join(" ")} exited ${result.status}${signal}\nstdout:\n${result.stdout}\nstderr:\n${result.stderr}` ); } return result.stdout; @@ -178,7 +179,16 @@ await Bun.build({ if (parsed.commonVersion !== PINNED) { fail(`compiled host onnxruntime-common=${parsed.commonVersion}, expected ${PINNED}`); } - log(`compiled host PASS — pinned node=${parsed.nodeEntry}`); + if (parsed.embeddingDims !== 384) { + fail(`compiled host embeddingDims=${parsed.embeddingDims}, expected 384`); + } + if (!(parsed.embeddingNorm > 0.9 && parsed.embeddingNorm < 1.1)) { + fail(`compiled host embeddingNorm=${parsed.embeddingNorm}, expected ~1.0`); + } + // `run()` already asserted exit status 0 / no crash signal after inference. + log( + `compiled host PASS — pinned node=${parsed.nodeEntry}; embedding dims=${parsed.embeddingDims} L2=${parsed.embeddingNorm}` + ); rmSync(hostDir, { recursive: true, force: true }); } @@ -265,7 +275,7 @@ async function main() { const resolvedPkg = readPkgNear(nestedResolved).pkg; if (resolvedPkg.version === PINNED) { fail( - "expected transformers-local resolve to prefer nested 1.24.x before shim, but got pinned 1.22.0" + "expected transformers-local resolve to prefer nested 1.24.x before shim, but got pinned 1.20.1" ); } log(`pre-shim transformers resolve -> ${nestedResolved} (@${resolvedPkg.version})`); @@ -293,9 +303,7 @@ async function main() { fail(`after prepare, onnxruntime-node resolved to ${nodePkg.version} at ${pinnedNode}`); } if (commonPkg.version !== PINNED) { - fail( - `after prepare, onnxruntime-common resolved to ${commonPkg.version} at ${pinnedCommon}` - ); + fail(`after prepare, onnxruntime-common resolved to ${commonPkg.version} at ${pinnedCommon}`); } const resolveUrl = pathToFileURL( @@ -355,7 +363,7 @@ async function main() { await verifyCompiledHost(pluginRoot); - log("PASS — nested fixture loads production CJS path on onnxruntime 1.22.0 stack"); + log("PASS — nested fixture loads production CJS path on onnxruntime 1.20.1 stack"); if (cleanup && process.env.KEEP_FIXTURE !== "1") cleanup(); } diff --git a/src/services/embedding.ts b/src/services/embedding.ts index cc142bb..8ebf226 100644 --- a/src/services/embedding.ts +++ b/src/services/embedding.ts @@ -55,8 +55,8 @@ function getTransformersPackageSpecifier(): string { async function ensureTransformersLoaded(): Promise> { if (_transformers !== null) return _transformers; - // Pin onnxruntime-node (+ common) to our direct 1.22.0 stack before transformers - // resolves them (#184 / #210). Load the CJS export so Module._resolveFilename + // Pin onnxruntime-node (+ common) to our direct 1.20.1 stack before transformers + // resolves them (#184 / #210 / #225). Load the CJS export so Module._resolveFilename // shim applies — the ESM entry's static import bypasses it under OpenCode nested installs. // // Critical ordering for OpenCode's Bun --compile host (#210 follow-up): diff --git a/src/services/onnxruntime-resolve.ts b/src/services/onnxruntime-resolve.ts index 78459b4..58d1f10 100644 --- a/src/services/onnxruntime-resolve.ts +++ b/src/services/onnxruntime-resolve.ts @@ -6,16 +6,23 @@ * `overrides` at the install root, so `@huggingface/transformers` would otherwise * keep nested `onnxruntime-node@1.24.3` (no darwin/x64 binding). See #184 / #158 / #210. * + * We pin onnxruntime-node@1.20.1: + * - 1.21.0–1.23.2 crash during macOS Ort::Env process-exit teardown (#225 / + * microsoft/onnxruntime#24579); the fix shipped in 1.24.1 + * - fixed releases still lack darwin/x64 binaries (microsoft/onnxruntime#27961) + * - OpenCode's embedded Bun 1.3.14 surfaces the teardown failure as SIGILL + * * Transformers must be loaded via its CJS export so this Module._resolveFilename * shim applies; the ESM entry's static `import "onnxruntime-node"` bypasses it. */ import { createRequire } from "node:module"; -import { existsSync } from "node:fs"; +import { existsSync, readdirSync } from "node:fs"; import { dirname, join } from "node:path"; import { createRuntimeRequire } from "./runtime-require.js"; const PACKAGE_NAME = "onnxruntime-node"; const COMMON_PACKAGE = "onnxruntime-common"; +const PINNED_VERSION_HINT = "1.20.1"; const requireFromHere = createRuntimeRequire(import.meta); let shimInstalled = false; @@ -31,7 +38,7 @@ function getPinnedOnnxruntimeEntry(): string { function getPinnedOnnxruntimeCommonEntry(): string { if (pinnedCommonEntry) return pinnedCommonEntry; - // Resolve common from the pinned node package so we always get the 1.22.0 stack, + // Resolve common from the pinned node package so we always get the pinned stack, // whether the package manager hoists it or nests it under onnxruntime-node. pinnedCommonEntry = createRequire(getPinnedOnnxruntimeEntry()).resolve(COMMON_PACKAGE); return pinnedCommonEntry; @@ -53,6 +60,38 @@ export function getPinnedOnnxruntimePackageRoot(): string { return pinnedPackageRoot; } +/** + * Resolve the N-API layout directory shipped by the pinned onnxruntime-node + * package (`napi-v3` for 1.20.x, `napi-v6` for 1.22.x, …). + */ +export function getOnnxruntimeNapiDirName( + platform: NodeJS.Platform = process.platform, + arch: string = process.arch +): string { + const binDir = join(getPinnedOnnxruntimePackageRoot(), "bin"); + if (!existsSync(binDir)) return "napi-v3"; + + let entries: string[] = []; + try { + entries = readdirSync(binDir, { withFileTypes: true }) + .filter((entry) => entry.isDirectory() && /^napi-v\d+$/.test(entry.name)) + .map((entry) => entry.name) + .sort((a, b) => Number(a.slice("napi-v".length)) - Number(b.slice("napi-v".length))); + } catch { + return "napi-v3"; + } + + // Prefer a layout that actually contains the platform binding. + for (let i = entries.length - 1; i >= 0; i--) { + const name = entries[i]!; + if (existsSync(join(binDir, name, platform, arch, "onnxruntime_binding.node"))) { + return name; + } + } + + return entries.at(-1) ?? "napi-v3"; +} + export function getOnnxruntimeBindingPath( platform: NodeJS.Platform = process.platform, arch: string = process.arch @@ -60,7 +99,7 @@ export function getOnnxruntimeBindingPath( return join( getPinnedOnnxruntimePackageRoot(), "bin", - "napi-v6", + getOnnxruntimeNapiDirName(platform, arch), platform, arch, "onnxruntime_binding.node" @@ -74,8 +113,8 @@ export function formatMissingOnnxruntimeBindingError( const bindingPath = getOnnxruntimeBindingPath(platform, arch); const intelHint = platform === "darwin" && arch === "x64" - ? " On Intel Mac (darwin/x64), onnxruntime-node@1.24+ ships without an x64 binding; opencode-mem pins 1.22.0. If this persists after updating, clear OpenCode's plugin cache (~/.cache/opencode/packages/opencode-mem@*) and reinstall, or configure remote embeddings via embeddingApiUrl + embeddingApiKey." - : " Configure remote embeddings via embeddingApiUrl + embeddingApiKey, or reinstall the plugin so onnxruntime-node@1.22.0 is used."; + ? ` On Intel Mac (darwin/x64), onnxruntime-node@1.21.0–1.23.2 can crash Bun 1.3.14 on process exit (#225), while fixed releases still lack an x64 binding; opencode-mem pins ${PINNED_VERSION_HINT}. If this persists after updating, clear OpenCode's plugin cache (~/.cache/opencode/packages/opencode-mem@*) and reinstall, or configure remote embeddings via embeddingApiUrl + embeddingApiKey.` + : ` Configure remote embeddings via embeddingApiUrl + embeddingApiKey, or reinstall the plugin so onnxruntime-node@${PINNED_VERSION_HINT} is used.`; return `Local embedding native binding missing for ${platform}/${arch} at ${bindingPath}.${intelHint}`; } @@ -84,7 +123,7 @@ export function formatMissingOnnxruntimeBindingError( * * When the pinned binding is absent, keep the clear "missing" message. * When it is present, preserve the original error so nested-1.24 / dlopen / - * codesign failures are not misreported as a missing 1.22.0 file (#210). + * codesign failures are not misreported as a missing pinned binding (#210). */ export function formatOnnxruntimeInitError( error: unknown, @@ -96,7 +135,7 @@ export function formatOnnxruntimeInitError( message.includes("onnxruntime_binding.node") || message.includes("onnxruntime-node") || message.includes("onnxruntime-common") || - /napi-v6\/[^/]+\/[^/]+/.test(message); + /napi-v\d+\/[^/]+\/[^/]+/.test(message); if (!isOnnxRelated) { return error instanceof Error ? error : new Error(message); @@ -109,7 +148,7 @@ export function formatOnnxruntimeInitError( const intelHint = platform === "darwin" && arch === "x64" - ? " On Intel Mac nested installs, @huggingface/transformers may resolve onnxruntime-node@1.24+ (no x64 binding); opencode-mem pins 1.22.0 via a CJS resolve shim." + ? ` On Intel Mac nested installs, @huggingface/transformers may resolve onnxruntime-node@1.24+ (no x64 binding); opencode-mem pins ${PINNED_VERSION_HINT} via a CJS resolve shim.` : ""; return new Error( @@ -149,7 +188,7 @@ function resolvePinnedRequest( /** * Patch Module._resolveFilename so require() of onnxruntime-node / onnxruntime-common - * from nested transformers resolves to our direct 1.22.0 dependency stack. + * from nested transformers resolves to our direct pinned dependency stack. */ export function installOnnxruntimeResolveShim(): void { if (shimInstalled) return; diff --git a/tests/onnxruntime-resolve.test.ts b/tests/onnxruntime-resolve.test.ts index b4e3fc5..8f4315d 100644 --- a/tests/onnxruntime-resolve.test.ts +++ b/tests/onnxruntime-resolve.test.ts @@ -18,6 +18,7 @@ import { formatMissingOnnxruntimeBindingError, formatOnnxruntimeInitError, getOnnxruntimeBindingPath, + getOnnxruntimeNapiDirName, getPinnedOnnxruntimePackageRoot, installOnnxruntimeResolveShim, prepareOnnxruntimeForTransformers, @@ -95,12 +96,23 @@ describe("onnxruntime resolve shim (#184 / #210)", () => { expect(message).toContain("darwin/x64"); expect(message).toContain("embeddingApiUrl"); expect(message).toContain("embeddingApiKey"); - expect(message).toContain("1.22.0"); + expect(message).toContain("1.20.1"); + expect(message).toContain("#225"); + }); + + it("discovers the napi layout shipped by the pinned onnxruntime-node package", () => { + const napiDir = getOnnxruntimeNapiDirName(); + expect(napiDir).toMatch(/^napi-v\d+$/); + const bindingPath = getOnnxruntimeBindingPath(); + expect(bindingPath.split(/[/\\]/)).toContain(napiDir); + if (existsSync(bindingPath)) { + expect(bindingPath.endsWith("onnxruntime_binding.node")).toBe(true); + } }); it("init error reports missing binding only when the pinned file is absent", () => { const rewritten = formatOnnxruntimeInitError( - new Error("Cannot find module '.../napi-v6/darwin/nope/onnxruntime_binding.node'"), + new Error("Cannot find module '.../napi-v3/darwin/nope/onnxruntime_binding.node'"), "darwin", "nope" ); diff --git a/tests/package-dependencies.test.ts b/tests/package-dependencies.test.ts index 086b6da..723c693 100644 --- a/tests/package-dependencies.test.ts +++ b/tests/package-dependencies.test.ts @@ -12,12 +12,14 @@ describe("published dependency constraints", () => { expect(pkg.dependencies).not.toHaveProperty("@xenova/transformers"); }); - it("pins onnxruntime-node@1.22.0 as a direct dependency (OpenCode nested install ignores overrides)", () => { + it("pins onnxruntime-node@1.20.1 as a direct dependency (Intel binding + Bun teardown)", () => { // Nested package.json overrides are ignored by npm/Arborist (#184). A direct // dependency is required so Intel Mac (darwin/x64) gets a shipping binding. - expect(pkg.dependencies["onnxruntime-node"]).toBe("1.22.0"); + // Stay on 1.20.1 until onnxruntime publishes a post-teardown-fix x64 build + // (#225 / microsoft/onnxruntime#24579 / #27961) and OpenCode embeds Bun >1.3.14. + expect(pkg.dependencies["onnxruntime-node"]).toBe("1.20.1"); expect((pkg as { overrides?: Record }).overrides?.["onnxruntime-node"]).toBe( - "1.22.0" + "1.20.1" ); }); });