@oh-my-pi/pi-mnemopi 16.0.5 → 16.0.6

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.
package/CHANGELOG.md CHANGED
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [16.0.6] - 2026-06-18
6
+
7
+ ### Fixed
8
+
9
+ - Forced the on-demand fastembed runtime install to override fastembed's archived `onnxruntime-node@1.21.0` transitive pin with Mnemopi's `onnxruntime-node@1.26.0` pin, fixing local embedding startup on macOS ARM64. ([#2920](https://github.com/can1357/oh-my-pi/issues/2920))
10
+
11
+ ### Changed
12
+
13
+ - Updated OpenRouter request headers to use standard shared headers from the pi-ai package
14
+
5
15
  ## [16.0.5] - 2026-06-17
6
16
 
7
17
  ### Fixed
@@ -1,4 +1,14 @@
1
+ import { type RuntimeInstallSpec } from "@oh-my-pi/pi-utils";
1
2
  import type * as Fastembed from "fastembed";
2
3
  type FastembedModule = typeof Fastembed;
4
+ /** Runtime install inputs for the optional fastembed embedding stack. */
5
+ export interface FastembedRuntimeInstallPlan {
6
+ /** Cache directory key; changes when runtime resolution policy changes. */
7
+ versionKey: string;
8
+ /** Dependency graph written to the runtime cache package manifest. */
9
+ install: RuntimeInstallSpec;
10
+ }
11
+ /** Build the deterministic fastembed runtime install plan used by local embeddings. */
12
+ export declare function fastembedRuntimeInstallPlan(): FastembedRuntimeInstallPlan;
3
13
  export declare function loadFastembed(): Promise<FastembedModule>;
4
14
  export {};
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@oh-my-pi/pi-mnemopi",
4
- "version": "16.0.5",
4
+ "version": "16.0.6",
5
5
  "description": "Local SQLite memory engine for Oh My Pi agents",
6
6
  "homepage": "https://omp.sh",
7
7
  "author": "Can Boluk",
@@ -39,9 +39,9 @@
39
39
  "fmt": "biome format --write ."
40
40
  },
41
41
  "dependencies": {
42
- "@oh-my-pi/pi-ai": "16.0.5",
43
- "@oh-my-pi/pi-catalog": "16.0.5",
44
- "@oh-my-pi/pi-utils": "16.0.5",
42
+ "@oh-my-pi/pi-ai": "16.0.6",
43
+ "@oh-my-pi/pi-catalog": "16.0.6",
44
+ "@oh-my-pi/pi-utils": "16.0.6",
45
45
  "lru-cache": "11.5.1"
46
46
  },
47
47
  "peerDependencies": {
@@ -1,5 +1,5 @@
1
1
  import { mkdirSync } from "node:fs";
2
- import { type ApiKey, ProviderHttpError, withAuth } from "@oh-my-pi/pi-ai";
2
+ import { type ApiKey, getOpenRouterHeaders, ProviderHttpError, withAuth } from "@oh-my-pi/pi-ai";
3
3
  import { hostMatchesUrl } from "@oh-my-pi/pi-catalog/hosts";
4
4
  import {
5
5
  $env,
@@ -11,7 +11,6 @@ import {
11
11
  } from "@oh-my-pi/pi-utils";
12
12
  import type { EmbeddingModel } from "fastembed";
13
13
  import { LRUCache } from "lru-cache/raw";
14
- import packageJson from "../../package.json" with { type: "json" };
15
14
  import { loadFastembed } from "./fastembed-runtime";
16
15
  import {
17
16
  type EmbeddingOutput,
@@ -268,10 +267,7 @@ async function embedApi(texts: readonly string[]): Promise<EmbeddingMatrix | nul
268
267
  const response = await withAuth(apiKey, async key => {
269
268
  const headers: Record<string, string> = {
270
269
  "Content-Type": "application/json",
271
- "User-Agent": `Oh-My-Pi/${packageJson.version}`,
272
- "HTTP-Referer": "https://omp.sh/",
273
- "X-OpenRouter-Title": "Oh-My-Pi",
274
- "X-OpenRouter-Categories": "cli-agent",
270
+ ...getOpenRouterHeaders(),
275
271
  };
276
272
  if (key !== "") {
277
273
  headers.Authorization = `Bearer ${key}`;
@@ -5,6 +5,7 @@ import {
5
5
  getFastembedRuntimeDir,
6
6
  installRuntimeModuleResolver,
7
7
  logger,
8
+ type RuntimeInstallSpec,
8
9
  resolveRuntimeModule,
9
10
  } from "@oh-my-pi/pi-utils";
10
11
  import type * as Fastembed from "fastembed";
@@ -12,13 +13,21 @@ import packageManifest from "../../package.json" with { type: "json" };
12
13
 
13
14
  type FastembedModule = typeof Fastembed;
14
15
 
16
+ /** Runtime install inputs for the optional fastembed embedding stack. */
17
+ export interface FastembedRuntimeInstallPlan {
18
+ /** Cache directory key; changes when runtime resolution policy changes. */
19
+ versionKey: string;
20
+ /** Dependency graph written to the runtime cache package manifest. */
21
+ install: RuntimeInstallSpec;
22
+ }
23
+
15
24
  /**
16
25
  * `fastembed` and `onnxruntime-node` are optional peers (~270MB of native
17
26
  * assets across platforms), never bundled and never installed eagerly. When
18
27
  * the direct import cannot resolve — bundled `dist/cli.js`, compiled binary,
19
- * or a consumer that skipped the optional peers the pinned pair is
20
- * `bun install`ed into a per-version runtime cache on first use and loaded
21
- * from there (#2389).
28
+ * a consumer that skipped the optional peers, or a native loader failure from
29
+ * fastembed's nested ORT the pinned pair is `bun install`ed into a
30
+ * per-version runtime cache on first use and loaded from there (#2389, #2920).
22
31
  *
23
32
  * The pins live in `peerDependencies` as exact versions (not `catalog:`) so
24
33
  * this module reads concrete specs even when the workspace manifest is
@@ -27,6 +36,16 @@ type FastembedModule = typeof Fastembed;
27
36
  const FASTEMBED_SPEC = packageManifest.peerDependencies.fastembed;
28
37
  const ORT_SPEC = packageManifest.peerDependencies["onnxruntime-node"];
29
38
 
39
+ /** Build the deterministic fastembed runtime install plan used by local embeddings. */
40
+ export function fastembedRuntimeInstallPlan(): FastembedRuntimeInstallPlan {
41
+ return {
42
+ versionKey: `fastembed-${FASTEMBED_SPEC}_ort-${ORT_SPEC}_forced-ort`.replace(/[^A-Za-z0-9._-]/g, "_"),
43
+ install: {
44
+ dependencies: { fastembed: FASTEMBED_SPEC, "onnxruntime-node": ORT_SPEC },
45
+ overrides: { "onnxruntime-common": ORT_SPEC, "onnxruntime-node": ORT_SPEC },
46
+ },
47
+ };
48
+ }
30
49
  let fastembedLoad: Promise<FastembedModule> | null = null;
31
50
 
32
51
  export function loadFastembed(): Promise<FastembedModule> {
@@ -42,15 +61,15 @@ async function loadFastembedOnce(): Promise<FastembedModule> {
42
61
  // native addons and may be absent at runtime — a static import would load
43
62
  // the addon at module-init and crash every consumer without the peers.
44
63
  try {
45
- // Preload ORT 1.24 before fastembed's nested ORT 1.21 — only on Windows,
64
+ // Preload the pinned ORT before fastembed's nested ORT — only on Windows,
46
65
  // where loading the older binding first triggers a DLL-reuse crash.
47
66
  if (process.platform === "win32") {
48
67
  await import("onnxruntime-node");
49
68
  }
50
69
  return await import("fastembed");
51
70
  } catch (error) {
52
- if (!isModuleResolutionError(error)) throw error;
53
- logger.debug("mnemopi: fastembed not resolvable, using on-demand runtime install", {
71
+ if (!isRecoverableFastembedLoadError(error)) throw error;
72
+ logger.debug("mnemopi: fastembed not loadable, using on-demand runtime install", {
54
73
  error: String(error),
55
74
  });
56
75
  return loadFromRuntimeInstall();
@@ -58,10 +77,10 @@ async function loadFastembedOnce(): Promise<FastembedModule> {
58
77
  }
59
78
 
60
79
  async function loadFromRuntimeInstall(): Promise<FastembedModule> {
61
- const versionKey = `fastembed-${FASTEMBED_SPEC}_ort-${ORT_SPEC}`.replace(/[^A-Za-z0-9._-]/g, "_");
80
+ const plan = fastembedRuntimeInstallPlan();
62
81
  const runtimeDir = await ensureRuntimeInstalled({
63
- runtimeDir: path.join(getFastembedRuntimeDir(), versionKey),
64
- install: { dependencies: { fastembed: FASTEMBED_SPEC, "onnxruntime-node": ORT_SPEC } },
82
+ runtimeDir: path.join(getFastembedRuntimeDir(), plan.versionKey),
83
+ install: plan.install,
65
84
  probePackage: "fastembed",
66
85
  });
67
86
  const nodeModules = path.join(runtimeDir, "node_modules");
@@ -80,10 +99,10 @@ async function loadFromRuntimeInstall(): Promise<FastembedModule> {
80
99
  return requireRuntime(entry) as FastembedModule;
81
100
  }
82
101
 
83
- function isModuleResolutionError(error: unknown): boolean {
102
+ function isRecoverableFastembedLoadError(error: unknown): boolean {
84
103
  if (typeof error !== "object" || error === null) return false;
85
104
  const { name, code, message } = error as { name?: unknown; code?: unknown; message?: unknown };
86
105
  if (name === "ResolveMessage") return true;
87
- if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND") return true;
106
+ if (code === "ERR_MODULE_NOT_FOUND" || code === "MODULE_NOT_FOUND" || code === "ERR_DLOPEN_FAILED") return true;
88
107
  return typeof message === "string" && /cannot find (module|package)/i.test(message);
89
108
  }