@oh-my-pi/pi-natives 18.10.4 → 18.11.1
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/native/index.d.ts +24 -1
- package/native/loader-state.js +13 -7
- package/native/vcs.d.ts +3 -0
- package/native/vcs.js +53 -0
- package/package.json +7 -7
package/native/index.d.ts
CHANGED
|
@@ -2058,7 +2058,10 @@ export interface GrepOptions {
|
|
|
2058
2058
|
pattern: string
|
|
2059
2059
|
/** Directory or file to search: a host path or an absolute `scheme://` URL. */
|
|
2060
2060
|
path: string
|
|
2061
|
-
/**
|
|
2061
|
+
/**
|
|
2062
|
+
* Glob filter for file paths (e.g., "*.ts"); a matched directory selects
|
|
2063
|
+
* every file under it.
|
|
2064
|
+
*/
|
|
2062
2065
|
glob?: string
|
|
2063
2066
|
/**
|
|
2064
2067
|
* Match simple glob patterns at any depth (default: true; `*.ts` ->
|
|
@@ -2459,6 +2462,13 @@ export interface ListWorkspaceOptions {
|
|
|
2459
2462
|
* to find them. Default: false.
|
|
2460
2463
|
*/
|
|
2461
2464
|
collectAgentsMd?: boolean
|
|
2465
|
+
/**
|
|
2466
|
+
* Report unreadable directories instead of silently skipping them: an
|
|
2467
|
+
* unreadable root fails the scan, and unreadable subdirectories are
|
|
2468
|
+
* returned in `unreadableDirectories` while the walk continues. Default:
|
|
2469
|
+
* false (startup discovery stays best-effort).
|
|
2470
|
+
*/
|
|
2471
|
+
reportDirectoryErrors?: boolean
|
|
2462
2472
|
/** Timeout in milliseconds for the operation. */
|
|
2463
2473
|
timeoutMs?: number
|
|
2464
2474
|
/** Abort signal for cancelling the operation. */
|
|
@@ -2476,6 +2486,11 @@ export interface ListWorkspaceResult {
|
|
|
2476
2486
|
agentsMdFiles: Array<string>
|
|
2477
2487
|
/** True when any output cap was hit. */
|
|
2478
2488
|
truncated: boolean
|
|
2489
|
+
/**
|
|
2490
|
+
* Subdirectories whose contents could not be listed. Always empty unless
|
|
2491
|
+
* `reportDirectoryErrors` is set.
|
|
2492
|
+
*/
|
|
2493
|
+
unreadableDirectories: Array<WorkspaceDirectoryError>
|
|
2479
2494
|
}
|
|
2480
2495
|
|
|
2481
2496
|
/**
|
|
@@ -3908,6 +3923,14 @@ export interface WorkProfile {
|
|
|
3908
3923
|
sampleCount: number
|
|
3909
3924
|
}
|
|
3910
3925
|
|
|
3926
|
+
/** A subdirectory the scan could not list. */
|
|
3927
|
+
export interface WorkspaceDirectoryError {
|
|
3928
|
+
/** Forward-slash path relative to the scan root. */
|
|
3929
|
+
path: string
|
|
3930
|
+
/** Platform error, e.g. `Permission denied (os error 13)`. */
|
|
3931
|
+
message: string
|
|
3932
|
+
}
|
|
3933
|
+
|
|
3911
3934
|
/**
|
|
3912
3935
|
* Wrap text to a visible width, preserving ANSI escape codes across line
|
|
3913
3936
|
* breaks.
|
package/native/loader-state.js
CHANGED
|
@@ -499,13 +499,11 @@ export function extractEmbeddedAddons({ files, targetDir }) {
|
|
|
499
499
|
return writtenPaths;
|
|
500
500
|
}
|
|
501
501
|
|
|
502
|
-
function maybeExtractEmbeddedAddon(ctx, errors) {
|
|
502
|
+
function maybeExtractEmbeddedAddon(ctx, errors, file = selectEmbeddedAddonFile(ctx.selectedVariant)) {
|
|
503
503
|
if (!ctx.isCompiledBinary || !embeddedAddon) return null;
|
|
504
504
|
if (embeddedAddon.platformTag !== ctx.platformTag || embeddedAddon.version !== ctx.packageVersion) return null;
|
|
505
|
-
|
|
506
|
-
const
|
|
507
|
-
if (!selectedEmbeddedFile) return null;
|
|
508
|
-
const targetPath = path.join(ctx.versionedDir, selectedEmbeddedFile.filename);
|
|
505
|
+
if (!file) return null;
|
|
506
|
+
const targetPath = path.join(ctx.versionedDir, file.filename);
|
|
509
507
|
|
|
510
508
|
startupMarker("native:extractEmbeddedAddon:start");
|
|
511
509
|
try {
|
|
@@ -517,11 +515,11 @@ function maybeExtractEmbeddedAddon(ctx, errors) {
|
|
|
517
515
|
}
|
|
518
516
|
|
|
519
517
|
try {
|
|
520
|
-
extractEmbeddedAddons({ files:
|
|
518
|
+
extractEmbeddedAddons({ files: [file], targetDir: ctx.versionedDir });
|
|
521
519
|
return targetPath;
|
|
522
520
|
} catch (err) {
|
|
523
521
|
const message = err instanceof Error ? err.message : String(err);
|
|
524
|
-
errors.push(`embedded addon extraction (${
|
|
522
|
+
errors.push(`embedded addon extraction (${file.filename}): ${message}`);
|
|
525
523
|
return null;
|
|
526
524
|
}
|
|
527
525
|
}
|
|
@@ -866,8 +864,16 @@ export function loadNative() {
|
|
|
866
864
|
const stagedCandidate = embeddedCandidate ? null : maybeStageNodeModulesAddon(ctx, errors);
|
|
867
865
|
const prepended = [embeddedCandidate, stagedCandidate].filter(c => typeof c === "string");
|
|
868
866
|
const runtimeCandidates = prepended.length > 0 ? [...prepended, ...ctx.candidates] : ctx.candidates;
|
|
867
|
+
const fallbackEmbeddedFile =
|
|
868
|
+
ctx.selectedVariant === "modern" && embeddedAddon
|
|
869
|
+
? embeddedAddon.files.find(file => file.variant === "baseline")
|
|
870
|
+
: null;
|
|
871
|
+
const fallbackEmbeddedPath = fallbackEmbeddedFile && path.join(ctx.versionedDir, fallbackEmbeddedFile.filename);
|
|
869
872
|
|
|
870
873
|
for (const candidate of runtimeCandidates) {
|
|
874
|
+
if (fallbackEmbeddedFile && candidate === fallbackEmbeddedPath) {
|
|
875
|
+
maybeExtractEmbeddedAddon(ctx, errors, fallbackEmbeddedFile);
|
|
876
|
+
}
|
|
871
877
|
try {
|
|
872
878
|
startupMarker(`native:require:${path.basename(candidate)}`);
|
|
873
879
|
const bindings = require_(candidate);
|
package/native/vcs.d.ts
CHANGED
|
@@ -81,6 +81,9 @@ export declare function detachGitDir(
|
|
|
81
81
|
signal?: AbortSignal,
|
|
82
82
|
): Promise<"no-git" | "independent" | "detached">;
|
|
83
83
|
|
|
84
|
+
/** Preserve isolation-local Git objects in the source without changing its refs or index. */
|
|
85
|
+
export declare function copyGitObjects(isolationRoot: string, sourceRoot: string): Promise<void>;
|
|
86
|
+
|
|
84
87
|
/** Run Git's checkout hook in a new linked worktree and return its output and exit status. */
|
|
85
88
|
export declare function runPostCheckoutHook(
|
|
86
89
|
worktreeRoot: string,
|
package/native/vcs.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { $ } from "bun";
|
|
2
2
|
import * as fs from "node:fs";
|
|
3
|
+
import * as path from "node:path";
|
|
3
4
|
import { loadNative } from "./loader-state.js";
|
|
4
5
|
|
|
5
6
|
let native;
|
|
@@ -96,6 +97,58 @@ export function detachGitDir(worktreeRoot, sourceCommonDir, signal) {
|
|
|
96
97
|
return api().vcsDetachGitDir(worktreeRoot, sourceCommonDir, signal);
|
|
97
98
|
}
|
|
98
99
|
|
|
100
|
+
/**
|
|
101
|
+
* Publish `from` at `to` only once fully written: copy to a sibling temp name,
|
|
102
|
+
* then hard-link it into place (Git's own `finalize_object_file` strategy) so
|
|
103
|
+
* readers never see a partial file and an interrupted copy leaves only a
|
|
104
|
+
* `tmp_` file that `git gc` prunes. An existing `to` was itself published
|
|
105
|
+
* whole and holds the same content-addressed bytes, so it is kept.
|
|
106
|
+
*/
|
|
107
|
+
async function publishGitObjectFile(from, to) {
|
|
108
|
+
const tmp = path.join(path.dirname(to), `tmp_obj_omp_${crypto.randomUUID()}`);
|
|
109
|
+
try {
|
|
110
|
+
await fs.promises.copyFile(from, tmp, fs.constants.COPYFILE_EXCL);
|
|
111
|
+
try {
|
|
112
|
+
await fs.promises.link(tmp, to);
|
|
113
|
+
} catch (error) {
|
|
114
|
+
if (error?.code === "EEXIST") return;
|
|
115
|
+
// Filesystems without hard links: rename is still atomic, and any
|
|
116
|
+
// file it replaces holds identical content-addressed bytes.
|
|
117
|
+
if (error?.code !== "EPERM" && error?.code !== "ENOTSUP" && error?.code !== "EXDEV") throw error;
|
|
118
|
+
await fs.promises.rename(tmp, to);
|
|
119
|
+
}
|
|
120
|
+
} finally {
|
|
121
|
+
await fs.promises.rm(tmp, { force: true });
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Keep objects created in an isolated Git repository reachable after its
|
|
127
|
+
* worktree is removed, without changing the destination's refs or index.
|
|
128
|
+
* Every file is published atomically; a pack is published before its index.
|
|
129
|
+
*/
|
|
130
|
+
export async function copyGitObjects(isolationRoot, sourceRoot) {
|
|
131
|
+
const from = path.join(requireGit(isolationRoot).info().commonDir, "objects");
|
|
132
|
+
const to = path.join(requireGit(sourceRoot).info().commonDir, "objects");
|
|
133
|
+
for (const entry of await fs.promises.readdir(from, { withFileTypes: true })) {
|
|
134
|
+
if (!entry.isDirectory() || !/^[0-9a-f]{2}$/.test(entry.name)) continue;
|
|
135
|
+
await fs.promises.mkdir(path.join(to, entry.name), { recursive: true });
|
|
136
|
+
for (const name of await fs.promises.readdir(path.join(from, entry.name))) {
|
|
137
|
+
if (!/^[0-9a-f]{38,62}$/.test(name)) continue;
|
|
138
|
+
await publishGitObjectFile(path.join(from, entry.name, name), path.join(to, entry.name, name));
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
const packs = (await fs.promises.readdir(path.join(from, "pack"))).filter(name => name.startsWith("pack-"));
|
|
142
|
+
await fs.promises.mkdir(path.join(to, "pack"), { recursive: true });
|
|
143
|
+
// The index must only become visible after the pack it describes.
|
|
144
|
+
for (const name of packs.filter(name => name.endsWith(".pack"))) {
|
|
145
|
+
await publishGitObjectFile(path.join(from, "pack", name), path.join(to, "pack", name));
|
|
146
|
+
}
|
|
147
|
+
for (const name of packs.filter(name => /\.(?:idx|rev|keep|promisor|mtimes)$/.test(name))) {
|
|
148
|
+
await publishGitObjectFile(path.join(from, "pack", name), path.join(to, "pack", name));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
|
|
99
152
|
/**
|
|
100
153
|
* Run Git's checkout hook in a newly created linked worktree, using the same
|
|
101
154
|
* null old HEAD and branch-switch flag as `git worktree add`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@oh-my-pi/pi-natives",
|
|
3
|
-
"version": "18.
|
|
3
|
+
"version": "18.11.1",
|
|
4
4
|
"description": "Native Rust bindings for PDF conversion, audio, WebRTC, grep, clipboard, image processing, syntax highlighting, PTY, and shell operations via N-API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://omp.sh",
|
|
@@ -113,11 +113,11 @@
|
|
|
113
113
|
}
|
|
114
114
|
},
|
|
115
115
|
"optionalDependencies": {
|
|
116
|
-
"@oh-my-pi/pi-natives-linux-x64": "18.
|
|
117
|
-
"@oh-my-pi/pi-natives-linux-arm64": "18.
|
|
118
|
-
"@oh-my-pi/pi-natives-darwin-x64": "18.
|
|
119
|
-
"@oh-my-pi/pi-natives-darwin-arm64": "18.
|
|
120
|
-
"@oh-my-pi/pi-natives-win32-x64": "18.
|
|
121
|
-
"@oh-my-pi/pi-natives-win32-arm64": "18.
|
|
116
|
+
"@oh-my-pi/pi-natives-linux-x64": "18.11.1",
|
|
117
|
+
"@oh-my-pi/pi-natives-linux-arm64": "18.11.1",
|
|
118
|
+
"@oh-my-pi/pi-natives-darwin-x64": "18.11.1",
|
|
119
|
+
"@oh-my-pi/pi-natives-darwin-arm64": "18.11.1",
|
|
120
|
+
"@oh-my-pi/pi-natives-win32-x64": "18.11.1",
|
|
121
|
+
"@oh-my-pi/pi-natives-win32-arm64": "18.11.1"
|
|
122
122
|
}
|
|
123
123
|
}
|