@oh-my-pi/pi-utils 17.3.7 → 17.4.0
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 +6 -0
- package/dist/types/binary.d.ts +6 -0
- package/dist/types/dirs.d.ts +6 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/sqlite.d.ts +23 -0
- package/package.json +2 -2
- package/src/binary.ts +6 -2
- package/src/dirs.ts +17 -2
- package/src/index.ts +1 -0
- package/src/sqlite.ts +33 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
## [Unreleased]
|
|
4
4
|
|
|
5
|
+
## [17.3.8] - 2026-08-19
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Exported `BINARY_SNIFF_BYTES`, the header window `isProbablyBinary` sniffs, so a caller holding the whole file in memory can classify the identical prefix through `isProbablyBinaryHeader` instead of reopening the file.
|
|
10
|
+
|
|
5
11
|
## [17.3.5] - 2026-08-16
|
|
6
12
|
|
|
7
13
|
### Fixed
|
package/dist/types/binary.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Header window sniffed for the binary heuristic; mirrors git's 8000-byte scan.
|
|
3
|
+
* Exported so callers that already hold the whole file in memory can sniff the
|
|
4
|
+
* identical prefix through {@link isProbablyBinaryHeader} instead of reopening.
|
|
5
|
+
*/
|
|
6
|
+
export declare const BINARY_SNIFF_BYTES = 8192;
|
|
1
7
|
/**
|
|
2
8
|
* Classify an in-memory byte header as binary (non-UTF-8-text).
|
|
3
9
|
*
|
package/dist/types/dirs.d.ts
CHANGED
|
@@ -181,6 +181,8 @@ export declare function getGpuCachePath(): string;
|
|
|
181
181
|
* cache file without touching the rest of the config root.
|
|
182
182
|
*/
|
|
183
183
|
export declare function getGithubCacheDbPath(): string;
|
|
184
|
+
/** Get the legacy Pi extension parse cache database path. */
|
|
185
|
+
export declare function getLegacyPiExtensionCacheDbPath(): string;
|
|
184
186
|
/**
|
|
185
187
|
* Get the encrypted auth-broker snapshot cache path (~/.omp/cache/auth-broker-snapshot.enc).
|
|
186
188
|
* Honors the `OMP_AUTH_BROKER_SNAPSHOT_CACHE` env var when set so tests and
|
|
@@ -243,8 +245,12 @@ export declare function getCrashLogPath(agentDir?: string): string;
|
|
|
243
245
|
export declare function getDebugLogPath(agentDir?: string): string;
|
|
244
246
|
/** Get the secret placeholder key path (~/.omp/agent/secret-placeholder.key; XDG default: $XDG_STATE_HOME/omp/secret-placeholder.key). Adopts a legacy key on first XDG resolution. */
|
|
245
247
|
export declare function getSecretPlaceholderKeyPath(): string;
|
|
248
|
+
/** Root directory containing every per-project daemon runtime scope (~/.omp/run/daemons; XDG default: $XDG_STATE_HOME/omp/run/daemons). */
|
|
249
|
+
export declare function getDaemonRuntimeRoot(): string;
|
|
246
250
|
/** Get the daemon runtime directory for a project (~/.omp/run/daemons/<hash>; XDG default: $XDG_STATE_HOME/omp/run/daemons/<hash>). */
|
|
247
251
|
export declare function getDaemonRuntimeDir(projectDir: string): string;
|
|
252
|
+
/** Root directory containing every machine-global daemon service scope. */
|
|
253
|
+
export declare function getGlobalDaemonRuntimeRoot(): string;
|
|
248
254
|
/** Get a profile-independent runtime directory for a machine-global daemon service. */
|
|
249
255
|
export declare function getGlobalDaemonRuntimeDir(service: string): string;
|
|
250
256
|
/** Get the provider in-flight root directory (~/.omp/run/provider-inflight; XDG default: $XDG_STATE_HOME/omp/run/provider-inflight). */
|
package/dist/types/index.d.ts
CHANGED
|
@@ -28,6 +28,7 @@ export { AbortError, ChildProcess, Exception, NonZeroExitError } from "./ptree.j
|
|
|
28
28
|
export * from "./runtime-install.js";
|
|
29
29
|
export * from "./sanitize-text.js";
|
|
30
30
|
export * from "./snowflake.js";
|
|
31
|
+
export * from "./sqlite.js";
|
|
31
32
|
export * from "./stderr-guard.js";
|
|
32
33
|
export * from "./stream.js";
|
|
33
34
|
export * from "./tab-spacing.js";
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared classifiers for `bun:sqlite` error result codes.
|
|
3
|
+
*
|
|
4
|
+
* Every omp SQLite store (`agent.db` credential/usage store, `models.db` model
|
|
5
|
+
* cache, `history.db`) needs the same two distinctions: a transient BUSY that
|
|
6
|
+
* clears by retrying, and an unrecoverable corruption that never does. Keeping
|
|
7
|
+
* one implementation here prevents the classifiers from drifting between the
|
|
8
|
+
* credential store and the model cache.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* SQLite's busy result-code family — base `SQLITE_BUSY` plus the extended
|
|
12
|
+
* variants `SQLITE_BUSY_RECOVERY` (concurrent WAL recovery), `SQLITE_BUSY_SNAPSHOT`,
|
|
13
|
+
* and `SQLITE_BUSY_TIMEOUT`. All warrant the same backoff-and-retry treatment.
|
|
14
|
+
*/
|
|
15
|
+
export declare function isSqliteBusyError(err: unknown): boolean;
|
|
16
|
+
/**
|
|
17
|
+
* SQLite's unrecoverable-corruption result codes — the `SQLITE_CORRUPT` family
|
|
18
|
+
* (base plus extended variants like `SQLITE_CORRUPT_VTAB` / `SQLITE_CORRUPT_INDEX`)
|
|
19
|
+
* and `SQLITE_NOTADB` (the file header is not a database). Unlike
|
|
20
|
+
* {@link isSqliteBusyError}, these never clear by retrying: the store must be
|
|
21
|
+
* repaired or replaced, so callers latch, quarantine, or recreate the file.
|
|
22
|
+
*/
|
|
23
|
+
export declare function isSqliteCorruptionError(err: unknown): boolean;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@oh-my-pi/pi-utils",
|
|
4
|
-
"version": "17.
|
|
4
|
+
"version": "17.4.0",
|
|
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": "17.
|
|
34
|
+
"@oh-my-pi/pi-natives": "17.4.0"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@types/bun": "^1.3.14"
|
package/src/binary.ts
CHANGED
|
@@ -14,8 +14,12 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { peekFile, peekFileSync } from "./peek-file";
|
|
16
16
|
|
|
17
|
-
/**
|
|
18
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Header window sniffed for the binary heuristic; mirrors git's 8000-byte scan.
|
|
19
|
+
* Exported so callers that already hold the whole file in memory can sniff the
|
|
20
|
+
* identical prefix through {@link isProbablyBinaryHeader} instead of reopening.
|
|
21
|
+
*/
|
|
22
|
+
export const BINARY_SNIFF_BYTES = 8192;
|
|
19
23
|
|
|
20
24
|
/**
|
|
21
25
|
* Classify an in-memory byte header as binary (non-UTF-8-text).
|
package/src/dirs.ts
CHANGED
|
@@ -678,6 +678,11 @@ export function getGithubCacheDbPath(): string {
|
|
|
678
678
|
return dirs.rootSubdir(path.join("cache", "github-cache.db"), "cache");
|
|
679
679
|
}
|
|
680
680
|
|
|
681
|
+
/** Get the legacy Pi extension parse cache database path. */
|
|
682
|
+
export function getLegacyPiExtensionCacheDbPath(): string {
|
|
683
|
+
return dirs.rootSubdir(path.join("cache", "legacy-pi-extension-cache.db"), "cache");
|
|
684
|
+
}
|
|
685
|
+
|
|
681
686
|
/**
|
|
682
687
|
* Get the encrypted auth-broker snapshot cache path (~/.omp/cache/auth-broker-snapshot.enc).
|
|
683
688
|
* Honors the `OMP_AUTH_BROKER_SNAPSHOT_CACHE` env var when set so tests and
|
|
@@ -854,10 +859,20 @@ export function getSecretPlaceholderKeyPath(): string {
|
|
|
854
859
|
return keyPath;
|
|
855
860
|
}
|
|
856
861
|
|
|
862
|
+
/** Root directory containing every per-project daemon runtime scope (~/.omp/run/daemons; XDG default: $XDG_STATE_HOME/omp/run/daemons). */
|
|
863
|
+
export function getDaemonRuntimeRoot(): string {
|
|
864
|
+
return dirs.rootSubdir(path.join("run", "daemons"), "state");
|
|
865
|
+
}
|
|
866
|
+
|
|
857
867
|
/** Get the daemon runtime directory for a project (~/.omp/run/daemons/<hash>; XDG default: $XDG_STATE_HOME/omp/run/daemons/<hash>). */
|
|
858
868
|
export function getDaemonRuntimeDir(projectDir: string): string {
|
|
859
869
|
const key = Bun.hash.wyhash(path.resolve(projectDir)).toString(16).padStart(16, "0");
|
|
860
|
-
return
|
|
870
|
+
return path.join(getDaemonRuntimeRoot(), key);
|
|
871
|
+
}
|
|
872
|
+
|
|
873
|
+
/** Root directory containing every machine-global daemon service scope. */
|
|
874
|
+
export function getGlobalDaemonRuntimeRoot(): string {
|
|
875
|
+
return path.join(getBaseConfigRoot(), "run", "daemons", "global");
|
|
861
876
|
}
|
|
862
877
|
|
|
863
878
|
/** Get a profile-independent runtime directory for a machine-global daemon service. */
|
|
@@ -865,7 +880,7 @@ export function getGlobalDaemonRuntimeDir(service: string): string {
|
|
|
865
880
|
if (!/^[a-z0-9][a-z0-9._-]*$/i.test(service)) {
|
|
866
881
|
throw new Error(`Invalid global daemon service name: ${JSON.stringify(service)}`);
|
|
867
882
|
}
|
|
868
|
-
return path.join(
|
|
883
|
+
return path.join(getGlobalDaemonRuntimeRoot(), service);
|
|
869
884
|
}
|
|
870
885
|
|
|
871
886
|
/** Get the provider in-flight root directory (~/.omp/run/provider-inflight; XDG default: $XDG_STATE_HOME/omp/run/provider-inflight). */
|
package/src/index.ts
CHANGED
|
@@ -28,6 +28,7 @@ export { AbortError, ChildProcess, Exception, NonZeroExitError } from "./ptree";
|
|
|
28
28
|
export * from "./runtime-install";
|
|
29
29
|
export * from "./sanitize-text";
|
|
30
30
|
export * from "./snowflake";
|
|
31
|
+
export * from "./sqlite";
|
|
31
32
|
export * from "./stderr-guard";
|
|
32
33
|
export * from "./stream";
|
|
33
34
|
export * from "./tab-spacing";
|
package/src/sqlite.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared classifiers for `bun:sqlite` error result codes.
|
|
3
|
+
*
|
|
4
|
+
* Every omp SQLite store (`agent.db` credential/usage store, `models.db` model
|
|
5
|
+
* cache, `history.db`) needs the same two distinctions: a transient BUSY that
|
|
6
|
+
* clears by retrying, and an unrecoverable corruption that never does. Keeping
|
|
7
|
+
* one implementation here prevents the classifiers from drifting between the
|
|
8
|
+
* credential store and the model cache.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* SQLite's busy result-code family — base `SQLITE_BUSY` plus the extended
|
|
13
|
+
* variants `SQLITE_BUSY_RECOVERY` (concurrent WAL recovery), `SQLITE_BUSY_SNAPSHOT`,
|
|
14
|
+
* and `SQLITE_BUSY_TIMEOUT`. All warrant the same backoff-and-retry treatment.
|
|
15
|
+
*/
|
|
16
|
+
export function isSqliteBusyError(err: unknown): boolean {
|
|
17
|
+
if (err === null || typeof err !== "object" || !("code" in err)) return false;
|
|
18
|
+
const code = err.code;
|
|
19
|
+
return typeof code === "string" && code.startsWith("SQLITE_BUSY");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* SQLite's unrecoverable-corruption result codes — the `SQLITE_CORRUPT` family
|
|
24
|
+
* (base plus extended variants like `SQLITE_CORRUPT_VTAB` / `SQLITE_CORRUPT_INDEX`)
|
|
25
|
+
* and `SQLITE_NOTADB` (the file header is not a database). Unlike
|
|
26
|
+
* {@link isSqliteBusyError}, these never clear by retrying: the store must be
|
|
27
|
+
* repaired or replaced, so callers latch, quarantine, or recreate the file.
|
|
28
|
+
*/
|
|
29
|
+
export function isSqliteCorruptionError(err: unknown): boolean {
|
|
30
|
+
if (err === null || typeof err !== "object" || !("code" in err)) return false;
|
|
31
|
+
const code = err.code;
|
|
32
|
+
return typeof code === "string" && (code.startsWith("SQLITE_CORRUPT") || code === "SQLITE_NOTADB");
|
|
33
|
+
}
|