@linxiraos/pi-utils 1.4.9 → 1.4.10

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
@@ -1,5 +1,9 @@
1
1
  ## [Unreleased]
2
2
 
3
+ ## [1.4.10] - 2026-11-05
4
+
5
+ - Legacy OMP dotenv files are no longer loaded by default; set `ZETA_OMP_COMPAT=1` to opt into the read-only fallback. Zeta `.zeta` dotenv files keep precedence.
6
+
3
7
  ## [1.4.9] - 2026-11-03
4
8
 
5
9
  - Synced with upstream OMP v18.16.0; no package-specific user-visible changes.
@@ -44,6 +44,7 @@ export declare function getDotenvEnvValues(cwd?: string, env?: Record<string, st
44
44
  * only shell-identifier names and spawn-safe values.
45
45
  */
46
46
  export declare function parseEnvFile(filePath: string): Record<string, string>;
47
+ export declare function isOmpCompatEnabled(env?: Record<string, string | undefined>): boolean;
47
48
  /**
48
49
  * Intentional re-export of Bun.env.
49
50
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linxiraos/pi-utils",
3
- "version": "1.4.9",
3
+ "version": "1.4.10",
4
4
  "description": "Shared utilities for pi packages",
5
5
  "keywords": [
6
6
  "utilities",
@@ -54,8 +54,8 @@
54
54
  "fmt": "oxfmt --no-error-on-unmatched-pattern 'src/**/*.{ts,tsx}' '{test,bench,examples,scripts}/**/*.ts' '*.ts'"
55
55
  },
56
56
  "dependencies": {
57
- "@linxiraos/pi-natives": "1.4.9",
58
- "@linxiraos/pi-omptype": "1.4.9"
57
+ "@linxiraos/pi-natives": "1.4.10",
58
+ "@linxiraos/pi-omptype": "1.4.10"
59
59
  },
60
60
  "devDependencies": {
61
61
  "@types/bun": "1.4.4"
package/src/env.ts CHANGED
@@ -2,7 +2,7 @@ import * as fs from "node:fs";
2
2
  import * as os from "node:os";
3
3
  import * as path from "node:path";
4
4
  import { parseEnv } from "node:util";
5
- import { getAgentDir, getConfigRootDir, getProjectDir, refreshDirsFromEnv } from "./dirs";
5
+ import { getActiveProfile, getAgentDir, getConfigRootDir, getProjectDir, refreshDirsFromEnv } from "./dirs";
6
6
  import { isBunTestRuntime } from "./test-runtime";
7
7
 
8
8
  export * from "./test-runtime";
@@ -278,11 +278,55 @@ export function parseEnvFile(filePath: string): Record<string, string> {
278
278
  return result;
279
279
  }
280
280
 
281
+ // Read-only compatibility with the old OMP agent directory. Off by default:
282
+ // external OMP configuration must be explicitly imported. Set
283
+ // ZETA_OMP_COMPAT=1 in the shell or a Zeta dotenv file to enable both the
284
+ // legacy dotenv fallback and the models.yml/agent.db overlay.
285
+ export function isOmpCompatEnabled(env: Record<string, string | undefined> = Bun.env): boolean {
286
+ const value = env.ZETA_OMP_COMPAT;
287
+ if (!value) return false;
288
+ const normalized = value.toLowerCase();
289
+ return normalized === "1" || normalized === "true" || normalized === "yes" || normalized === "on";
290
+ }
291
+
292
+ function loadLegacyOmpEnv(): Record<string, string> {
293
+ const home = os.homedir();
294
+ const project = getProjectDir();
295
+ const profile = getActiveProfile();
296
+ const files = [
297
+ { file: path.join(home, ".omp", ".env"), project: false },
298
+ { file: path.join(home, ".omp", "agent", ".env"), project: false },
299
+ ...(profile ? [{ file: path.join(home, ".omp", "profiles", profile, "agent", ".env"), project: false }] : []),
300
+ { file: path.join(project, ".omp", ".env"), project: true },
301
+ { file: path.join(project, ".omp", "agent", ".env"), project: true },
302
+ ];
303
+ const merged: Record<string, string> = {};
304
+ const seen = new Set<string>();
305
+ for (const { file, project: projectFile } of files) {
306
+ if (seen.has(file)) continue;
307
+ seen.add(file);
308
+ for (const [key, value] of Object.entries(parseEnvFile(file))) {
309
+ merged[key] = value;
310
+ if (projectFile) projectEnvNamesLoadedByOmp.add(key);
311
+ }
312
+ }
313
+ return merged;
314
+ }
315
+
281
316
  // Eagerly parse the user's $HOME/.env and the current project's .env (from cwd)
282
317
  const homeEnv = parseEnvFile(path.join(os.homedir(), ".env"));
283
318
  const piEnv = parseEnvFile(path.join(getConfigRootDir(), ".env"));
284
319
  const agentEnv = parseEnvFile(path.join(getAgentDir(), ".env"));
285
320
  const projectEnv = parseEnvFile(path.join(getProjectDir(), ".env"));
321
+ // The switch itself may come from the shell or any Zeta dotenv file. Check the
322
+ // same precedence before touching legacy OMP files; do not read them by default.
323
+ const ompCompatValue =
324
+ Bun.env.ZETA_OMP_COMPAT ??
325
+ projectEnv.ZETA_OMP_COMPAT ??
326
+ agentEnv.ZETA_OMP_COMPAT ??
327
+ piEnv.ZETA_OMP_COMPAT ??
328
+ homeEnv.ZETA_OMP_COMPAT;
329
+ const legacyOmpEnv = isOmpCompatEnabled({ ZETA_OMP_COMPAT: ompCompatValue }) ? loadLegacyOmpEnv() : {};
286
330
 
287
331
  for (const key of Object.keys(Bun.env)) {
288
332
  const value = Bun.env[key];
@@ -291,7 +335,7 @@ for (const key of Object.keys(Bun.env)) {
291
335
  }
292
336
  }
293
337
 
294
- for (const file of [projectEnv, agentEnv, piEnv, homeEnv]) {
338
+ for (const file of [projectEnv, agentEnv, piEnv, homeEnv, legacyOmpEnv]) {
295
339
  for (const key in file) {
296
340
  if (!isMacosMallocStackLoggingEnvName(key) && !Bun.env[key]) {
297
341
  Bun.env[key] = file[key];