@oh-my-pi/pi-utils 16.2.5 → 16.2.7
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/dist/types/binary.d.ts +17 -0
- package/dist/types/index.d.ts +2 -0
- package/dist/types/path.d.ts +2 -0
- package/package.json +2 -2
- package/src/binary.ts +50 -0
- package/src/index.ts +2 -0
- package/src/path.ts +28 -0
- package/src/worker-host.ts +3 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [16.2.7] - 2026-06-30
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added a utility to detect binary files based on content sniffing.
|
|
10
|
+
|
|
11
|
+
## [16.2.6] - 2026-06-29
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- Added `stripWindowsExtendedLengthPathPrefix()` utility to normalize `\\?\` and native Win32 path prefixes before Bun import or spawn calls.
|
|
16
|
+
|
|
5
17
|
## [16.2.3] - 2026-06-28
|
|
6
18
|
|
|
7
19
|
### Added
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Classify an in-memory byte header as binary (non-UTF-8-text).
|
|
3
|
+
*
|
|
4
|
+
* Binary when the header contains a NUL byte (true binary, plus UTF-16/UTF-32
|
|
5
|
+
* text whose ASCII range is NUL-padded) or when it is not valid UTF-8. The
|
|
6
|
+
* decode runs in streaming mode so a multibyte sequence truncated at the header
|
|
7
|
+
* boundary is tolerated, while any genuinely invalid byte still fails — matching
|
|
8
|
+
* the strict `fatal` decode the `local://`/`ssh://` read paths already use.
|
|
9
|
+
*/
|
|
10
|
+
export declare function isProbablyBinaryHeader(header: Uint8Array): boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Sniff the first {@link BINARY_SNIFF_BYTES} of `filePath` and report whether it
|
|
13
|
+
* is binary (non-UTF-8-text). See {@link isProbablyBinaryHeader} for the rule.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isProbablyBinary(filePath: string, maxBytes?: number): Promise<boolean>;
|
|
16
|
+
/** Synchronous {@link isProbablyBinary}. */
|
|
17
|
+
export declare function isProbablyBinarySync(filePath: string, maxBytes?: number): boolean;
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { once, untilAborted } from "./abortable";
|
|
2
2
|
export * from "./async";
|
|
3
|
+
export * from "./binary";
|
|
3
4
|
export * from "./color";
|
|
4
5
|
export * from "./dirs";
|
|
5
6
|
export * from "./env";
|
|
@@ -14,6 +15,7 @@ export * as logger from "./logger";
|
|
|
14
15
|
export * from "./loop-phase";
|
|
15
16
|
export * from "./mermaid-ascii";
|
|
16
17
|
export * from "./mime";
|
|
18
|
+
export * from "./path";
|
|
17
19
|
export * from "./path-tree";
|
|
18
20
|
export * from "./peek-file";
|
|
19
21
|
export * as postmortem from "./postmortem";
|
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.2.
|
|
4
|
+
"version": "16.2.7",
|
|
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.2.
|
|
34
|
+
"@oh-my-pi/pi-natives": "16.2.7",
|
|
35
35
|
"handlebars": "^4.7.9",
|
|
36
36
|
"winston": "^3.19.0",
|
|
37
37
|
"winston-daily-rotate-file": "^5.0.0"
|
package/src/binary.ts
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Content-based binary/text classification for files that are about to be
|
|
3
|
+
* decoded as UTF-8 text and shown to a model or user.
|
|
4
|
+
*
|
|
5
|
+
* The read tool and `@file` auto-read both materialize file bytes as UTF-8
|
|
6
|
+
* strings. For a binary file (font, object, archive, packed blob) that decode
|
|
7
|
+
* is lossy: NUL bytes and invalid sequences survive as control characters and
|
|
8
|
+
* U+FFFD replacements, which corrupt terminal rendering and waste the context
|
|
9
|
+
* window with mojibake. Sniff the header first and refuse instead.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* if (await isProbablyBinary(path)) return "[binary file omitted]";
|
|
13
|
+
* const text = await Bun.file(path).text();
|
|
14
|
+
*/
|
|
15
|
+
import { peekFile, peekFileSync } from "./peek-file";
|
|
16
|
+
|
|
17
|
+
/** Header window sniffed for the binary heuristic; mirrors git's 8000-byte scan. */
|
|
18
|
+
const BINARY_SNIFF_BYTES = 8192;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Classify an in-memory byte header as binary (non-UTF-8-text).
|
|
22
|
+
*
|
|
23
|
+
* Binary when the header contains a NUL byte (true binary, plus UTF-16/UTF-32
|
|
24
|
+
* text whose ASCII range is NUL-padded) or when it is not valid UTF-8. The
|
|
25
|
+
* decode runs in streaming mode so a multibyte sequence truncated at the header
|
|
26
|
+
* boundary is tolerated, while any genuinely invalid byte still fails — matching
|
|
27
|
+
* the strict `fatal` decode the `local://`/`ssh://` read paths already use.
|
|
28
|
+
*/
|
|
29
|
+
export function isProbablyBinaryHeader(header: Uint8Array): boolean {
|
|
30
|
+
if (header.indexOf(0) !== -1) return true;
|
|
31
|
+
try {
|
|
32
|
+
new TextDecoder("utf-8", { fatal: true }).decode(header, { stream: true });
|
|
33
|
+
return false;
|
|
34
|
+
} catch {
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Sniff the first {@link BINARY_SNIFF_BYTES} of `filePath` and report whether it
|
|
41
|
+
* is binary (non-UTF-8-text). See {@link isProbablyBinaryHeader} for the rule.
|
|
42
|
+
*/
|
|
43
|
+
export function isProbablyBinary(filePath: string, maxBytes = BINARY_SNIFF_BYTES): Promise<boolean> {
|
|
44
|
+
return peekFile(filePath, maxBytes, isProbablyBinaryHeader);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Synchronous {@link isProbablyBinary}. */
|
|
48
|
+
export function isProbablyBinarySync(filePath: string, maxBytes = BINARY_SNIFF_BYTES): boolean {
|
|
49
|
+
return peekFileSync(filePath, maxBytes, isProbablyBinaryHeader);
|
|
50
|
+
}
|
package/src/index.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
export { once, untilAborted } from "./abortable";
|
|
2
2
|
export * from "./async";
|
|
3
|
+
export * from "./binary";
|
|
3
4
|
export * from "./color";
|
|
4
5
|
export * from "./dirs";
|
|
5
6
|
export * from "./env";
|
|
@@ -14,6 +15,7 @@ export * as logger from "./logger";
|
|
|
14
15
|
export * from "./loop-phase";
|
|
15
16
|
export * from "./mermaid-ascii";
|
|
16
17
|
export * from "./mime";
|
|
18
|
+
export * from "./path";
|
|
17
19
|
export * from "./path-tree";
|
|
18
20
|
export * from "./peek-file";
|
|
19
21
|
export * as postmortem from "./postmortem";
|
package/src/path.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const WINDOWS_DRIVE_EXTENDED_PREFIX = /^\\\\[?]\\([A-Za-z]:[\\/].*)$/;
|
|
2
|
+
const WINDOWS_UNC_EXTENDED_PREFIX = /^\\\\[?]\\UNC[\\/]([^\\/]+)[\\/](.+)$/i;
|
|
3
|
+
const WINDOWS_DRIVE_EXTENDED_FORWARD_PREFIX = /^\/\/[?]\/([A-Za-z]:\/.*)$/;
|
|
4
|
+
const WINDOWS_UNC_EXTENDED_FORWARD_PREFIX = /^\/\/[?]\/UNC\/([^/]+)\/(.+)$/i;
|
|
5
|
+
const WINDOWS_DRIVE_NT_PREFIX = /^\\\\[?][?]\\([A-Za-z]:[\\/].*)$/;
|
|
6
|
+
const WINDOWS_UNC_NT_PREFIX = /^\\\\[?][?]\\UNC[\\/]([^\\/]+)[\\/](.+)$/i;
|
|
7
|
+
|
|
8
|
+
/** Removes Win32 extended-length prefixes before passing paths to Bun APIs. */
|
|
9
|
+
export function stripWindowsExtendedLengthPathPrefix(
|
|
10
|
+
filePath: string,
|
|
11
|
+
platform: NodeJS.Platform = process.platform,
|
|
12
|
+
): string {
|
|
13
|
+
if (platform !== "win32") return filePath;
|
|
14
|
+
|
|
15
|
+
const uncMatch = WINDOWS_UNC_EXTENDED_PREFIX.exec(filePath) ?? WINDOWS_UNC_NT_PREFIX.exec(filePath);
|
|
16
|
+
if (uncMatch) return `\\\\${uncMatch[1]}\\${uncMatch[2]}`;
|
|
17
|
+
|
|
18
|
+
const driveMatch = WINDOWS_DRIVE_EXTENDED_PREFIX.exec(filePath) ?? WINDOWS_DRIVE_NT_PREFIX.exec(filePath);
|
|
19
|
+
if (driveMatch) return driveMatch[1];
|
|
20
|
+
|
|
21
|
+
const forwardUncMatch = WINDOWS_UNC_EXTENDED_FORWARD_PREFIX.exec(filePath);
|
|
22
|
+
if (forwardUncMatch) return `//${forwardUncMatch[1]}/${forwardUncMatch[2]}`;
|
|
23
|
+
|
|
24
|
+
const forwardDriveMatch = WINDOWS_DRIVE_EXTENDED_FORWARD_PREFIX.exec(filePath);
|
|
25
|
+
if (forwardDriveMatch) return forwardDriveMatch[1];
|
|
26
|
+
|
|
27
|
+
return filePath;
|
|
28
|
+
}
|
package/src/worker-host.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { stripWindowsExtendedLengthPathPrefix } from "./path";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* Main-module path declared by self-dispatching CLI entrypoints — entries
|
|
3
5
|
* whose top-level argv handling routes hidden `__omp_*` worker selectors.
|
|
@@ -10,7 +12,7 @@ let workerHostMain: string | null = null;
|
|
|
10
12
|
|
|
11
13
|
/** Called by CLI entrypoints whose main module dispatches worker argv selectors. */
|
|
12
14
|
export function declareWorkerHostEntry(): void {
|
|
13
|
-
workerHostMain = Bun.main;
|
|
15
|
+
workerHostMain = stripWindowsExtendedLengthPathPrefix(Bun.main);
|
|
14
16
|
}
|
|
15
17
|
|
|
16
18
|
/** Main-module path of the self-dispatching CLI host, or null outside it. */
|