@sayknow-cli/natives 0.4.7 → 0.5.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/native/index.d.ts +142 -8
- package/native/index.js +5 -1
- package/native/loader-state.d.ts +64 -2
- package/native/loader-state.js +204 -87
- package/package.json +6 -6
package/native/index.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
/* auto-generated by NAPI-RS */
|
|
2
2
|
/* eslint-disable */
|
|
3
|
+
/**
|
|
4
|
+
* macOS computer-use controller.
|
|
5
|
+
*
|
|
6
|
+
* This declaration and the named JS export are available on every platform so
|
|
7
|
+
* consumers can import them portably; the native controller itself is built
|
|
8
|
+
* only on macOS.
|
|
9
|
+
*/
|
|
3
10
|
export declare class ComputerController {
|
|
4
11
|
constructor()
|
|
5
12
|
screenshot(): ComputerScreenshot
|
|
@@ -120,7 +127,7 @@ export declare class NotificationServer {
|
|
|
120
127
|
* Create a server for `session_id` authenticated by `token`.
|
|
121
128
|
*
|
|
122
129
|
* `state_root` (when given) is where the endpoint discovery file is written
|
|
123
|
-
* (e.g. `<repo>/.
|
|
130
|
+
* (e.g. `<repo>/.skc/state`). `resolver_available` defaults to `true`.
|
|
124
131
|
*/
|
|
125
132
|
constructor(sessionId: string, token: string, stateRoot?: string | undefined | null, resolverAvailable?: boolean | undefined | null)
|
|
126
133
|
/** Register the reply callback. Must be called before [`Self::start`]. */
|
|
@@ -201,6 +208,11 @@ export declare class NotificationServer {
|
|
|
201
208
|
* Fails if not started or `frame_json` is not a valid `ServerMessage`.
|
|
202
209
|
*/
|
|
203
210
|
pushFrame(frameJson: string): void
|
|
211
|
+
/**
|
|
212
|
+
* Deliver a frame through every authenticated connection and wait for each
|
|
213
|
+
* socket writer to settle within `timeout_ms`.
|
|
214
|
+
*/
|
|
215
|
+
pushFrameAndWait(frameJson: string, timeoutMs: number): Promise<boolean>
|
|
204
216
|
/**
|
|
205
217
|
* Broadcast a TypeScript-constructed turn frame without re-parsing JSON.
|
|
206
218
|
* External frames must continue through [`Self::push_frame`] for serde
|
|
@@ -300,6 +312,15 @@ export declare class Process {
|
|
|
300
312
|
get ppid(): number | null
|
|
301
313
|
/** Launch arguments for this process. */
|
|
302
314
|
args(): Array<string>
|
|
315
|
+
/**
|
|
316
|
+
* Send `signal` only to this pinned process reference.
|
|
317
|
+
*
|
|
318
|
+
* On Linux this uses the owned pidfd; on Windows it uses the owned process
|
|
319
|
+
* handle. It deliberately never discovers descendants or signals a process
|
|
320
|
+
* group. Returns `false` when the pinned process has already exited or the
|
|
321
|
+
* operating system rejects delivery.
|
|
322
|
+
*/
|
|
323
|
+
signalRoot(signal: number): boolean
|
|
303
324
|
/**
|
|
304
325
|
* Send `signal` to this process and its descendants, children first.
|
|
305
326
|
*
|
|
@@ -377,7 +398,7 @@ export declare class RecoveryFsRoot {
|
|
|
377
398
|
*/
|
|
378
399
|
appendManaged(relativePath: string, data: Uint8Array, expectedDev: string, expectedIno: string, expectedSize: string, expectedMtimeNs: string, expectedCtimeNs: string, expectedSha256: string): RecoveryFsResult
|
|
379
400
|
/** Remove one exact managed regular file through retained authority. */
|
|
380
|
-
removeManaged(relativePath: string, expectedDev: string, expectedIno: string, expectedSize: string, expectedMtimeNs: string, expectedCtimeNs: string, expectedSha256: string):
|
|
401
|
+
removeManaged(relativePath: string, expectedDev: string, expectedIno: string, expectedSize: string, expectedMtimeNs: string, expectedCtimeNs: string, expectedSha256: string): RecoveryFsRetainedCleanupResult
|
|
381
402
|
/**
|
|
382
403
|
* Create each absent directory component beneath the retained root with
|
|
383
404
|
* owner-only security. Existing components are re-opened no-follow.
|
|
@@ -388,22 +409,22 @@ export declare class RecoveryFsRoot {
|
|
|
388
409
|
* retained root. The source identity is rechecked after the no-replace
|
|
389
410
|
* rename, and the move is rolled back on a mismatch.
|
|
390
411
|
*/
|
|
391
|
-
renameManagedFileNoReplace(sourceRelativePath: string, destinationRelativePath: string, expectedDev: string, expectedIno: string, expectedSize: string, expectedMtimeNs: string, expectedCtimeNs: string, expectedSha256: string):
|
|
412
|
+
renameManagedFileNoReplace(sourceRelativePath: string, destinationRelativePath: string, expectedDev: string, expectedIno: string, expectedSize: string, expectedMtimeNs: string, expectedCtimeNs: string, expectedSha256: string): RecoveryFsPublishResult
|
|
392
413
|
/** Snapshot a managed directory tree entirely through the retained root. */
|
|
393
414
|
snapshotManagedTree(relativePath: string): NativeDirectoryTreeResult
|
|
394
415
|
/**
|
|
395
416
|
* Move an exact managed directory tree to an absent name through retained
|
|
396
417
|
* authority.
|
|
397
418
|
*/
|
|
398
|
-
renameManagedTreeNoReplace(sourceRelativePath: string, destinationRelativePath: string, expected: NativeDirectoryTreeSnapshot):
|
|
419
|
+
renameManagedTreeNoReplace(sourceRelativePath: string, destinationRelativePath: string, expected: NativeDirectoryTreeSnapshot): RecoveryFsPublishResult
|
|
399
420
|
/** Remove an exact managed directory tree through retained authority. */
|
|
400
|
-
removeManagedTree(relativePath: string, expected: NativeDirectoryTreeSnapshot):
|
|
421
|
+
removeManagedTree(relativePath: string, expected: NativeDirectoryTreeSnapshot): RecoveryFsRetainedCleanupResult
|
|
401
422
|
/**
|
|
402
423
|
* Atomically install an already-created regular file at an absent name.
|
|
403
424
|
* Both names remain relative to this retained root and are never resolved
|
|
404
425
|
* through a pathname after their parent descriptors are acquired.
|
|
405
426
|
*/
|
|
406
|
-
install(sourceRelativePath: string, destinationRelativePath: string):
|
|
427
|
+
install(sourceRelativePath: string, destinationRelativePath: string): RecoveryFsPublishResult
|
|
407
428
|
/**
|
|
408
429
|
* Synchronize the retained root directory, making a preceding create or
|
|
409
430
|
* install durable when the filesystem supports directory fsync.
|
|
@@ -443,6 +464,15 @@ export declare class Shell {
|
|
|
443
464
|
abort(): Promise<void>
|
|
444
465
|
}
|
|
445
466
|
|
|
467
|
+
/**
|
|
468
|
+
* Publish-result wire-contract sentinel.
|
|
469
|
+
*
|
|
470
|
+
* The loader requires this in addition to the release sentinel, so a
|
|
471
|
+
* same-version modern artifact built before the retained-publish contract
|
|
472
|
+
* cannot be selected over a compatible baseline.
|
|
473
|
+
*/
|
|
474
|
+
export declare function __piNativesPublishOutcomeV1(): void
|
|
475
|
+
|
|
446
476
|
/**
|
|
447
477
|
* Version sentinel — exists solely so the JS loader can prove at load time
|
|
448
478
|
* that the `.node` file on disk is from the same package release as the
|
|
@@ -461,7 +491,7 @@ export declare class Shell {
|
|
|
461
491
|
* `packages/natives/native/index.js` (which derives the name from
|
|
462
492
|
* `package.json#version`).
|
|
463
493
|
*/
|
|
464
|
-
export declare function
|
|
494
|
+
export declare function __piNativesV0_5_0(): void
|
|
465
495
|
|
|
466
496
|
/**
|
|
467
497
|
* Apply conservative pre-execution rewrites to a bash command.
|
|
@@ -1711,6 +1741,18 @@ export interface NativeExactUnlinkResult {
|
|
|
1711
1741
|
retainedUnknownPath?: string
|
|
1712
1742
|
}
|
|
1713
1743
|
|
|
1744
|
+
/** Dedicated result for an atomic no-replace namespace publication. */
|
|
1745
|
+
export interface NativeNoReplaceResult {
|
|
1746
|
+
ok: boolean
|
|
1747
|
+
code?: string
|
|
1748
|
+
mutationState: string
|
|
1749
|
+
durabilityState: string
|
|
1750
|
+
reason: string
|
|
1751
|
+
primitive: string
|
|
1752
|
+
phase: string
|
|
1753
|
+
diagnostic: NativePublishDiagnostic
|
|
1754
|
+
}
|
|
1755
|
+
|
|
1714
1756
|
/** Result of applying or checking owner-only path security. */
|
|
1715
1757
|
export type NativeOwnerOnlySecurityResult =
|
|
1716
1758
|
| {
|
|
@@ -1856,6 +1898,8 @@ export interface PresentationLease {
|
|
|
1856
1898
|
registrationEpoch: number
|
|
1857
1899
|
}
|
|
1858
1900
|
|
|
1901
|
+
export declare function probeWindowsJobMemory(): WindowsJobMemoryProbeResult
|
|
1902
|
+
|
|
1859
1903
|
/** Current state of a process reference. */
|
|
1860
1904
|
export declare enum ProcessStatus {
|
|
1861
1905
|
/** The referenced process is still running. */
|
|
@@ -1941,6 +1985,38 @@ export interface RecoveryFsIdentity {
|
|
|
1941
1985
|
sha256?: string
|
|
1942
1986
|
}
|
|
1943
1987
|
|
|
1988
|
+
/** Bounded, path-free diagnostic evidence for one retained publication. */
|
|
1989
|
+
export interface RecoveryFsPublishDiagnostic {
|
|
1990
|
+
schemaVersion: number
|
|
1991
|
+
collectionState: string
|
|
1992
|
+
osCode?: number
|
|
1993
|
+
syncFailures?: Array<RecoveryFsPublishSyncFailure>
|
|
1994
|
+
}
|
|
1995
|
+
|
|
1996
|
+
/**
|
|
1997
|
+
* Explicit mutation and durability outcome for retained no-replace
|
|
1998
|
+
* publication.
|
|
1999
|
+
*/
|
|
2000
|
+
export interface RecoveryFsPublishResult {
|
|
2001
|
+
ok: boolean
|
|
2002
|
+
code?: string
|
|
2003
|
+
identity?: RecoveryFsIdentity
|
|
2004
|
+
mutationState: string
|
|
2005
|
+
durabilityState: string
|
|
2006
|
+
reason: string
|
|
2007
|
+
primitive: string
|
|
2008
|
+
phase: string
|
|
2009
|
+
diagnostic: RecoveryFsPublishDiagnostic
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
/** Bounded, path-free diagnostic evidence for one retained publication. */
|
|
2013
|
+
export interface RecoveryFsPublishSyncFailure {
|
|
2014
|
+
phase: string
|
|
2015
|
+
parentRole: string
|
|
2016
|
+
osCode?: number
|
|
2017
|
+
kind: string
|
|
2018
|
+
}
|
|
2019
|
+
|
|
1944
2020
|
export interface RecoveryFsResult {
|
|
1945
2021
|
ok: boolean
|
|
1946
2022
|
code?: string
|
|
@@ -1948,7 +2024,28 @@ export interface RecoveryFsResult {
|
|
|
1948
2024
|
data?: Uint8Array
|
|
1949
2025
|
}
|
|
1950
2026
|
|
|
1951
|
-
|
|
2027
|
+
/**
|
|
2028
|
+
* Fail-closed outcome for a removal whose detached object remains retained.
|
|
2029
|
+
* `recovery_path` identifies evidence only; it grants no authority to replay
|
|
2030
|
+
* or delete the retained object.
|
|
2031
|
+
*/
|
|
2032
|
+
export interface RecoveryFsRetainedCleanupResult {
|
|
2033
|
+
ok: boolean
|
|
2034
|
+
code?: string
|
|
2035
|
+
recoveryPath?: string
|
|
2036
|
+
identity?: RecoveryFsIdentity
|
|
2037
|
+
treeSnapshot?: NativeDirectoryTreeSnapshot
|
|
2038
|
+
}
|
|
2039
|
+
|
|
2040
|
+
export declare function renameNoReplacePath(sourcePath: string, destinationPath: string): NativeNoReplaceResult
|
|
2041
|
+
|
|
2042
|
+
/**
|
|
2043
|
+
* Repair an owner-only ACL on a retained expected path.
|
|
2044
|
+
*
|
|
2045
|
+
* Its no-follow handle must still identify the expected object before repair
|
|
2046
|
+
* and again after final ACL verification.
|
|
2047
|
+
*/
|
|
2048
|
+
export declare function repairOwnerOnlyPathSecurityExpected(path: string, kind: "directory" | "file", expectedDev: bigint, expectedIno: bigint): NativeOwnerOnlySecurityResult
|
|
1952
2049
|
|
|
1953
2050
|
/** A client reply forwarded to the TypeScript host for gate resolution. */
|
|
1954
2051
|
export interface ReplyEvent {
|
|
@@ -2178,6 +2275,12 @@ export declare function verifyOwnerOnlyFdSecurity(path: string, kind: "directory
|
|
|
2178
2275
|
|
|
2179
2276
|
export declare function verifyOwnerOnlyPathSecurity(path: string, kind: "directory" | "file"): NativeOwnerOnlySecurityResult
|
|
2180
2277
|
|
|
2278
|
+
/**
|
|
2279
|
+
* Verify owner-only ACL security without mutation only when the retained
|
|
2280
|
+
* no-follow handle identifies the expected object before and after inspection.
|
|
2281
|
+
*/
|
|
2282
|
+
export declare function verifyOwnerOnlyPathSecurityExpected(path: string, kind: "directory" | "file", expectedDev: bigint, expectedIno: bigint): NativeOwnerOnlySecurityResult
|
|
2283
|
+
|
|
2181
2284
|
/**
|
|
2182
2285
|
* Calculate visible width of text, excluding ANSI escape sequences.
|
|
2183
2286
|
*
|
|
@@ -2188,6 +2291,21 @@ export declare function visibleWidth(text: string, tabWidth: number): number
|
|
|
2188
2291
|
/** Calculate visible widths of many strings, excluding ANSI escape sequences. */
|
|
2189
2292
|
export declare function visibleWidths(lines: Array<string>, tabWidth: number): Array<number>
|
|
2190
2293
|
|
|
2294
|
+
export interface WindowsJobMemoryProbeResult {
|
|
2295
|
+
kind: string
|
|
2296
|
+
platform: string
|
|
2297
|
+
isInJob?: boolean
|
|
2298
|
+
jobMemoryLimitBytes?: string
|
|
2299
|
+
jobMemoryUsedBytes?: string
|
|
2300
|
+
peakJobMemoryUsedBytes?: string
|
|
2301
|
+
processMemoryLimitBytes?: string
|
|
2302
|
+
processPrivateUsageBytes?: string
|
|
2303
|
+
processWorkingSetBytes?: string
|
|
2304
|
+
peakProcessWorkingSetBytes?: string
|
|
2305
|
+
call?: string
|
|
2306
|
+
code?: string
|
|
2307
|
+
}
|
|
2308
|
+
|
|
2191
2309
|
/** Profiling results returned to JavaScript. */
|
|
2192
2310
|
export interface WorkProfile {
|
|
2193
2311
|
/** Folded stack format for flamegraph tools. */
|
|
@@ -2209,3 +2327,19 @@ export interface WorkProfile {
|
|
|
2209
2327
|
* Returns UTF-16 lines with active SGR codes carried across line boundaries.
|
|
2210
2328
|
*/
|
|
2211
2329
|
export declare function wrapTextWithAnsi(text: string, width: number, tabWidth: number): Array<string>
|
|
2330
|
+
|
|
2331
|
+
/** Bounded, path-free evidence for a parent-directory durability failure. */
|
|
2332
|
+
export interface NativePublishSyncFailure {
|
|
2333
|
+
phase: string
|
|
2334
|
+
parentRole: string
|
|
2335
|
+
osCode: number
|
|
2336
|
+
kind: string
|
|
2337
|
+
}
|
|
2338
|
+
|
|
2339
|
+
/** Bounded, path-free evidence for one atomic publication. */
|
|
2340
|
+
export interface NativePublishDiagnostic {
|
|
2341
|
+
schemaVersion: number
|
|
2342
|
+
collectionState: string
|
|
2343
|
+
osCode?: number
|
|
2344
|
+
syncFailures?: Array<NativePublishSyncFailure>
|
|
2345
|
+
}
|
package/native/index.js
CHANGED
|
@@ -29,7 +29,8 @@ export const RecoveryFsRoot = nativeBindings.RecoveryFsRoot;
|
|
|
29
29
|
export const Shell = nativeBindings.Shell;
|
|
30
30
|
|
|
31
31
|
// functions
|
|
32
|
-
export const
|
|
32
|
+
export const __piNativesPublishOutcomeV1 = nativeBindings.__piNativesPublishOutcomeV1;
|
|
33
|
+
export const __piNativesV0_5_0 = nativeBindings.__piNativesV0_5_0;
|
|
33
34
|
export const applyBashFixups = nativeBindings.applyBashFixups;
|
|
34
35
|
export const applyOwnerOnlyFdSecurity = nativeBindings.applyOwnerOnlyFdSecurity;
|
|
35
36
|
export const applyOwnerOnlyPathSecurity = nativeBindings.applyOwnerOnlyPathSecurity;
|
|
@@ -74,9 +75,11 @@ export const nativeBuildInfo = nativeBindings.nativeBuildInfo;
|
|
|
74
75
|
export const openRecoveryFsRoot = nativeBindings.openRecoveryFsRoot;
|
|
75
76
|
export const parseKey = nativeBindings.parseKey;
|
|
76
77
|
export const parseKittySequence = nativeBindings.parseKittySequence;
|
|
78
|
+
export const probeWindowsJobMemory = nativeBindings.probeWindowsJobMemory;
|
|
77
79
|
export const ptyTimeoutCount = nativeBindings.ptyTimeoutCount;
|
|
78
80
|
export const readImageFromClipboard = nativeBindings.readImageFromClipboard;
|
|
79
81
|
export const renameNoReplacePath = nativeBindings.renameNoReplacePath;
|
|
82
|
+
export const repairOwnerOnlyPathSecurityExpected = nativeBindings.repairOwnerOnlyPathSecurityExpected;
|
|
80
83
|
export const retainBrokerPublication = nativeBindings.retainBrokerPublication;
|
|
81
84
|
export const search = nativeBindings.search;
|
|
82
85
|
export const sliceWithWidth = nativeBindings.sliceWithWidth;
|
|
@@ -87,6 +90,7 @@ export const truncateLinesToWidth = nativeBindings.truncateLinesToWidth;
|
|
|
87
90
|
export const truncateToWidth = nativeBindings.truncateToWidth;
|
|
88
91
|
export const verifyOwnerOnlyFdSecurity = nativeBindings.verifyOwnerOnlyFdSecurity;
|
|
89
92
|
export const verifyOwnerOnlyPathSecurity = nativeBindings.verifyOwnerOnlyPathSecurity;
|
|
93
|
+
export const verifyOwnerOnlyPathSecurityExpected = nativeBindings.verifyOwnerOnlyPathSecurityExpected;
|
|
90
94
|
export const visibleWidth = nativeBindings.visibleWidth;
|
|
91
95
|
export const visibleWidths = nativeBindings.visibleWidths;
|
|
92
96
|
export const wrapTextWithAnsi = nativeBindings.wrapTextWithAnsi;
|
package/native/loader-state.d.ts
CHANGED
|
@@ -26,6 +26,15 @@ export interface GetAddonFilenamesInput {
|
|
|
26
26
|
|
|
27
27
|
export function getAddonFilenames(input: GetAddonFilenamesInput): string[];
|
|
28
28
|
|
|
29
|
+
export function getOptionalPackageNames(platformTag: string): string[];
|
|
30
|
+
|
|
31
|
+
export interface ResolveOptionalPackageNativeDirsInput {
|
|
32
|
+
packageNames: string[];
|
|
33
|
+
requireResolve: (id: string) => string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function resolveOptionalPackageNativeDirs(input: ResolveOptionalPackageNativeDirsInput): string[];
|
|
37
|
+
|
|
29
38
|
export interface ShouldStageNodeModulesAddonInput {
|
|
30
39
|
platform: NodeJS.Platform | string;
|
|
31
40
|
isCompiledBinary: boolean;
|
|
@@ -38,8 +47,9 @@ export interface ResolveLoaderCandidatesInput {
|
|
|
38
47
|
addonFilenames: string[];
|
|
39
48
|
isCompiledBinary: boolean;
|
|
40
49
|
stageFromNodeModules?: boolean;
|
|
50
|
+
isWorkspaceLoad?: boolean;
|
|
51
|
+
optionalPackageNativeDirs?: string[];
|
|
41
52
|
nativeDir: string;
|
|
42
|
-
platformNativeDir?: string | null;
|
|
43
53
|
execDir: string;
|
|
44
54
|
versionedDir: string;
|
|
45
55
|
userDataDir: string;
|
|
@@ -47,4 +57,56 @@ export interface ResolveLoaderCandidatesInput {
|
|
|
47
57
|
|
|
48
58
|
export function resolveLoaderCandidates(input: ResolveLoaderCandidatesInput): string[];
|
|
49
59
|
|
|
50
|
-
export
|
|
60
|
+
export interface LoadFromCandidatesInput<T> {
|
|
61
|
+
candidates: string[];
|
|
62
|
+
requireCandidate: (candidate: string) => T;
|
|
63
|
+
validateCandidate: (bindings: T, candidate: string) => void;
|
|
64
|
+
describeCandidate: (candidate: string) => string;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export interface LoadFromCandidatesResult<T> {
|
|
68
|
+
bindings: T | null;
|
|
69
|
+
errors: string[];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function loadFromCandidates<T>(input: LoadFromCandidatesInput<T>): LoadFromCandidatesResult<T>;
|
|
73
|
+
|
|
74
|
+
export interface CachedEmbeddedExtractionIsFreshInput {
|
|
75
|
+
targetPath: string;
|
|
76
|
+
embeddedPath: string;
|
|
77
|
+
sizeOf: (path: string) => number | null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function cachedEmbeddedExtractionIsFresh(input: CachedEmbeddedExtractionIsFreshInput): boolean;
|
|
81
|
+
|
|
82
|
+
export function validateLoadedBindings(
|
|
83
|
+
ctx: { versionSentinelExport: string; packageVersion: string },
|
|
84
|
+
bindings: Record<string, unknown>,
|
|
85
|
+
candidate: string,
|
|
86
|
+
): void;
|
|
87
|
+
|
|
88
|
+
export interface LoaderContext {
|
|
89
|
+
isCompiledBinary: boolean;
|
|
90
|
+
platformTag: string;
|
|
91
|
+
packageVersion?: string;
|
|
92
|
+
addonLabel?: string;
|
|
93
|
+
addonFilenames?: string[];
|
|
94
|
+
versionedDir?: string;
|
|
95
|
+
candidates?: string[];
|
|
96
|
+
selectedVariant?: "modern" | "baseline" | null;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function embeddedAddonIsAuthoritative(
|
|
100
|
+
ctx: LoaderContext,
|
|
101
|
+
addon?: EmbeddedAddon | null,
|
|
102
|
+
): boolean;
|
|
103
|
+
|
|
104
|
+
export interface LoadNativeOptions {
|
|
105
|
+
context?: LoaderContext;
|
|
106
|
+
extractEmbeddedAddons?: (ctx: LoaderContext) => string[];
|
|
107
|
+
stageNodeModulesAddon?: () => string | null;
|
|
108
|
+
requireCandidate?: (candidate: string) => Record<string, unknown>;
|
|
109
|
+
validateCandidate?: (bindings: Record<string, unknown>) => void;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export function loadNative(options?: LoadNativeOptions): Record<string, unknown>;
|
package/native/loader-state.js
CHANGED
|
@@ -31,6 +31,14 @@ import { embeddedAddon } from "./embedded-addon.js";
|
|
|
31
31
|
*/
|
|
32
32
|
|
|
33
33
|
const SUPPORTED_PLATFORMS = ["linux-x64", "linux-arm64", "darwin-x64", "darwin-arm64", "win32-x64"];
|
|
34
|
+
const OPTIONAL_PACKAGE_BY_PLATFORM_TAG = {
|
|
35
|
+
"darwin-arm64": "@sayknow-cli/natives-darwin-arm64",
|
|
36
|
+
"darwin-x64": "@sayknow-cli/natives-darwin-x64",
|
|
37
|
+
"linux-arm64": "@sayknow-cli/natives-linux-arm64",
|
|
38
|
+
"linux-x64": "@sayknow-cli/natives-linux-x64",
|
|
39
|
+
"win32-x64": "@sayknow-cli/natives-win32-x64",
|
|
40
|
+
};
|
|
41
|
+
|
|
34
42
|
|
|
35
43
|
function getNativesDir() {
|
|
36
44
|
const xdgDataHome = process.env.XDG_DATA_HOME;
|
|
@@ -78,6 +86,32 @@ export function getAddonFilenames({ tag, arch, variant }) {
|
|
|
78
86
|
return [baselineFilename, defaultFilename];
|
|
79
87
|
}
|
|
80
88
|
|
|
89
|
+
/**
|
|
90
|
+
* @param {string} platformTag
|
|
91
|
+
* @returns {string[]}
|
|
92
|
+
*/
|
|
93
|
+
export function getOptionalPackageNames(platformTag) {
|
|
94
|
+
const packageName = OPTIONAL_PACKAGE_BY_PLATFORM_TAG[platformTag];
|
|
95
|
+
return packageName ? [packageName] : [];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* @param {{ packageNames: string[]; requireResolve: (id: string) => string }} input
|
|
100
|
+
* @returns {string[]}
|
|
101
|
+
*/
|
|
102
|
+
export function resolveOptionalPackageNativeDirs({ packageNames, requireResolve }) {
|
|
103
|
+
const dirs = [];
|
|
104
|
+
for (const packageName of packageNames) {
|
|
105
|
+
try {
|
|
106
|
+
const manifestPath = requireResolve(`${packageName}/package.json`);
|
|
107
|
+
dirs.push(path.join(path.dirname(manifestPath), "native"));
|
|
108
|
+
} catch {
|
|
109
|
+
// Optional dependency is absent on non-matching platforms or older installs.
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return dirs;
|
|
113
|
+
}
|
|
114
|
+
|
|
81
115
|
/**
|
|
82
116
|
* Decide whether the loader should mirror the package's `native/<filename>.node`
|
|
83
117
|
* into the per-version cache directory (`~/.skc/natives/<version>/`) before loading.
|
|
@@ -112,8 +146,9 @@ export function shouldStageNodeModulesAddon({ platform, isCompiledBinary, native
|
|
|
112
146
|
* addonFilenames: string[];
|
|
113
147
|
* isCompiledBinary: boolean;
|
|
114
148
|
* stageFromNodeModules?: boolean;
|
|
149
|
+
* isWorkspaceLoad?: boolean;
|
|
150
|
+
* optionalPackageNativeDirs?: string[];
|
|
115
151
|
* nativeDir: string;
|
|
116
|
-
* platformNativeDir?: string | null;
|
|
117
152
|
* execDir: string;
|
|
118
153
|
* versionedDir: string;
|
|
119
154
|
* userDataDir: string;
|
|
@@ -124,18 +159,25 @@ export function resolveLoaderCandidates({
|
|
|
124
159
|
addonFilenames,
|
|
125
160
|
isCompiledBinary,
|
|
126
161
|
stageFromNodeModules = false,
|
|
162
|
+
isWorkspaceLoad = false,
|
|
163
|
+
optionalPackageNativeDirs = [],
|
|
127
164
|
nativeDir,
|
|
128
|
-
platformNativeDir,
|
|
129
165
|
execDir,
|
|
130
166
|
versionedDir,
|
|
131
167
|
userDataDir,
|
|
132
168
|
}) {
|
|
133
|
-
const
|
|
134
|
-
const
|
|
135
|
-
|
|
136
|
-
|
|
169
|
+
const workspaceCandidates = addonFilenames.map(filename => path.join(nativeDir, filename));
|
|
170
|
+
const optionalPackageCandidates = optionalPackageNativeDirs.flatMap(optionalNativeDir =>
|
|
171
|
+
addonFilenames.map(filename => path.join(optionalNativeDir, filename)),
|
|
172
|
+
);
|
|
173
|
+
const legacyReleaseCandidates = addonFilenames.flatMap(filename => [
|
|
174
|
+
path.join(nativeDir, filename),
|
|
137
175
|
path.join(execDir, filename),
|
|
138
176
|
]);
|
|
177
|
+
const legacyExecCandidates = addonFilenames.map(filename => path.join(execDir, filename));
|
|
178
|
+
const baseReleaseCandidates = isWorkspaceLoad
|
|
179
|
+
? [...workspaceCandidates, ...optionalPackageCandidates, ...legacyExecCandidates]
|
|
180
|
+
: [...optionalPackageCandidates, ...legacyReleaseCandidates];
|
|
139
181
|
const compiledCandidates = addonFilenames.flatMap(filename => [
|
|
140
182
|
path.join(versionedDir, filename),
|
|
141
183
|
path.join(userDataDir, filename),
|
|
@@ -152,6 +194,52 @@ export function resolveLoaderCandidates({
|
|
|
152
194
|
return [...new Set(releaseCandidates)];
|
|
153
195
|
}
|
|
154
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Deterministically try candidate paths in order using injected operations.
|
|
199
|
+
* This leaves file loading and compatibility policy at the call site while
|
|
200
|
+
* making fallback behavior testable without a native addon on disk.
|
|
201
|
+
*
|
|
202
|
+
* @template T
|
|
203
|
+
* @param {{
|
|
204
|
+
* candidates: string[];
|
|
205
|
+
* requireCandidate: (candidate: string) => T;
|
|
206
|
+
* validateCandidate: (bindings: T, candidate: string) => void;
|
|
207
|
+
* describeCandidate: (candidate: string) => string;
|
|
208
|
+
* }} input
|
|
209
|
+
* @returns {{ bindings: T | null; errors: string[] }}
|
|
210
|
+
*/
|
|
211
|
+
export function loadFromCandidates({ candidates, requireCandidate, validateCandidate, describeCandidate }) {
|
|
212
|
+
const errors = [];
|
|
213
|
+
for (const candidate of candidates) {
|
|
214
|
+
try {
|
|
215
|
+
const bindings = requireCandidate(candidate);
|
|
216
|
+
validateCandidate(bindings, candidate);
|
|
217
|
+
return { bindings, errors };
|
|
218
|
+
} catch (err) {
|
|
219
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
220
|
+
errors.push(`${describeCandidate(candidate)}: ${message}`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
return { bindings: null, errors };
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Decide whether a previously extracted embedded addon may be reused. A cached
|
|
228
|
+
* extraction from an earlier build of the same version carries the same version
|
|
229
|
+
* sentinel yet can expose a different native surface, so it is fresh only when
|
|
230
|
+
* its byte size matches the embedded payload. `sizeOf` returns the byte size of
|
|
231
|
+
* a path, or `null` when it cannot be inspected.
|
|
232
|
+
* @param {{ targetPath: string; embeddedPath: string; sizeOf: (path: string) => number | null }} input
|
|
233
|
+
* @returns {boolean}
|
|
234
|
+
*/
|
|
235
|
+
export function cachedEmbeddedExtractionIsFresh({ targetPath, embeddedPath, sizeOf }) {
|
|
236
|
+
const cachedSize = sizeOf(targetPath);
|
|
237
|
+
if (cachedSize === null) return false;
|
|
238
|
+
const embeddedSize = sizeOf(embeddedPath);
|
|
239
|
+
if (embeddedSize === null) return false;
|
|
240
|
+
return cachedSize === embeddedSize;
|
|
241
|
+
}
|
|
242
|
+
|
|
155
243
|
// =========================================================================
|
|
156
244
|
// Side-effectful loader. Everything below runs only when `loadNative()` is
|
|
157
245
|
// called from `native/index.js` — tests that only import the pure helpers
|
|
@@ -218,70 +306,79 @@ function resolveCpuVariant(override) {
|
|
|
218
306
|
return detectAvx2Support() ? "modern" : "baseline";
|
|
219
307
|
}
|
|
220
308
|
|
|
221
|
-
function
|
|
222
|
-
if (!embeddedAddon) return
|
|
223
|
-
const
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
);
|
|
231
|
-
}
|
|
232
|
-
return embeddedAddon.files.find(file => file.variant === "baseline") || null;
|
|
309
|
+
function embeddedAddonCandidates(selectedVariant) {
|
|
310
|
+
if (!embeddedAddon) return [];
|
|
311
|
+
const files = embeddedAddon.files;
|
|
312
|
+
const candidates = process.arch !== "x64"
|
|
313
|
+
? [files.find(file => file.variant === "default"), ...files]
|
|
314
|
+
: selectedVariant === "modern"
|
|
315
|
+
? [files.find(file => file.variant === "modern"), files.find(file => file.variant === "baseline")]
|
|
316
|
+
: [files.find(file => file.variant === "baseline")];
|
|
317
|
+
return [...new Set(candidates.filter(Boolean))];
|
|
233
318
|
}
|
|
234
319
|
|
|
235
|
-
function
|
|
236
|
-
if (!ctx.isCompiledBinary || !embeddedAddon) return
|
|
237
|
-
if (embeddedAddon.platformTag !== ctx.platformTag || embeddedAddon.version !== ctx.packageVersion) return
|
|
238
|
-
|
|
239
|
-
const selectedEmbeddedFile = selectEmbeddedAddonFile(ctx.selectedVariant);
|
|
240
|
-
if (!selectedEmbeddedFile) return null;
|
|
241
|
-
const targetPath = path.join(ctx.versionedDir, selectedEmbeddedFile.filename);
|
|
242
|
-
if (fs.existsSync(targetPath)) return targetPath;
|
|
320
|
+
function maybeExtractEmbeddedAddons(ctx, errors) {
|
|
321
|
+
if (!ctx.isCompiledBinary || !embeddedAddon) return [];
|
|
322
|
+
if (embeddedAddon.platformTag !== ctx.platformTag || embeddedAddon.version !== ctx.packageVersion) return [];
|
|
243
323
|
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
324
|
+
const extracted = [];
|
|
325
|
+
for (const embeddedFile of embeddedAddonCandidates(ctx.selectedVariant)) {
|
|
326
|
+
const targetPath = path.join(ctx.versionedDir, embeddedFile.filename);
|
|
327
|
+
if (fs.existsSync(targetPath)) {
|
|
328
|
+
// Guard against intra-version drift: a cached extraction written by an earlier
|
|
329
|
+
// build of the same version carries the same version sentinel but can expose a
|
|
330
|
+
// different native surface (e.g. a symbol added mid-cycle). The embedded addon
|
|
331
|
+
// is the source of truth, so reuse the cached file only when it matches the
|
|
332
|
+
// embedded payload size and re-extract otherwise.
|
|
333
|
+
const sizeOf = candidate => {
|
|
334
|
+
try {
|
|
335
|
+
return fs.statSync(candidate).size;
|
|
336
|
+
} catch {
|
|
337
|
+
return null;
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
if (cachedEmbeddedExtractionIsFresh({ targetPath, embeddedPath: embeddedFile.filePath, sizeOf })) {
|
|
341
|
+
extracted.push(targetPath);
|
|
342
|
+
continue;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
251
345
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
346
|
+
try {
|
|
347
|
+
fs.mkdirSync(ctx.versionedDir, { recursive: true });
|
|
348
|
+
const buffer = fs.readFileSync(embeddedFile.filePath);
|
|
349
|
+
const tempPath = `${targetPath}.tmp.${process.pid}`;
|
|
350
|
+
fs.writeFileSync(tempPath, buffer);
|
|
351
|
+
fs.renameSync(tempPath, targetPath);
|
|
352
|
+
extracted.push(targetPath);
|
|
353
|
+
} catch (err) {
|
|
354
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
355
|
+
errors.push(`embedded addon write (${embeddedFile.filename}): ${message}`);
|
|
356
|
+
}
|
|
262
357
|
}
|
|
358
|
+
return extracted;
|
|
263
359
|
}
|
|
264
360
|
|
|
265
361
|
/**
|
|
266
|
-
* Mirror
|
|
267
|
-
* installs so the running process
|
|
268
|
-
*
|
|
269
|
-
* update. No-op on non-Windows,
|
|
270
|
-
*
|
|
362
|
+
* Mirror the optional-package or legacy bundled `native/<filename>.node` into
|
|
363
|
+
* `versionedDir/<filename>.node` on Windows installs so the running process
|
|
364
|
+
* keeps its OS-level handle on a versioned cache path, never on the
|
|
365
|
+
* `node_modules` copy that bun must overwrite on update. No-op on non-Windows,
|
|
366
|
+
* in workspace dev, and for compiled binaries — see `shouldStageNodeModulesAddon`.
|
|
271
367
|
*/
|
|
272
368
|
function maybeStageNodeModulesAddon(ctx, errors) {
|
|
273
369
|
if (!ctx.stageFromNodeModules) return null;
|
|
274
370
|
|
|
275
371
|
let stagedPath = null;
|
|
372
|
+
const sourceDirs = [...ctx.optionalPackageNativeDirs, ctx.nativeDir];
|
|
276
373
|
for (const filename of ctx.addonFilenames) {
|
|
277
|
-
const sourcePath = path.join(ctx.nativeDir, filename);
|
|
278
374
|
const targetPath = path.join(ctx.versionedDir, filename);
|
|
279
375
|
|
|
280
376
|
if (fs.existsSync(targetPath)) {
|
|
281
377
|
stagedPath = stagedPath || targetPath;
|
|
282
378
|
continue;
|
|
283
379
|
}
|
|
284
|
-
|
|
380
|
+
const sourcePath = sourceDirs.map(sourceDir => path.join(sourceDir, filename)).find(candidate => fs.existsSync(candidate));
|
|
381
|
+
if (!sourcePath) continue;
|
|
285
382
|
|
|
286
383
|
try {
|
|
287
384
|
fs.mkdirSync(ctx.versionedDir, { recursive: true });
|
|
@@ -304,19 +401,26 @@ function maybeStageNodeModulesAddon(ctx, errors) {
|
|
|
304
401
|
return stagedPath;
|
|
305
402
|
}
|
|
306
403
|
|
|
307
|
-
function validateLoadedBindings(ctx, bindings, candidate) {
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
`
|
|
318
|
-
"
|
|
319
|
-
|
|
404
|
+
export function validateLoadedBindings(ctx, bindings, candidate) {
|
|
405
|
+
if (typeof bindings[ctx.versionSentinelExport] !== "function") {
|
|
406
|
+
throw new Error(
|
|
407
|
+
`Loaded ${candidate} but it does not expose the @sayknow-cli/natives@${ctx.packageVersion} ` +
|
|
408
|
+
`version sentinel \`${ctx.versionSentinelExport}\`. The .node file on disk is from a different ` +
|
|
409
|
+
"release than this loader — reinstall to re-sync.",
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
if (typeof bindings.__piNativesPublishOutcomeV1 !== "function") {
|
|
413
|
+
throw new Error(
|
|
414
|
+
`Loaded ${candidate} but it lacks retained-publish capability sentinel ` +
|
|
415
|
+
"`__piNativesPublishOutcomeV1`; trying the next compatible artifact.",
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
if (typeof bindings.renameNoReplacePath !== "function") {
|
|
419
|
+
throw new Error(`Loaded ${candidate} but it lacks required atomic publish capability \`renameNoReplacePath\`.`);
|
|
420
|
+
}
|
|
421
|
+
if (typeof bindings.probeWindowsJobMemory !== "function") {
|
|
422
|
+
throw new Error(`Loaded ${candidate} but it lacks required memory probe capability \`probeWindowsJobMemory\`.`);
|
|
423
|
+
}
|
|
320
424
|
}
|
|
321
425
|
|
|
322
426
|
function buildHelpMessage(ctx) {
|
|
@@ -347,11 +451,10 @@ function buildHelpMessage(ctx) {
|
|
|
347
451
|
* Called from `loadNative()` rather than at module scope so importing pure
|
|
348
452
|
* helpers from this file doesn't trigger AVX2 detection or filesystem probes.
|
|
349
453
|
*/
|
|
350
|
-
function initLoaderContext() {
|
|
454
|
+
function initLoaderContext(require_) {
|
|
351
455
|
const platformTag = `${process.platform}-${process.arch}`;
|
|
352
456
|
const packageVersion = packageJson.version;
|
|
353
457
|
const nativeDir = path.join(import.meta.dir, "..", "native");
|
|
354
|
-
const platformNativeDir = path.join(nativeDir, "..", "..", `natives-${platformTag}`, "native");
|
|
355
458
|
const execDir = path.dirname(process.execPath);
|
|
356
459
|
const versionedDir = path.join(getNativesDir(), packageVersion);
|
|
357
460
|
const userDataDir =
|
|
@@ -369,17 +472,25 @@ function initLoaderContext() {
|
|
|
369
472
|
isCompiledBinary,
|
|
370
473
|
nativeDir,
|
|
371
474
|
});
|
|
475
|
+
const isWorkspaceLoad =
|
|
476
|
+
!isCompiledBinary && !nativeDir.includes("\\node_modules\\") && !nativeDir.includes("/node_modules/");
|
|
372
477
|
|
|
373
478
|
const selectedVariant = resolveCpuVariant(getVariantOverride());
|
|
374
479
|
const addonFilenames = getAddonFilenames({ tag: platformTag, arch: process.arch, variant: selectedVariant });
|
|
375
480
|
const addonLabel = selectedVariant ? `${platformTag} (${selectedVariant})` : platformTag;
|
|
481
|
+
const optionalPackageNativeDirs = resolveOptionalPackageNativeDirs({
|
|
482
|
+
packageNames: getOptionalPackageNames(platformTag),
|
|
483
|
+
requireResolve: id => require_.resolve(id),
|
|
484
|
+
});
|
|
485
|
+
|
|
376
486
|
|
|
377
487
|
const candidates = resolveLoaderCandidates({
|
|
378
488
|
addonFilenames,
|
|
379
489
|
isCompiledBinary,
|
|
380
490
|
stageFromNodeModules,
|
|
491
|
+
isWorkspaceLoad,
|
|
492
|
+
optionalPackageNativeDirs,
|
|
381
493
|
nativeDir,
|
|
382
|
-
platformNativeDir,
|
|
383
494
|
execDir,
|
|
384
495
|
versionedDir,
|
|
385
496
|
userDataDir,
|
|
@@ -393,8 +504,6 @@ function initLoaderContext() {
|
|
|
393
504
|
// turns the silent `<sym> is not a function` crash from a Windows
|
|
394
505
|
// locked-file update into an actionable load-time error.
|
|
395
506
|
const versionSentinelExport = `__piNativesV${packageVersion.replace(/[^A-Za-z0-9]/g, "_")}`;
|
|
396
|
-
const isWorkspaceLoad =
|
|
397
|
-
!isCompiledBinary && !nativeDir.includes("\\node_modules\\") && !nativeDir.includes("/node_modules/");
|
|
398
507
|
|
|
399
508
|
return {
|
|
400
509
|
platformTag,
|
|
@@ -405,33 +514,41 @@ function initLoaderContext() {
|
|
|
405
514
|
stageFromNodeModules,
|
|
406
515
|
selectedVariant,
|
|
407
516
|
addonFilenames,
|
|
517
|
+
optionalPackageNativeDirs,
|
|
408
518
|
addonLabel,
|
|
409
519
|
candidates,
|
|
410
520
|
versionSentinelExport,
|
|
411
|
-
isWorkspaceLoad,
|
|
412
521
|
};
|
|
413
522
|
}
|
|
414
523
|
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
524
|
+
/** Embedded standalone payloads are the complete trust boundary for their matching build. */
|
|
525
|
+
export function embeddedAddonIsAuthoritative(ctx, addon = embeddedAddon) {
|
|
526
|
+
return (
|
|
527
|
+
ctx.isCompiledBinary && addon?.platformTag === ctx.platformTag && addon.version === ctx.packageVersion
|
|
528
|
+
);
|
|
529
|
+
}
|
|
418
530
|
|
|
419
|
-
|
|
420
|
-
const
|
|
421
|
-
const
|
|
422
|
-
const prepended = [embeddedCandidate, stagedCandidate].filter(c => typeof c === "string");
|
|
423
|
-
const runtimeCandidates = prepended.length > 0 ? [...prepended, ...ctx.candidates] : ctx.candidates;
|
|
531
|
+
export function loadNative(options = {}) {
|
|
532
|
+
const require_ = options.requireCandidate ? null : createRequire(import.meta.url);
|
|
533
|
+
const ctx = options.context ?? initLoaderContext(require_);
|
|
424
534
|
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
535
|
+
const errors = [];
|
|
536
|
+
const embeddedCandidates = (options.extractEmbeddedAddons ?? maybeExtractEmbeddedAddons)(ctx, errors);
|
|
537
|
+
const embeddedIsAuthoritative = embeddedAddonIsAuthoritative(ctx);
|
|
538
|
+
const stagedCandidate =
|
|
539
|
+
embeddedCandidates.length > 0 || embeddedIsAuthoritative
|
|
540
|
+
? null
|
|
541
|
+
: (options.stageNodeModulesAddon ?? maybeStageNodeModulesAddon)(ctx, errors);
|
|
542
|
+
const prepended = [...embeddedCandidates, stagedCandidate].filter(c => typeof c === "string");
|
|
543
|
+
const runtimeCandidates = embeddedIsAuthoritative ? prepended : prepended.length > 0 ? [...prepended, ...ctx.candidates] : ctx.candidates;
|
|
544
|
+
const loaded = loadFromCandidates({
|
|
545
|
+
candidates: runtimeCandidates,
|
|
546
|
+
requireCandidate: options.requireCandidate ?? (candidate => require_(candidate)),
|
|
547
|
+
validateCandidate: options.validateCandidate ?? ((bindings, candidate) => validateLoadedBindings(ctx, bindings, candidate)),
|
|
548
|
+
describeCandidate: candidate => candidate,
|
|
549
|
+
});
|
|
550
|
+
if (loaded.bindings) return loaded.bindings;
|
|
551
|
+
errors.push(...loaded.errors);
|
|
435
552
|
|
|
436
553
|
if (!SUPPORTED_PLATFORMS.includes(ctx.platformTag)) {
|
|
437
554
|
throw new Error(
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sayknow-cli/natives",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "Native Rust bindings for grep, clipboard, image processing, syntax highlighting, PTY, and shell operations via N-API",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"homepage": "https://sayknow-cli.com",
|
|
@@ -61,11 +61,11 @@
|
|
|
61
61
|
"README.md"
|
|
62
62
|
],
|
|
63
63
|
"optionalDependencies": {
|
|
64
|
-
"@sayknow-cli/natives-darwin-arm64": "0.
|
|
65
|
-
"@sayknow-cli/natives-darwin-x64": "0.
|
|
66
|
-
"@sayknow-cli/natives-linux-arm64": "0.
|
|
67
|
-
"@sayknow-cli/natives-linux-x64": "0.
|
|
68
|
-
"@sayknow-cli/natives-win32-x64": "0.
|
|
64
|
+
"@sayknow-cli/natives-darwin-arm64": "0.5.0",
|
|
65
|
+
"@sayknow-cli/natives-darwin-x64": "0.5.0",
|
|
66
|
+
"@sayknow-cli/natives-linux-arm64": "0.5.0",
|
|
67
|
+
"@sayknow-cli/natives-linux-x64": "0.5.0",
|
|
68
|
+
"@sayknow-cli/natives-win32-x64": "0.5.0"
|
|
69
69
|
},
|
|
70
70
|
"exports": {
|
|
71
71
|
".": {
|