@linxiraos/pi-utils 1.1.10 → 1.1.11
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 +8 -0
- package/dist/types/dirs.d.ts +7 -11
- package/dist/types/env.d.ts +1 -2
- package/package.json +48 -48
- package/src/dirs.ts +40 -60
- package/src/env.ts +7 -14
package/CHANGELOG.md
CHANGED
|
@@ -2,8 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.1.11] - 2026-09-08
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
|
|
9
|
+
- Fixed `filterChildShellEnv` applying the Zeta process's own launch-environment provenance (the pre-dotenv `NODE_ENV` and launcher-owned names read from `/proc/self/environ`) to caller-supplied environment objects; launch provenance now only applies when filtering the live `process.env`/`Bun.env`, and an explicit env resolves its dotenv mode from its own `NODE_ENV`.
|
|
10
|
+
|
|
5
11
|
## [1.1.10] - 2026-09-07
|
|
6
12
|
|
|
13
|
+
### Fixed
|
|
14
|
+
|
|
7
15
|
- Fixed `extractRetryHint` dropping the longer timing signal when an error body carries both an account reset and an appended retry hint: competing signals now merge by longest window instead of first match, so retries honor the provider's full backoff.
|
|
8
16
|
|
|
9
17
|
## [1.1.9] - 2026-09-05
|
package/dist/types/dirs.d.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Centralized path helpers for zeta config directories.
|
|
3
3
|
*
|
|
4
4
|
* Uses PI_CONFIG_DIR (default ".zeta") for the config root and
|
|
5
|
-
*
|
|
5
|
+
* ZETA_CODING_AGENT_DIR to override the agent directory.
|
|
6
6
|
*
|
|
7
7
|
* On Linux, if XDG_DATA_HOME / XDG_STATE_HOME / XDG_CACHE_HOME environment
|
|
8
8
|
* variables are set, paths are redirected to XDG-compliant locations under
|
|
@@ -32,14 +32,11 @@ export declare const MIN_BUN_VERSION: string;
|
|
|
32
32
|
*/
|
|
33
33
|
export declare function normalizeProfileName(profile: string | undefined): string | undefined;
|
|
34
34
|
/**
|
|
35
|
-
* Resolve the active profile from
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
* explicitly-empty `OMP_PROFILE` therefore selects the default profile rather
|
|
39
|
-
* than silently inheriting `PI_PROFILE`. Delegates validation/normalization to
|
|
40
|
-
* {@link normalizeProfileName} (which throws on a syntactically invalid value).
|
|
35
|
+
* Resolve the active profile from `ZETA_PROFILE`. Delegates
|
|
36
|
+
* validation/normalization to {@link normalizeProfileName} (which throws on a
|
|
37
|
+
* syntactically invalid value).
|
|
41
38
|
*/
|
|
42
|
-
export declare function resolveProfileEnv(
|
|
39
|
+
export declare function resolveProfileEnv(profile: string | undefined): string | undefined;
|
|
43
40
|
export declare function resolveEquivalentPath(inputPath: string): string;
|
|
44
41
|
export declare function normalizePathForComparison(inputPath: string): string;
|
|
45
42
|
export declare function pathIsWithin(root: string, candidate: string): boolean;
|
|
@@ -81,7 +78,7 @@ export declare function getConfigAgentDirName(): string;
|
|
|
81
78
|
/**
|
|
82
79
|
* Rebuild the dirs resolver from the current environment, reusing the profile
|
|
83
80
|
* resolved at module load. Directory-affecting keys (XDG_*_HOME and, in default
|
|
84
|
-
* mode, `
|
|
81
|
+
* mode, `ZETA_CODING_AGENT_DIR`) loaded from a profile/agent `.env` only reach
|
|
85
82
|
* `process.env` *after* this module froze the resolver at import time, so
|
|
86
83
|
* `env.ts` calls this once after applying its `.env` files. The agent `.env`
|
|
87
84
|
* location derives from the profile name + home before this runs, so the
|
|
@@ -94,7 +91,7 @@ export declare function getConfigRootDir(): string;
|
|
|
94
91
|
/** Set the coding agent directory. Creates a fresh resolver, invalidating all cached paths. */
|
|
95
92
|
export declare function setAgentDir(dir: string): void;
|
|
96
93
|
/**
|
|
97
|
-
* Test-only: reset the pre-profile `
|
|
94
|
+
* Test-only: reset the pre-profile `ZETA_CODING_AGENT_DIR` snapshot to whatever
|
|
98
95
|
* the current environment looks like. Cross-suite test pollution can otherwise
|
|
99
96
|
* leak a stale snapshot through `setAgentDir` and corrupt `setProfile(undefined)`
|
|
100
97
|
* restore semantics. Production code MUST NOT call this — the snapshot's
|
|
@@ -109,7 +106,6 @@ export declare function __resetProfileSnapshotForTests(): void;
|
|
|
109
106
|
* back.
|
|
110
107
|
*/
|
|
111
108
|
export declare function __resetDirsFromEnvForTests(): void;
|
|
112
|
-
/** Activate a named profile. Passing undefined or "default" returns to the default profile. */
|
|
113
109
|
export declare function setProfile(profile: string | undefined): void;
|
|
114
110
|
/** Get the active named profile. Undefined means the default profile. */
|
|
115
111
|
export declare function getActiveProfile(): string | undefined;
|
package/dist/types/env.d.ts
CHANGED
|
@@ -30,8 +30,7 @@ export declare function filterProcessEnv(env: Record<string, string | undefined>
|
|
|
30
30
|
export declare function filterChildShellEnv(env: Record<string, string | undefined>, cwd?: string): Record<string, string>;
|
|
31
31
|
/**
|
|
32
32
|
* Parses a .env file synchronously into key-value string pairs using
|
|
33
|
-
* {@link parseEnvLine} for Bun-compatible line semantics
|
|
34
|
-
* `OMP_` variables to their `PI_` aliases.
|
|
33
|
+
* {@link parseEnvLine} for Bun-compatible line semantics.
|
|
35
34
|
*/
|
|
36
35
|
export declare function parseEnvFile(filePath: string): Record<string, string>;
|
|
37
36
|
/**
|
package/package.json
CHANGED
|
@@ -1,36 +1,24 @@
|
|
|
1
1
|
{
|
|
2
|
-
"
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
"
|
|
6
|
-
"
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
"
|
|
10
|
-
|
|
11
|
-
"
|
|
12
|
-
|
|
13
|
-
"
|
|
14
|
-
"check": "tsgo -p tsconfig.json --noEmit"
|
|
2
|
+
"name": "@linxiraos/pi-utils",
|
|
3
|
+
"version": "1.1.11",
|
|
4
|
+
"description": "Shared utilities for pi packages",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"utilities",
|
|
7
|
+
"cli",
|
|
8
|
+
"logging",
|
|
9
|
+
"streams"
|
|
10
|
+
],
|
|
11
|
+
"homepage": "https://linxira-os.github.io/zeta/",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Linxira-OS/linxira-zeta/issues"
|
|
15
14
|
},
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"./ar": {
|
|
23
|
-
"import": "./src/ar/index.ts",
|
|
24
|
-
"types": "./dist/types/ar/index.d.ts"
|
|
25
|
-
},
|
|
26
|
-
".": {
|
|
27
|
-
"import": "./src/index.ts",
|
|
28
|
-
"types": "./dist/types/index.d.ts"
|
|
29
|
-
}
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"author": "Can Boluk",
|
|
17
|
+
"repository": {
|
|
18
|
+
"directory": "packages/utils",
|
|
19
|
+
"url": "git+https://github.com/Linxira-OS/linxira-zeta.git",
|
|
20
|
+
"type": "git"
|
|
30
21
|
},
|
|
31
|
-
"types": "./dist/types/index.d.ts",
|
|
32
|
-
"main": "./src/index.ts",
|
|
33
|
-
"type": "module",
|
|
34
22
|
"files": [
|
|
35
23
|
"src",
|
|
36
24
|
"README.md",
|
|
@@ -39,24 +27,36 @@
|
|
|
39
27
|
"THIRD-PARTY-NOTICES.txt",
|
|
40
28
|
"dist/types"
|
|
41
29
|
],
|
|
42
|
-
"
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
30
|
+
"type": "module",
|
|
31
|
+
"main": "./src/index.ts",
|
|
32
|
+
"types": "./dist/types/index.d.ts",
|
|
33
|
+
"exports": {
|
|
34
|
+
".": {
|
|
35
|
+
"types": "./dist/types/index.d.ts",
|
|
36
|
+
"import": "./src/index.ts"
|
|
37
|
+
},
|
|
38
|
+
"./ar": {
|
|
39
|
+
"types": "./dist/types/ar/index.d.ts",
|
|
40
|
+
"import": "./src/ar/index.ts"
|
|
41
|
+
},
|
|
42
|
+
"./*": {
|
|
43
|
+
"types": "./dist/types/*.d.ts",
|
|
44
|
+
"import": "./src/*.ts"
|
|
45
|
+
},
|
|
46
|
+
"./*.js": "./src/*.ts"
|
|
46
47
|
},
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"
|
|
48
|
+
"scripts": {
|
|
49
|
+
"check": "tsgo -p tsconfig.json --noEmit",
|
|
50
|
+
"check:types": "tsgo -p tsconfig.json --noEmit",
|
|
51
|
+
"test": "bun test --parallel"
|
|
51
52
|
},
|
|
52
|
-
"
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
"
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
"name": "@linxiraos/pi-utils"
|
|
53
|
+
"dependencies": {
|
|
54
|
+
"@linxiraos/pi-natives": "1.1.11"
|
|
55
|
+
},
|
|
56
|
+
"devDependencies": {
|
|
57
|
+
"@types/bun": "^1.3.14"
|
|
58
|
+
},
|
|
59
|
+
"engines": {
|
|
60
|
+
"bun": ">=1.3.14"
|
|
61
|
+
}
|
|
62
62
|
}
|
package/src/dirs.ts
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Centralized path helpers for zeta config directories.
|
|
3
3
|
*
|
|
4
4
|
* Uses PI_CONFIG_DIR (default ".zeta") for the config root and
|
|
5
|
-
*
|
|
5
|
+
* ZETA_CODING_AGENT_DIR to override the agent directory.
|
|
6
6
|
*
|
|
7
7
|
* On Linux, if XDG_DATA_HOME / XDG_STATE_HOME / XDG_CACHE_HOME environment
|
|
8
8
|
* variables are set, paths are redirected to XDG-compliant locations under
|
|
@@ -36,7 +36,7 @@ export const USER_AGENT = `zeta/${VERSION}`;
|
|
|
36
36
|
export const MIN_BUN_VERSION: string = engines.bun.replace(/[^0-9.]/g, "");
|
|
37
37
|
|
|
38
38
|
const PROFILE_NAME_RE = /^[a-z0-9][a-z0-9._-]{0,63}$/;
|
|
39
|
-
const PROFILE_ENV_KEYS = ["
|
|
39
|
+
const PROFILE_ENV_KEYS = ["ZETA_PROFILE"] as const;
|
|
40
40
|
|
|
41
41
|
/**
|
|
42
42
|
* Names Windows treats as reserved device aliases. Matches the basename
|
|
@@ -76,24 +76,21 @@ export function normalizeProfileName(profile: string | undefined): string | unde
|
|
|
76
76
|
}
|
|
77
77
|
|
|
78
78
|
/**
|
|
79
|
-
* Resolve the active profile from
|
|
80
|
-
*
|
|
81
|
-
*
|
|
82
|
-
* explicitly-empty `OMP_PROFILE` therefore selects the default profile rather
|
|
83
|
-
* than silently inheriting `PI_PROFILE`. Delegates validation/normalization to
|
|
84
|
-
* {@link normalizeProfileName} (which throws on a syntactically invalid value).
|
|
79
|
+
* Resolve the active profile from `ZETA_PROFILE`. Delegates
|
|
80
|
+
* validation/normalization to {@link normalizeProfileName} (which throws on a
|
|
81
|
+
* syntactically invalid value).
|
|
85
82
|
*/
|
|
86
|
-
export function resolveProfileEnv(
|
|
87
|
-
return normalizeProfileName(
|
|
83
|
+
export function resolveProfileEnv(profile: string | undefined): string | undefined {
|
|
84
|
+
return normalizeProfileName(profile);
|
|
88
85
|
}
|
|
89
86
|
|
|
90
87
|
function getProfileFromEnv(): string | undefined {
|
|
91
|
-
return resolveProfileEnv(process.env.
|
|
88
|
+
return resolveProfileEnv(process.env.ZETA_PROFILE);
|
|
92
89
|
}
|
|
93
90
|
|
|
94
91
|
/**
|
|
95
92
|
* Module-load profile resolution. Unlike {@link getProfileFromEnv}, an invalid
|
|
96
|
-
*
|
|
93
|
+
* ZETA_PROFILE value does NOT throw here — a bad env var must not
|
|
97
94
|
* crash a bare `import` of this module with an uncaught stack trace before the
|
|
98
95
|
* CLI's error handling is in scope. The default profile is used instead; the
|
|
99
96
|
* CLI re-validates the env (see `runCli` in coding-agent/src/cli.ts) so the
|
|
@@ -116,14 +113,6 @@ function getProfileConfigRoot(profile: string | undefined): string {
|
|
|
116
113
|
return profile ? path.join(root, "profiles", profile) : root;
|
|
117
114
|
}
|
|
118
115
|
|
|
119
|
-
function readPiProfileFromEnvSafe(): string | undefined {
|
|
120
|
-
try {
|
|
121
|
-
return normalizeProfileName(process.env.PI_PROFILE);
|
|
122
|
-
} catch {
|
|
123
|
-
return undefined;
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
116
|
function getProfileAgentDir(profile: string): string {
|
|
128
117
|
return path.join(getProfileConfigRoot(profile), "agent");
|
|
129
118
|
}
|
|
@@ -398,14 +387,14 @@ class DirResolver {
|
|
|
398
387
|
}
|
|
399
388
|
|
|
400
389
|
/**
|
|
401
|
-
* Decide which `
|
|
390
|
+
* Decide which `ZETA_CODING_AGENT_DIR` value to capture as the pre-profile
|
|
402
391
|
* baseline. A value equal to a profile's derived agent dir is profile-derived
|
|
403
392
|
* (propagated by a parent's `setProfile`), so it must NOT be snapshotted as the
|
|
404
393
|
* default-mode baseline — otherwise default mode would resolve to the profile's
|
|
405
|
-
* agent dir. The profile source can be the active profile or
|
|
406
|
-
* `
|
|
407
|
-
*
|
|
408
|
-
* standard `~/.zeta/agent`.
|
|
394
|
+
* agent dir. The profile source can be the active profile or an inherited
|
|
395
|
+
* `ZETA_PROFILE` (for example a parent CLI process that resolved a profile
|
|
396
|
+
* without exporting it). Returns `undefined` in those cases so reset falls back
|
|
397
|
+
* to the standard `~/.zeta/agent`.
|
|
409
398
|
*/
|
|
410
399
|
function resolvePreProfileAgentDir(
|
|
411
400
|
profile: string | undefined,
|
|
@@ -420,14 +409,21 @@ let activeProfile = readProfileFromEnvSafe();
|
|
|
420
409
|
/**
|
|
421
410
|
* Resolve the agent-dir override for the current `activeProfile` from the live
|
|
422
411
|
* environment. A named profile derives its own agent dir (no override); default
|
|
423
|
-
* mode honors a non-profile `
|
|
412
|
+
* mode honors a non-profile `ZETA_CODING_AGENT_DIR` (see
|
|
424
413
|
* {@link resolvePreProfileAgentDir}). Shared by the module-load resolver and
|
|
425
414
|
* {@link refreshDirsFromEnv} so both apply identical logic.
|
|
426
415
|
*/
|
|
427
416
|
function resolveActiveAgentDirOverride(): string | undefined {
|
|
428
|
-
return
|
|
429
|
-
|
|
430
|
-
|
|
417
|
+
if (activeProfile) return undefined;
|
|
418
|
+
// A ZETA_CODING_AGENT_DIR pointing under a profile subtree
|
|
419
|
+
// (`profiles/<name>/agent`) is derived state inherited from a parent that
|
|
420
|
+
// activated a profile — with a single profile key there is no second env var
|
|
421
|
+
// to consult, so the directory shape is the only witness. Treat it as absent
|
|
422
|
+
// for default-mode resolution (and the pre-profile snapshot), or default mode
|
|
423
|
+
// would silently resolve into a profile's agent dir.
|
|
424
|
+
const env = process.env.ZETA_CODING_AGENT_DIR;
|
|
425
|
+
if (env && /[/\\]profiles[/\\][^/\\]+[/\\]agent$/.test(env.replace(/\\/g, "/"))) return undefined;
|
|
426
|
+
return resolvePreProfileAgentDir(undefined, env);
|
|
431
427
|
}
|
|
432
428
|
|
|
433
429
|
let dirs = new DirResolver({
|
|
@@ -435,21 +431,16 @@ let dirs = new DirResolver({
|
|
|
435
431
|
profile: activeProfile,
|
|
436
432
|
});
|
|
437
433
|
/**
|
|
438
|
-
* Snapshot of `
|
|
434
|
+
* Snapshot of `ZETA_CODING_AGENT_DIR` from before the first named-profile
|
|
439
435
|
* activation. Reset paths restore this value (or its absence) instead of
|
|
440
436
|
* unconditionally deleting the env var. Without the snapshot, a process started
|
|
441
|
-
* with `
|
|
437
|
+
* with `ZETA_CODING_AGENT_DIR=/custom` then `setProfile("work")` then
|
|
442
438
|
* `setProfile(undefined)` would silently lose `/custom` and fall back to
|
|
443
439
|
* `~/.zeta/agent`. Captured at module load — ignoring a profile-derived value
|
|
444
|
-
* inherited from a parent's `setProfile` (
|
|
445
|
-
* — and refreshed on `setAgentDir
|
|
446
|
-
* redefining the baseline.
|
|
440
|
+
* inherited from a parent's `setProfile` (detected by directory shape in
|
|
441
|
+
* {@link resolveActiveAgentDirOverride}) — and refreshed on `setAgentDir`.
|
|
447
442
|
*/
|
|
448
|
-
let preProfileAgentDirEnv: string | undefined =
|
|
449
|
-
activeProfile,
|
|
450
|
-
process.env.PI_CODING_AGENT_DIR,
|
|
451
|
-
activeProfile ?? readPiProfileFromEnvSafe(),
|
|
452
|
-
);
|
|
443
|
+
let preProfileAgentDirEnv: string | undefined = resolveActiveAgentDirOverride();
|
|
453
444
|
// Anchor home for the resolver. Captured at module load to stay stable across
|
|
454
445
|
// test mocks of `os.homedir()`. `getPluginsDir(home)` compares against this so
|
|
455
446
|
// production callers (`home === RESOLVER_HOME`) hit the XDG-aware resolver while
|
|
@@ -459,7 +450,7 @@ const RESOLVER_HOME = os.homedir();
|
|
|
459
450
|
/**
|
|
460
451
|
* Rebuild the dirs resolver from the current environment, reusing the profile
|
|
461
452
|
* resolved at module load. Directory-affecting keys (XDG_*_HOME and, in default
|
|
462
|
-
* mode, `
|
|
453
|
+
* mode, `ZETA_CODING_AGENT_DIR`) loaded from a profile/agent `.env` only reach
|
|
463
454
|
* `process.env` *after* this module froze the resolver at import time, so
|
|
464
455
|
* `env.ts` calls this once after applying its `.env` files. The agent `.env`
|
|
465
456
|
* location derives from the profile name + home before this runs, so the
|
|
@@ -486,15 +477,14 @@ export function getConfigRootDir(): string {
|
|
|
486
477
|
export function setAgentDir(dir: string): void {
|
|
487
478
|
activeProfile = undefined;
|
|
488
479
|
dirs = new DirResolver({ agentDirOverride: dir });
|
|
489
|
-
process.env.
|
|
490
|
-
preProfileAgentDirEnv = dir;
|
|
480
|
+
process.env.ZETA_CODING_AGENT_DIR = dir;
|
|
491
481
|
for (const key of PROFILE_ENV_KEYS) {
|
|
492
482
|
delete process.env[key];
|
|
493
483
|
}
|
|
494
484
|
}
|
|
495
485
|
|
|
496
486
|
/**
|
|
497
|
-
* Test-only: reset the pre-profile `
|
|
487
|
+
* Test-only: reset the pre-profile `ZETA_CODING_AGENT_DIR` snapshot to whatever
|
|
498
488
|
* the current environment looks like. Cross-suite test pollution can otherwise
|
|
499
489
|
* leak a stale snapshot through `setAgentDir` and corrupt `setProfile(undefined)`
|
|
500
490
|
* restore semantics. Production code MUST NOT call this — the snapshot's
|
|
@@ -502,11 +492,7 @@ export function setAgentDir(dir: string): void {
|
|
|
502
492
|
* no business clearing it.
|
|
503
493
|
*/
|
|
504
494
|
export function __resetProfileSnapshotForTests(): void {
|
|
505
|
-
preProfileAgentDirEnv =
|
|
506
|
-
activeProfile,
|
|
507
|
-
process.env.PI_CODING_AGENT_DIR,
|
|
508
|
-
activeProfile ?? readPiProfileFromEnvSafe(),
|
|
509
|
-
);
|
|
495
|
+
preProfileAgentDirEnv = resolveActiveAgentDirOverride();
|
|
510
496
|
}
|
|
511
497
|
|
|
512
498
|
/**
|
|
@@ -521,35 +507,29 @@ export function __resetDirsFromEnvForTests(): void {
|
|
|
521
507
|
refreshDirsFromEnv();
|
|
522
508
|
}
|
|
523
509
|
|
|
524
|
-
/** Activate a named profile. Passing undefined or "default" returns to the default profile. */
|
|
525
510
|
export function setProfile(profile: string | undefined): void {
|
|
526
511
|
const next = normalizeProfileName(profile);
|
|
527
512
|
if (next && !activeProfile) {
|
|
528
513
|
// First activation of a named profile in this process: snapshot the
|
|
529
|
-
// current
|
|
514
|
+
// current ZETA_CODING_AGENT_DIR so a later reset can restore the user's
|
|
530
515
|
// explicit override. Subsequent profile switches keep the original
|
|
531
516
|
// snapshot — the "pre-profile" baseline is the state before profiles
|
|
532
517
|
// entered the picture, not the state between two activations.
|
|
533
|
-
preProfileAgentDirEnv =
|
|
534
|
-
undefined,
|
|
535
|
-
process.env.PI_CODING_AGENT_DIR,
|
|
536
|
-
readPiProfileFromEnvSafe(),
|
|
537
|
-
);
|
|
518
|
+
preProfileAgentDirEnv = resolveActiveAgentDirOverride();
|
|
538
519
|
}
|
|
539
520
|
activeProfile = next;
|
|
540
521
|
if (activeProfile) {
|
|
541
522
|
dirs = new DirResolver({ profile: activeProfile });
|
|
542
|
-
process.env.
|
|
543
|
-
process.env.
|
|
544
|
-
process.env.PI_CODING_AGENT_DIR = dirs.agentDir;
|
|
523
|
+
process.env.ZETA_PROFILE = activeProfile;
|
|
524
|
+
process.env.ZETA_CODING_AGENT_DIR = dirs.agentDir;
|
|
545
525
|
} else {
|
|
546
526
|
for (const key of PROFILE_ENV_KEYS) {
|
|
547
527
|
delete process.env[key];
|
|
548
528
|
}
|
|
549
529
|
if (preProfileAgentDirEnv === undefined) {
|
|
550
|
-
delete process.env.
|
|
530
|
+
delete process.env.ZETA_CODING_AGENT_DIR;
|
|
551
531
|
} else {
|
|
552
|
-
process.env.
|
|
532
|
+
process.env.ZETA_CODING_AGENT_DIR = preProfileAgentDirEnv;
|
|
553
533
|
}
|
|
554
534
|
dirs = new DirResolver({ agentDirOverride: preProfileAgentDirEnv });
|
|
555
535
|
}
|
package/src/env.ts
CHANGED
|
@@ -112,9 +112,10 @@ export function filterChildShellEnv(
|
|
|
112
112
|
env: Record<string, string | undefined>,
|
|
113
113
|
cwd: string = process.cwd(),
|
|
114
114
|
): Record<string, string> {
|
|
115
|
+
const runtimeLaunchEnvValues = env === Bun.env || env === process.env ? launchEnvValues : undefined;
|
|
115
116
|
const result = filterProcessEnv(env);
|
|
116
117
|
const projectEnv = parseEnvFile(path.join(cwd, ".env"));
|
|
117
|
-
const launchNodeEnv =
|
|
118
|
+
const launchNodeEnv = runtimeLaunchEnvValues ? runtimeLaunchEnvValues.get("NODE_ENV") : env.NODE_ENV;
|
|
118
119
|
const nodeEnvName = `.env.${launchNodeEnv || "development"}`;
|
|
119
120
|
const modeEnv = parseEnvFile(path.join(cwd, nodeEnvName));
|
|
120
121
|
const localEnv = parseEnvFile(path.join(cwd, ".env.local"));
|
|
@@ -128,7 +129,7 @@ export function filterChildShellEnv(
|
|
|
128
129
|
};
|
|
129
130
|
let fallbackLaunchEnv: Record<string, string> | undefined;
|
|
130
131
|
let expandedFallbackLaunchEnv: Record<string, string> | undefined;
|
|
131
|
-
if (!
|
|
132
|
+
if (!runtimeLaunchEnvValues && nodeEnvName !== ".env.development") {
|
|
132
133
|
const fallbackModeEnv = parseEnvFile(path.join(cwd, ".env.development"));
|
|
133
134
|
const fallbackModeLocalEnv = parseEnvFile(path.join(cwd, ".env.development.local"));
|
|
134
135
|
const candidate = { ...projectEnv, ...fallbackModeEnv, ...localEnv, ...fallbackModeLocalEnv };
|
|
@@ -147,7 +148,7 @@ export function filterChildShellEnv(
|
|
|
147
148
|
}
|
|
148
149
|
const allLaunchEnv = fallbackLaunchEnv ? { ...launchEnv, ...fallbackLaunchEnv } : launchEnv;
|
|
149
150
|
for (const key in allLaunchEnv) {
|
|
150
|
-
const launchValue =
|
|
151
|
+
const launchValue = runtimeLaunchEnvValues?.get(key);
|
|
151
152
|
if (launchValue !== undefined) {
|
|
152
153
|
// Launcher-owned name: it keeps the launcher's own value. Bun overwrites
|
|
153
154
|
// an empty launcher value with the dotenv one, so restore the launcher
|
|
@@ -163,7 +164,7 @@ export function filterChildShellEnv(
|
|
|
163
164
|
}
|
|
164
165
|
continue;
|
|
165
166
|
}
|
|
166
|
-
if (
|
|
167
|
+
if (runtimeLaunchEnvValues || projectEnvNamesLoadedByOmp.has(key)) {
|
|
167
168
|
// Strong provenance: the launch environment is known and this name is
|
|
168
169
|
// absent from it, or OMP itself injected the value — either way it came
|
|
169
170
|
// from a project dotenv file, not the parent shell.
|
|
@@ -211,8 +212,7 @@ function parseEnvLine(line: string): { key: string; value: string } | undefined
|
|
|
211
212
|
|
|
212
213
|
/**
|
|
213
214
|
* Parses a .env file synchronously into key-value string pairs using
|
|
214
|
-
* {@link parseEnvLine} for Bun-compatible line semantics
|
|
215
|
-
* `OMP_` variables to their `PI_` aliases.
|
|
215
|
+
* {@link parseEnvLine} for Bun-compatible line semantics.
|
|
216
216
|
*/
|
|
217
217
|
export function parseEnvFile(filePath: string): Record<string, string> {
|
|
218
218
|
const result: Record<string, string> = {};
|
|
@@ -226,13 +226,6 @@ export function parseEnvFile(filePath: string): Record<string, string> {
|
|
|
226
226
|
// File doesn't exist or can't be read - return empty result
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
// OMP_ overrides PI_
|
|
230
|
-
for (const k in result) {
|
|
231
|
-
if (k.startsWith("OMP_")) {
|
|
232
|
-
result[`PI_${k.slice(4)}`] = result[k];
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
|
|
236
229
|
return result;
|
|
237
230
|
}
|
|
238
231
|
|
|
@@ -258,7 +251,7 @@ for (const file of [projectEnv, agentEnv, piEnv, homeEnv]) {
|
|
|
258
251
|
}
|
|
259
252
|
}
|
|
260
253
|
|
|
261
|
-
// Directory-affecting keys (XDG_*_HOME, and in default mode
|
|
254
|
+
// Directory-affecting keys (XDG_*_HOME, and in default mode ZETA_CODING_AGENT_DIR)
|
|
262
255
|
// may have just arrived from the profile/agent `.env` applied above. The dirs
|
|
263
256
|
// resolver cached its paths at module load — before this file ran — so rebuild
|
|
264
257
|
// it now from the updated env. `getAgentDir()` already located the `.env` from
|