pi-microsandbox 0.1.0 → 0.1.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/README.md +6 -3
- package/docs/development.md +54 -4
- package/docs/getting-started.md +21 -22
- package/docs/safety.md +8 -5
- package/extensions/pi-msb/flock.ts +94 -0
- package/extensions/pi-msb/locks.ts +5 -84
- package/native/flock/prebuilds/darwin-arm64/flock.node +0 -0
- package/native/flock/prebuilds/linux-arm64-gnu/flock.node +0 -0
- package/native/flock/prebuilds/linux-x64-gnu/flock.node +0 -0
- package/package.json +10 -7
package/README.md
CHANGED
|
@@ -46,9 +46,12 @@ same decisions every time you start it.
|
|
|
46
46
|
|
|
47
47
|
## Get started
|
|
48
48
|
|
|
49
|
-
You'll need Pi, **Node.js 22.19.0+**, and
|
|
50
|
-
|
|
51
|
-
|
|
49
|
+
You'll need Pi, **Node.js 22.19.0+**, and one of the supported host targets:
|
|
50
|
+
Apple Silicon macOS (`darwin-arm64`), GNU Linux x86_64
|
|
51
|
+
(`linux-x64-gnu`), or GNU Linux arm64 (`linux-arm64-gnu`). Live sandboxes also
|
|
52
|
+
need host virtualization support. The POSIX lock addon is bundled and installs
|
|
53
|
+
without lifecycle scripts or a compiler; keep npm optional dependencies enabled
|
|
54
|
+
for the Microsandbox platform package.
|
|
52
55
|
[Full requirements and installation help →](docs/getting-started.md)
|
|
53
56
|
|
|
54
57
|
Install the Microsandbox CLI first:
|
package/docs/development.md
CHANGED
|
@@ -12,19 +12,65 @@ To test from source without installing the npm package globally:
|
|
|
12
12
|
git clone https://github.com/hcohe/pi-microsandbox.git
|
|
13
13
|
cd pi-microsandbox
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
npm ci
|
|
15
|
+
npm ci --ignore-scripts=true
|
|
17
16
|
npm run typecheck
|
|
18
17
|
npm test
|
|
19
18
|
npm run smoke # extension-load smoke; no sandbox starts
|
|
20
19
|
npm run check # all three commands above
|
|
21
20
|
npm audit --omit=dev
|
|
22
|
-
npm pack --dry-run --json
|
|
23
21
|
```
|
|
24
22
|
|
|
25
23
|
The smoke and unit tests do not require KVM, image pulls, or a live sandbox.
|
|
26
24
|
The boot-speed check and live matrix below are explicit VM tests.
|
|
27
25
|
|
|
26
|
+
### Bundled flock addon
|
|
27
|
+
|
|
28
|
+
Consumers receive prebuilt lock addons and do not need native build tools. Only
|
|
29
|
+
contributors building or changing the addon need Python, a C compiler, and the
|
|
30
|
+
platform build tools used by node-gyp (`make` on GNU Linux or Xcode command-line
|
|
31
|
+
tools on macOS). On one of the three supported targets, run:
|
|
32
|
+
|
|
33
|
+
```sh
|
|
34
|
+
npm ci --ignore-scripts=true
|
|
35
|
+
npm run build:flock
|
|
36
|
+
npm run smoke:flock
|
|
37
|
+
npm run check
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The build writes
|
|
41
|
+
`native/flock/prebuilds/<target>/flock.node` for the current target. These
|
|
42
|
+
outputs are ignored by Git and must not be committed. CI builds
|
|
43
|
+
`darwin-arm64`, `linux-x64-gnu`, and `linux-arm64-gnu` separately on native
|
|
44
|
+
runners, then loads the same binary under Node 22.19.0 and Node 24.
|
|
45
|
+
|
|
46
|
+
### Assemble a package from CI artifacts
|
|
47
|
+
|
|
48
|
+
A complete package needs all three `flock-<target>` artifacts from one CI run.
|
|
49
|
+
Download each artifact into one empty artifact root, create a staging checkout
|
|
50
|
+
from the same commit's Git archive, then give both paths to the assembler:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
run_id=GITHUB_ACTIONS_RUN_ID
|
|
54
|
+
mkdir -p .tmp
|
|
55
|
+
artifact_root="$(mktemp -d "$PWD/.tmp/flock-artifacts.XXXXXX")"
|
|
56
|
+
staging="$(mktemp -d "$PWD/.tmp/package-staging.XXXXXX")"
|
|
57
|
+
pack_dir="$(mktemp -d "$PWD/.tmp/package-pack.XXXXXX")"
|
|
58
|
+
|
|
59
|
+
for target in darwin-arm64 linux-x64-gnu linux-arm64-gnu; do
|
|
60
|
+
gh run download "$run_id" --name "flock-$target" --dir "$artifact_root"
|
|
61
|
+
done
|
|
62
|
+
|
|
63
|
+
git archive HEAD | tar -x -C "$staging"
|
|
64
|
+
npm run assemble:package -- "$artifact_root" "$staging"
|
|
65
|
+
pack_json="$(npm pack "$staging" --json --pack-destination "$pack_dir")"
|
|
66
|
+
tarball="$(node -e 'const value=JSON.parse(process.argv[1]); const results=Array.isArray(value)?value:Object.values(value); if(results.length!==1) throw new Error(`expected one pack result, got ${results.length}`); process.stdout.write(results[0].filename)' "$pack_json")"
|
|
67
|
+
npm run package-smoke -- "$pack_dir/$tarball"
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Use artifacts built from the same commit as `HEAD`. The assembler rejects
|
|
71
|
+
missing, extra, or symlinked artifacts and keeps generated binaries out of the
|
|
72
|
+
source checkout.
|
|
73
|
+
|
|
28
74
|
## Boot speed regression test
|
|
29
75
|
|
|
30
76
|
With [`just`](https://just.systems/) installed, measure the awaited sandbox boot
|
|
@@ -98,7 +144,11 @@ canonical changelog. The first npm publication is a human-run local publish of
|
|
|
98
144
|
the reviewed tarball with interactive npm 2FA. Subsequent releases publish
|
|
99
145
|
directly to npm with OIDC only after a maintainer publishes the matching GitHub
|
|
100
146
|
Release and approves the protected `npm` GitHub Environment. Release automation
|
|
101
|
-
must not use a long-lived npm token.
|
|
147
|
+
must not use a long-lived npm token. Release CI builds every flock artifact from
|
|
148
|
+
the release commit, assembles a temporary staging tree, records each binary's
|
|
149
|
+
SHA-256, smoke-tests the exact tarball on every supported target, and packs only
|
|
150
|
+
once. The publish job downloads and publishes those verified bytes without
|
|
151
|
+
repacking.
|
|
102
152
|
|
|
103
153
|
The sandbox image workflow publishes all six AMD64 and ARM64 variants to
|
|
104
154
|
`ghcr.io/hcohe/pi-microsandbox`. An `image-vX.Y.Z` Git tag publishes the
|
package/docs/getting-started.md
CHANGED
|
@@ -9,28 +9,27 @@ require one of these hosts:
|
|
|
9
9
|
|
|
10
10
|
| Host | Architecture | Virtualization requirement |
|
|
11
11
|
| --- | --- | --- |
|
|
12
|
-
| macOS | Apple Silicon (arm64) | Apple virtualization support available to the process |
|
|
13
|
-
| Linux | x86_64 or arm64 (
|
|
14
|
-
|
|
15
|
-
Windows
|
|
16
|
-
microsandbox runtime has preview Windows support, but this package
|
|
17
|
-
|
|
18
|
-
KVM passthrough or nested virtualization; many hosted
|
|
19
|
-
provide it. Package loading and non-live tests do not
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
virtualization requirement.
|
|
12
|
+
| macOS | Apple Silicon (`darwin-arm64`) | Apple virtualization support available to the process |
|
|
13
|
+
| GNU Linux | x86_64 (`linux-x64-gnu`) or arm64 (`linux-arm64-gnu`) | KVM enabled, with `/dev/kvm` accessible to the process |
|
|
14
|
+
|
|
15
|
+
Windows, Intel macOS, and musl Linux are not supported by pi-microsandbox. The
|
|
16
|
+
upstream microsandbox runtime has preview Windows support, but this package
|
|
17
|
+
deliberately supports only the three targets above. A Linux container or
|
|
18
|
+
virtual machine also needs KVM passthrough or nested virtualization; many hosted
|
|
19
|
+
environments do not provide it. Package loading and non-live tests do not
|
|
20
|
+
require virtualization.
|
|
21
|
+
|
|
22
|
+
pi-microsandbox includes a prebuilt POSIX lock addon for each supported target.
|
|
23
|
+
It is loaded lazily when an owner lock is first needed. Consumer installation
|
|
24
|
+
does not compile native code or require Python, a C/C++ toolchain, or npm
|
|
25
|
+
lifecycle scripts; installation with scripts disabled is supported.
|
|
26
|
+
|
|
27
|
+
Keep optional dependencies enabled. `microsandbox@0.6.16` supplies its matching
|
|
28
|
+
native addon and runtime binaries through an optional platform package. If that
|
|
29
|
+
platform package is missing, reinstall with optional dependencies enabled,
|
|
30
|
+
install the matching Microsandbox platform package, or set `MSB_PATH` to a
|
|
31
|
+
working `msb` binary. These alternatives do not remove the host virtualization
|
|
32
|
+
requirement.
|
|
34
33
|
|
|
35
34
|
## Install
|
|
36
35
|
|
package/docs/safety.md
CHANGED
|
@@ -19,11 +19,14 @@ The default is fail-closed:
|
|
|
19
19
|
after a sandbox failure and is shown as `MSB host fallback`.
|
|
20
20
|
- A project cannot replace another process's sandbox: ownership is a
|
|
21
21
|
non-blocking kernel `flock` acquired before any sandbox or volume mutation.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
22
|
+
The small bundled POSIX addon is loaded lazily, has no install script, and
|
|
23
|
+
never falls back to a racy PID check. Stale sandbox pruning never removes
|
|
24
|
+
volumes.
|
|
25
|
+
|
|
26
|
+
The extension entry point does not import the native SDK or load the flock
|
|
27
|
+
addon. Unsupported hosts can still load Pi and remain blocked or explicitly
|
|
28
|
+
off. pi-microsandbox supports Apple Silicon macOS and GNU Linux x86_64 or arm64
|
|
29
|
+
with KVM; Windows, Intel macOS, and musl Linux are not supported.
|
|
27
30
|
|
|
28
31
|
## Host-read exceptions
|
|
29
32
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { fileURLToPath } from "node:url";
|
|
3
|
+
|
|
4
|
+
export type FlockOperation = "exnb" | "un";
|
|
5
|
+
export type FlockTarget = "darwin-arm64" | "linux-x64-gnu" | "linux-arm64-gnu";
|
|
6
|
+
|
|
7
|
+
export interface FlockRuntime {
|
|
8
|
+
platform: string;
|
|
9
|
+
arch: string;
|
|
10
|
+
glibcVersionRuntime?: unknown;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface NativeFlockBinding {
|
|
14
|
+
flock(fd: number, operation: FlockOperation): undefined;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface LoadFlockOptions {
|
|
18
|
+
runtime?: FlockRuntime;
|
|
19
|
+
requireAddon?: (absolutePath: string) => unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const SUPPORTED_TARGETS = "darwin-arm64, linux-x64-gnu, linux-arm64-gnu";
|
|
23
|
+
|
|
24
|
+
function errorMessage(error: unknown): string {
|
|
25
|
+
return error instanceof Error ? error.message : String(error);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function currentRuntime(): FlockRuntime {
|
|
29
|
+
const report = process.platform === "linux"
|
|
30
|
+
? process.report?.getReport() as { header?: { glibcVersionRuntime?: unknown } } | undefined
|
|
31
|
+
: undefined;
|
|
32
|
+
return {
|
|
33
|
+
platform: process.platform,
|
|
34
|
+
arch: process.arch,
|
|
35
|
+
glibcVersionRuntime: report?.header?.glibcVersionRuntime,
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function flockTarget(runtime: FlockRuntime): FlockTarget {
|
|
40
|
+
if (runtime.platform === "darwin" && runtime.arch === "arm64") return "darwin-arm64";
|
|
41
|
+
if (runtime.platform === "linux" && (runtime.arch === "x64" || runtime.arch === "arm64")) {
|
|
42
|
+
if (typeof runtime.glibcVersionRuntime !== "string" || runtime.glibcVersionRuntime.length === 0) {
|
|
43
|
+
throw new Error(
|
|
44
|
+
`Bundled owner-lock addon requires glibc on Linux; libc is musl or indeterminate for linux-${runtime.arch}; `
|
|
45
|
+
+ `supported targets: ${SUPPORTED_TARGETS}; refusing to use an unsafe fallback`,
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
return `linux-${runtime.arch}-gnu`;
|
|
49
|
+
}
|
|
50
|
+
throw new Error(
|
|
51
|
+
`Bundled owner-lock addon does not support ${runtime.platform}-${runtime.arch}; `
|
|
52
|
+
+ `supported targets: ${SUPPORTED_TARGETS}; refusing to use an unsafe fallback`,
|
|
53
|
+
);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export function flockBinaryPath(target: FlockTarget): string {
|
|
57
|
+
return fileURLToPath(new URL(`../../native/flock/prebuilds/${target}/flock.node`, import.meta.url));
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function loadFlockBinding(options: LoadFlockOptions = {}): NativeFlockBinding {
|
|
61
|
+
const target = flockTarget(options.runtime ?? currentRuntime());
|
|
62
|
+
const relativePath = `native/flock/prebuilds/${target}/flock.node`;
|
|
63
|
+
const absolutePath = flockBinaryPath(target);
|
|
64
|
+
const requireAddon = options.requireAddon ?? ((path: string) => createRequire(import.meta.url)(path));
|
|
65
|
+
|
|
66
|
+
try {
|
|
67
|
+
const candidate = requireAddon(absolutePath);
|
|
68
|
+
if (typeof candidate !== "object" || candidate === null
|
|
69
|
+
|| Object.keys(candidate).length !== 1
|
|
70
|
+
|| typeof (candidate as { flock?: unknown }).flock !== "function") {
|
|
71
|
+
throw new TypeError("native binding must export only flock() as a callable property");
|
|
72
|
+
}
|
|
73
|
+
return candidate as NativeFlockBinding;
|
|
74
|
+
} catch (error) {
|
|
75
|
+
throw new Error(
|
|
76
|
+
`Unable to load bundled owner-lock addon for ${target} from ${relativePath}; `
|
|
77
|
+
+ `refusing to use an unsafe fallback: ${errorMessage(error)}`,
|
|
78
|
+
{ cause: error },
|
|
79
|
+
);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let binding: NativeFlockBinding | undefined;
|
|
84
|
+
|
|
85
|
+
export async function flock(fd: number, operation: FlockOperation): Promise<void> {
|
|
86
|
+
if (!Number.isInteger(fd) || fd < 0 || fd > 0x7fff_ffff) {
|
|
87
|
+
throw new TypeError("file descriptor must be a non-negative integer");
|
|
88
|
+
}
|
|
89
|
+
if (operation !== "exnb" && operation !== "un") {
|
|
90
|
+
throw new TypeError('operation must be "exnb" or "un"');
|
|
91
|
+
}
|
|
92
|
+
binding ??= loadFlockBinding();
|
|
93
|
+
binding.flock(fd, operation);
|
|
94
|
+
}
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { chmod, mkdir, open, readFile } from "node:fs/promises";
|
|
2
2
|
import { isAbsolute, join } from "node:path";
|
|
3
3
|
|
|
4
|
+
import { flock as bundledFlock } from "./flock.ts";
|
|
4
5
|
import { LOCKFILE_VERSION, resourceId } from "./types.ts";
|
|
5
6
|
import type { LockHandle, LockInfo, LocksPort } from "./types.ts";
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* The hooks are deliberately part of the options shape so unit tests can exercise
|
|
9
10
|
* the lifecycle without loading the native addon. Production callers leave them
|
|
10
|
-
* unset and use
|
|
11
|
+
* unset and use the lazy bundled binding.
|
|
11
12
|
*/
|
|
12
13
|
export type FlockFn = (fd: number, operation: "exnb" | "un") => Promise<void>;
|
|
13
14
|
|
|
@@ -18,25 +19,6 @@ export interface LocksOptions {
|
|
|
18
19
|
unlock?: (fd: number) => Promise<void>;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
|
-
type FsExtCallback = (
|
|
22
|
-
fd: number,
|
|
23
|
-
operation: string,
|
|
24
|
-
callback: (error?: unknown) => void,
|
|
25
|
-
) => void;
|
|
26
|
-
type FsExtUnlockCallback = (fd: number, callback: (error?: unknown) => void) => void;
|
|
27
|
-
type FsExtModule = {
|
|
28
|
-
flock?: FsExtCallback;
|
|
29
|
-
unlock?: FsExtUnlockCallback;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
let fsExtPromise: Promise<FsExtModule> | undefined;
|
|
33
|
-
|
|
34
|
-
// Keep the native dependency genuinely lazy and let extension-load/type-only
|
|
35
|
-
// environments operate without resolving the optional native module.
|
|
36
|
-
function importNativeModule(specifier: string): Promise<unknown> {
|
|
37
|
-
return import(specifier);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
22
|
function errorCode(error: unknown): string | undefined {
|
|
41
23
|
if (typeof error === "object" && error !== null && "code" in error) {
|
|
42
24
|
const code = (error as { code?: unknown }).code;
|
|
@@ -49,77 +31,16 @@ function errorMessage(error: unknown): string {
|
|
|
49
31
|
return error instanceof Error ? error.message : String(error);
|
|
50
32
|
}
|
|
51
33
|
|
|
52
|
-
function unsupportedPlatformError(): Error {
|
|
53
|
-
return new Error(
|
|
54
|
-
"pi-microsandbox owner locks require POSIX flock(2) via fs-ext; this platform is unsupported (Windows LockFileEx is not implemented)",
|
|
55
|
-
);
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
async function loadFsExt(): Promise<FsExtModule> {
|
|
59
|
-
if (process.platform === "win32") throw unsupportedPlatformError();
|
|
60
|
-
fsExtPromise ??= importNativeModule("fs-ext").then((module) => {
|
|
61
|
-
const defaultExport = (module as unknown as { default?: unknown }).default;
|
|
62
|
-
const candidate = (defaultExport ?? module) as FsExtModule;
|
|
63
|
-
if (typeof candidate.flock !== "function") {
|
|
64
|
-
throw new Error("fs-ext loaded without flock(); refusing to use a racy PID fallback");
|
|
65
|
-
}
|
|
66
|
-
return candidate;
|
|
67
|
-
});
|
|
68
|
-
return fsExtPromise;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
function callbackFlock(flock: FsExtCallback, fd: number, operation: string): Promise<void> {
|
|
72
|
-
return new Promise((resolve, reject) => {
|
|
73
|
-
try {
|
|
74
|
-
flock(fd, operation, (error) => (error ? reject(error) : resolve()));
|
|
75
|
-
} catch (error) {
|
|
76
|
-
reject(error);
|
|
77
|
-
}
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
function callbackUnlock(unlock: FsExtUnlockCallback, fd: number): Promise<void> {
|
|
82
|
-
return new Promise((resolve, reject) => {
|
|
83
|
-
try {
|
|
84
|
-
unlock(fd, (error) => (error ? reject(error) : resolve()));
|
|
85
|
-
} catch (error) {
|
|
86
|
-
reject(error);
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
|
|
91
34
|
interface LockOperations {
|
|
92
35
|
flock(fd: number): Promise<void>;
|
|
93
36
|
unlock(fd: number): Promise<void>;
|
|
94
37
|
}
|
|
95
38
|
|
|
96
39
|
async function lockOperations(opts: LocksOptions): Promise<LockOperations> {
|
|
97
|
-
|
|
98
|
-
return {
|
|
99
|
-
flock: (fd) => opts.flock!(fd, "exnb"),
|
|
100
|
-
unlock: (fd) => opts.unlock ? opts.unlock(fd) : opts.flock!(fd, "un"),
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
let module: FsExtModule;
|
|
105
|
-
try {
|
|
106
|
-
module = await loadFsExt();
|
|
107
|
-
} catch (error) {
|
|
108
|
-
throw new Error(
|
|
109
|
-
`Unable to load fs-ext for owner locks; refusing to use a racy PID fallback: ${errorMessage(error)}`,
|
|
110
|
-
{ cause: error },
|
|
111
|
-
);
|
|
112
|
-
}
|
|
113
|
-
const flock = module.flock;
|
|
114
|
-
if (!flock) {
|
|
115
|
-
throw new Error("fs-ext does not provide flock(); refusing to use a racy PID fallback");
|
|
116
|
-
}
|
|
117
|
-
const unlock = module.unlock;
|
|
40
|
+
const flock = opts.flock ?? bundledFlock;
|
|
118
41
|
return {
|
|
119
|
-
flock: (fd) =>
|
|
120
|
-
unlock: (fd) => unlock
|
|
121
|
-
? callbackUnlock(unlock, fd)
|
|
122
|
-
: callbackFlock(flock, fd, "un"),
|
|
42
|
+
flock: (fd) => flock(fd, "exnb"),
|
|
43
|
+
unlock: (fd) => opts.unlock ? opts.unlock(fd) : flock(fd, "un"),
|
|
123
44
|
};
|
|
124
45
|
}
|
|
125
46
|
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pi-microsandbox",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "Microsandbox-backed isolation for Pi coding tools",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -33,7 +33,10 @@
|
|
|
33
33
|
"SECURITY.md",
|
|
34
34
|
"docs/*.md",
|
|
35
35
|
"extensions/pi-msb/*.ts",
|
|
36
|
-
"!extensions/pi-msb/*.test.ts"
|
|
36
|
+
"!extensions/pi-msb/*.test.ts",
|
|
37
|
+
"native/flock/prebuilds/darwin-arm64/flock.node",
|
|
38
|
+
"native/flock/prebuilds/linux-x64-gnu/flock.node",
|
|
39
|
+
"native/flock/prebuilds/linux-arm64-gnu/flock.node"
|
|
37
40
|
],
|
|
38
41
|
"pi": {
|
|
39
42
|
"extensions": [
|
|
@@ -41,16 +44,17 @@
|
|
|
41
44
|
]
|
|
42
45
|
},
|
|
43
46
|
"scripts": {
|
|
47
|
+
"build:flock": "node ./scripts/build-flock-addon.mjs",
|
|
48
|
+
"smoke:flock": "node ./scripts/smoke-flock-addon.mjs",
|
|
49
|
+
"assemble:package": "node ./scripts/assemble-package.mjs",
|
|
44
50
|
"typecheck": "tsc --noEmit",
|
|
45
51
|
"test": "node --experimental-strip-types --import ./test/setup.ts --test extensions/pi-msb/*.test.ts",
|
|
46
52
|
"smoke": "pi --no-extensions -e . --offline --list-models __pi_msb_smoke__",
|
|
47
53
|
"check": "npm run typecheck && npm test && npm run smoke",
|
|
48
54
|
"package-smoke": "./scripts/package-smoke.sh",
|
|
49
|
-
"release-check": "npm run check && npm
|
|
50
|
-
"prepublishOnly": "npm run release-check"
|
|
55
|
+
"release-check": "npm run check && npm audit --omit=dev"
|
|
51
56
|
},
|
|
52
57
|
"dependencies": {
|
|
53
|
-
"fs-ext": "2.1.1",
|
|
54
58
|
"microsandbox": "0.6.16"
|
|
55
59
|
},
|
|
56
60
|
"peerDependencies": {
|
|
@@ -61,13 +65,12 @@
|
|
|
61
65
|
"devDependencies": {
|
|
62
66
|
"@earendil-works/pi-coding-agent": "0.84.4",
|
|
63
67
|
"@earendil-works/pi-tui": "0.84.4",
|
|
64
|
-
"@types/fs-ext": "^2.0.3",
|
|
65
68
|
"@types/node": "^22.10.0",
|
|
69
|
+
"node-gyp": "12.1.0",
|
|
66
70
|
"typebox": "1.3.23",
|
|
67
71
|
"typescript": "^7.0.2"
|
|
68
72
|
},
|
|
69
73
|
"allowScripts": {
|
|
70
|
-
"fs-ext@2.1.1": true,
|
|
71
74
|
"@google/genai": false,
|
|
72
75
|
"protobufjs": false
|
|
73
76
|
}
|