@linxiraos/pi-utils 1.1.10 → 1.1.12
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 +12 -0
- package/README.md +1 -2
- package/dist/types/dirs.d.ts +11 -15
- package/dist/types/env.d.ts +1 -2
- package/dist/types/worker-host.d.ts +1 -1
- package/package.json +48 -48
- package/src/dirs.ts +46 -66
- package/src/env.ts +7 -14
- package/src/worker-host.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,8 +2,20 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [1.1.12] - 2026-09-10
|
|
6
|
+
|
|
7
|
+
- worker 宿主选择器族统一为 `__zeta_worker_*` 前缀(与主 CLI 对齐)。
|
|
8
|
+
|
|
9
|
+
## [1.1.11] - 2026-09-08
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- 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`.
|
|
14
|
+
|
|
5
15
|
## [1.1.10] - 2026-09-07
|
|
6
16
|
|
|
17
|
+
### Fixed
|
|
18
|
+
|
|
7
19
|
- 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
20
|
|
|
9
21
|
## [1.1.9] - 2026-09-05
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @linxiraos/pi-utils
|
|
2
2
|
|
|
3
|
-
Shared utilities for
|
|
3
|
+
Shared utilities for Zeta packages. Zero ceremony, Bun-first.
|
|
4
4
|
|
|
5
5
|
## Notable modules
|
|
6
6
|
|
|
@@ -33,5 +33,4 @@ Ships TypeScript source directly (no build step); requires Bun ≥ 1.3.14.
|
|
|
33
33
|
|
|
34
34
|
## References
|
|
35
35
|
|
|
36
|
-
- [Monorepo README](https://github.com/can1357/oh-my-pi#readme)
|
|
37
36
|
- [CHANGELOG](./CHANGELOG.md)
|
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;
|
|
@@ -123,7 +119,7 @@ export declare function getProjectAgentDir(cwd?: string): string;
|
|
|
123
119
|
export declare function getReportsDir(): string;
|
|
124
120
|
/** Get the logs directory (~/.zeta/logs). */
|
|
125
121
|
export declare function getLogsDir(): string;
|
|
126
|
-
/** Get this process's dated log path (~/.zeta/logs/
|
|
122
|
+
/** Get this process's dated log path (~/.zeta/logs/zeta.YYYY-MM-DD.PID.log). */
|
|
127
123
|
export declare function getLogPath(date?: Date, pid?: number): string;
|
|
128
124
|
/**
|
|
129
125
|
* Get the plugins directory (~/.zeta/plugins or its XDG equivalent).
|
|
@@ -267,9 +263,9 @@ export declare function getAgentModulesDir(agentDir?: string): string;
|
|
|
267
263
|
export declare function getMemoriesDir(agentDir?: string): string;
|
|
268
264
|
/** Get the terminal sessions directory (~/.zeta/agent/terminal-sessions). */
|
|
269
265
|
export declare function getTerminalSessionsDir(agentDir?: string): string;
|
|
270
|
-
/** Get the crash log path (~/.zeta/agent/
|
|
266
|
+
/** Get the crash log path (~/.zeta/agent/zeta-crash.log). */
|
|
271
267
|
export declare function getCrashLogPath(agentDir?: string): string;
|
|
272
|
-
/** Get the debug log path (~/.zeta/agent/
|
|
268
|
+
/** Get the debug log path (~/.zeta/agent/zeta-debug.log). */
|
|
273
269
|
export declare function getDebugLogPath(agentDir?: string): string;
|
|
274
270
|
/** Get the secret placeholder key path (~/.zeta/agent/secret-placeholder.key; XDG default: $XDG_STATE_HOME/zeta/secret-placeholder.key). Adopts a legacy key on first XDG resolution. */
|
|
275
271
|
export declare function getSecretPlaceholderKeyPath(): string;
|
|
@@ -299,7 +295,7 @@ export declare function getMCPConfigPath(scope: "user" | "project", cwd?: string
|
|
|
299
295
|
export declare function getSSHConfigPath(scope: "user" | "project", cwd?: string): string;
|
|
300
296
|
/**
|
|
301
297
|
* Application label for usage attribution (`OMP_APP_NAME`), defaulting to
|
|
302
|
-
* `
|
|
298
|
+
* `zeta`. Embedders that drive zeta programmatically (robomp, CI bots, …) set
|
|
303
299
|
* the env var so broker-side per-client burn tracking can answer "what did
|
|
304
300
|
* app X use" instead of folding everything into one install-wide bucket.
|
|
305
301
|
*/
|
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
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Prefix reserved for argv selectors dispatched by the shared CLI worker host. */
|
|
2
|
-
export declare const WORKER_HOST_SELECTOR_PREFIX = "
|
|
2
|
+
export declare const WORKER_HOST_SELECTOR_PREFIX = "__zeta_worker_";
|
|
3
3
|
/** Whether an argv value selects a worker hosted by the shared CLI entrypoint. */
|
|
4
4
|
export declare function isWorkerHostSelector(value: string | undefined): value is string;
|
|
5
5
|
/** Called by CLI entrypoints whose main module dispatches worker argv selectors. */
|
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.12",
|
|
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.12"
|
|
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
|
}
|
|
@@ -588,7 +568,7 @@ export function getLogsDir(): string {
|
|
|
588
568
|
return dirs.rootSubdir("logs", "state");
|
|
589
569
|
}
|
|
590
570
|
|
|
591
|
-
/** Get this process's dated log path (~/.zeta/logs/
|
|
571
|
+
/** Get this process's dated log path (~/.zeta/logs/zeta.YYYY-MM-DD.PID.log). */
|
|
592
572
|
export function getLogPath(date = new Date(), pid = process.pid): string {
|
|
593
573
|
return path.join(getLogsDir(), `${APP_NAME}.${date.toISOString().slice(0, 10)}.${pid}.log`);
|
|
594
574
|
}
|
|
@@ -913,12 +893,12 @@ export function getTerminalSessionsDir(agentDir?: string): string {
|
|
|
913
893
|
return dirs.agentSubdir(agentDir, "terminal-sessions", "state");
|
|
914
894
|
}
|
|
915
895
|
|
|
916
|
-
/** Get the crash log path (~/.zeta/agent/
|
|
896
|
+
/** Get the crash log path (~/.zeta/agent/zeta-crash.log). */
|
|
917
897
|
export function getCrashLogPath(agentDir?: string): string {
|
|
918
|
-
return dirs.agentSubdir(agentDir, "
|
|
898
|
+
return dirs.agentSubdir(agentDir, "zeta-crash.log", "state");
|
|
919
899
|
}
|
|
920
900
|
|
|
921
|
-
/** Get the debug log path (~/.zeta/agent/
|
|
901
|
+
/** Get the debug log path (~/.zeta/agent/zeta-debug.log). */
|
|
922
902
|
export function getDebugLogPath(agentDir?: string): string {
|
|
923
903
|
return dirs.agentSubdir(agentDir, `${APP_NAME}-debug.log`, "state");
|
|
924
904
|
}
|
|
@@ -1038,13 +1018,13 @@ let cachedInstallId: string | null = null;
|
|
|
1038
1018
|
const INSTALL_ID_FILE = "install-id";
|
|
1039
1019
|
/**
|
|
1040
1020
|
* Application label for usage attribution (`OMP_APP_NAME`), defaulting to
|
|
1041
|
-
* `
|
|
1021
|
+
* `zeta`. Embedders that drive zeta programmatically (robomp, CI bots, …) set
|
|
1042
1022
|
* the env var so broker-side per-client burn tracking can answer "what did
|
|
1043
1023
|
* app X use" instead of folding everything into one install-wide bucket.
|
|
1044
1024
|
*/
|
|
1045
1025
|
export function getAppName(): string {
|
|
1046
1026
|
const value = process.env.OMP_APP_NAME?.trim();
|
|
1047
|
-
return value ? value : "
|
|
1027
|
+
return value ? value : "zeta";
|
|
1048
1028
|
}
|
|
1049
1029
|
|
|
1050
1030
|
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
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
|
package/src/worker-host.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { stripWindowsExtendedLengthPathPrefix } from "./path";
|
|
2
2
|
|
|
3
3
|
/** Prefix reserved for argv selectors dispatched by the shared CLI worker host. */
|
|
4
|
-
export const WORKER_HOST_SELECTOR_PREFIX = "
|
|
4
|
+
export const WORKER_HOST_SELECTOR_PREFIX = "__zeta_worker_";
|
|
5
5
|
|
|
6
6
|
/** Whether an argv value selects a worker hosted by the shared CLI entrypoint. */
|
|
7
7
|
export function isWorkerHostSelector(value: string | undefined): value is string {
|
|
@@ -10,7 +10,7 @@ export function isWorkerHostSelector(value: string | undefined): value is string
|
|
|
10
10
|
|
|
11
11
|
/**
|
|
12
12
|
* Main-module path declared by self-dispatching CLI entrypoints — entries
|
|
13
|
-
* whose top-level argv handling routes hidden `
|
|
13
|
+
* whose top-level argv handling routes hidden `__zeta_**` worker selectors.
|
|
14
14
|
* Worker spawn sites re-enter this module via `new Worker(entry, { argv })`,
|
|
15
15
|
* so every distribution (source, npm bundle, compiled binary) needs exactly
|
|
16
16
|
* one JavaScript entrypoint. Never set under `bun test`, SDK embedding, or
|