@oh-my-pi/pi-utils 16.3.11 → 16.3.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 +10 -0
- package/dist/types/env.d.ts +2 -0
- package/dist/types/postmortem.d.ts +8 -0
- package/package.json +2 -2
- package/src/env.ts +13 -0
- package/src/postmortem.ts +27 -0
- package/src/procmgr.ts +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [16.3.12] - 2026-07-08
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added `postmortem.interceptUnhandledRejections()` to register interceptors consulted before an unhandled rejection tears the process down; a consuming interceptor (e.g. the JS eval runtime claiming rejections floated by user cell code) keeps the process alive and owns reporting.
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- Fixed child shell environment filtering to drop launch-directory `.env.local` values that Bun auto-loaded before OMP starts command shells. ([#4723](https://github.com/can1357/oh-my-pi/issues/4723))
|
|
14
|
+
|
|
5
15
|
## [16.3.10] - 2026-07-06
|
|
6
16
|
|
|
7
17
|
### Added
|
package/dist/types/env.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ export declare function isSafeEnvName(name: string): boolean;
|
|
|
17
17
|
export declare function isSafeEnvValue(value: string): boolean;
|
|
18
18
|
export declare function isMacosMallocStackLoggingEnvName(name: string): boolean;
|
|
19
19
|
export declare function filterProcessEnv(env: Record<string, string | undefined>): Record<string, string>;
|
|
20
|
+
/** Filters process env for child shells without launch-cwd `.env.local` values. */
|
|
21
|
+
export declare function filterChildShellEnv(env: Record<string, string | undefined>, cwd?: string): Record<string, string>;
|
|
20
22
|
/**
|
|
21
23
|
* Parses a .env file synchronously and extracts key-value string pairs.
|
|
22
24
|
* Ignores lines that are empty or start with '#'. Trims whitespace.
|
|
@@ -31,6 +31,14 @@ export declare function markExpectedCleanupError<T extends object>(reason: T): T
|
|
|
31
31
|
* its `cause`.
|
|
32
32
|
*/
|
|
33
33
|
export declare function isExpectedCleanupError(reason: unknown): boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Register an interceptor consulted before an unhandled rejection tears the
|
|
36
|
+
* process down. Return `true` to consume the rejection — the interceptor owns
|
|
37
|
+
* reporting and the process continues. Used by embedded script runtimes (JS
|
|
38
|
+
* eval cells) whose user code can float rejections the host must not die for.
|
|
39
|
+
* Returns an unregister function.
|
|
40
|
+
*/
|
|
41
|
+
export declare function interceptUnhandledRejections(interceptor: (reason: unknown) => boolean): () => void;
|
|
34
42
|
/**
|
|
35
43
|
* Register a process cleanup callback, to be run on shutdown, signal, or fatal error.
|
|
36
44
|
*
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-utils",
|
|
4
|
-
"version": "16.3.
|
|
4
|
+
"version": "16.3.12",
|
|
5
5
|
"description": "Shared utilities for pi packages",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
7
7
|
"author": "Can Boluk",
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"fmt": "biome format --write ."
|
|
32
32
|
},
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@oh-my-pi/pi-natives": "16.3.
|
|
34
|
+
"@oh-my-pi/pi-natives": "16.3.12",
|
|
35
35
|
"handlebars": "^4.7.9",
|
|
36
36
|
"winston": "^3.19.0",
|
|
37
37
|
"winston-daily-rotate-file": "^5.0.0"
|
package/src/env.ts
CHANGED
|
@@ -53,6 +53,19 @@ export function filterProcessEnv(env: Record<string, string | undefined>): Recor
|
|
|
53
53
|
return result;
|
|
54
54
|
}
|
|
55
55
|
|
|
56
|
+
/** Filters process env for child shells without launch-cwd `.env.local` values. */
|
|
57
|
+
export function filterChildShellEnv(
|
|
58
|
+
env: Record<string, string | undefined>,
|
|
59
|
+
cwd: string = process.cwd(),
|
|
60
|
+
): Record<string, string> {
|
|
61
|
+
const result = filterProcessEnv(env);
|
|
62
|
+
const launchLocalEnv = parseEnvFile(path.join(cwd, ".env.local"));
|
|
63
|
+
for (const key in launchLocalEnv) {
|
|
64
|
+
if (result[key] === launchLocalEnv[key]) delete result[key];
|
|
65
|
+
}
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
56
69
|
/**
|
|
57
70
|
* Parses a .env file synchronously and extracts key-value string pairs.
|
|
58
71
|
* Ignores lines that are empty or start with '#'. Trims whitespace.
|
package/src/postmortem.ts
CHANGED
|
@@ -121,6 +121,24 @@ export function isExpectedCleanupError(reason: unknown): boolean {
|
|
|
121
121
|
return false;
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
+
/**
|
|
125
|
+
* Interceptors consulted by the global `unhandledRejection` handler before the
|
|
126
|
+
* fatal path. See {@link interceptUnhandledRejections}.
|
|
127
|
+
*/
|
|
128
|
+
const rejectionInterceptors = new Set<(reason: unknown) => boolean>();
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Register an interceptor consulted before an unhandled rejection tears the
|
|
132
|
+
* process down. Return `true` to consume the rejection — the interceptor owns
|
|
133
|
+
* reporting and the process continues. Used by embedded script runtimes (JS
|
|
134
|
+
* eval cells) whose user code can float rejections the host must not die for.
|
|
135
|
+
* Returns an unregister function.
|
|
136
|
+
*/
|
|
137
|
+
export function interceptUnhandledRejections(interceptor: (reason: unknown) => boolean): () => void {
|
|
138
|
+
rejectionInterceptors.add(interceptor);
|
|
139
|
+
return () => rejectionInterceptors.delete(interceptor);
|
|
140
|
+
}
|
|
141
|
+
|
|
124
142
|
function formatFatalError(label: string, err: Error): string {
|
|
125
143
|
const name = err.name || "Error";
|
|
126
144
|
const message = err.message || "(no message)";
|
|
@@ -172,6 +190,15 @@ if (isMainThread) {
|
|
|
172
190
|
logger.warn("Ignoring expected cleanup rejection", { err });
|
|
173
191
|
return;
|
|
174
192
|
}
|
|
193
|
+
for (const interceptor of rejectionInterceptors) {
|
|
194
|
+
try {
|
|
195
|
+
if (interceptor(reason)) return;
|
|
196
|
+
} catch (interceptorErr) {
|
|
197
|
+
logger.warn("Unhandled-rejection interceptor threw; continuing with fatal path", {
|
|
198
|
+
err: interceptorErr,
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
}
|
|
175
202
|
process.stderr.write(formatFatalError("Unhandled Rejection", err));
|
|
176
203
|
logger.error("Unhandled rejection", { err });
|
|
177
204
|
await runCleanup(Reason.UNHANDLED_REJECTION);
|
package/src/procmgr.ts
CHANGED
|
@@ -2,7 +2,7 @@ import * as fs from "node:fs";
|
|
|
2
2
|
import * as path from "node:path";
|
|
3
3
|
import { Process, ProcessStatus } from "@oh-my-pi/pi-natives";
|
|
4
4
|
import type { Subprocess } from "bun";
|
|
5
|
-
import { $env,
|
|
5
|
+
import { $env, filterChildShellEnv } from "./env";
|
|
6
6
|
import { $which } from "./which";
|
|
7
7
|
|
|
8
8
|
export interface ShellConfig {
|
|
@@ -31,7 +31,7 @@ export function isExecutable(path: string): boolean {
|
|
|
31
31
|
function buildSpawnEnv(shell: string): Record<string, string> {
|
|
32
32
|
const noCI = $env.PI_BASH_NO_CI || $env.CLAUDE_BASH_NO_CI;
|
|
33
33
|
return {
|
|
34
|
-
...
|
|
34
|
+
...filterChildShellEnv(Bun.env),
|
|
35
35
|
SHELL: shell,
|
|
36
36
|
GIT_EDITOR: "true",
|
|
37
37
|
GPG_TTY: "not a tty",
|