@relayfile/sdk 0.8.18 → 0.8.20
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/dist/mount-launcher.js +8 -40
- package/dist/mount-path.d.ts +18 -0
- package/dist/mount-path.js +179 -0
- package/package.json +12 -2
package/dist/mount-launcher.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
2
|
+
import { createWriteStream } from "node:fs";
|
|
3
|
+
import { mkdir, readFile, rename, stat, unlink, writeFile } from "node:fs/promises";
|
|
4
4
|
import path from "node:path";
|
|
5
5
|
import process from "node:process";
|
|
6
|
-
import { fileURLToPath } from "node:url";
|
|
7
6
|
import { RelayFileClient } from "./client.js";
|
|
7
|
+
import { getRelayfileMountBinaryPath } from "./mount-path.js";
|
|
8
8
|
import { CloudAbortError, MountModeUnavailableError, MountReadyTimeoutError, RelayfileSetupError } from "./setup-errors.js";
|
|
9
9
|
const DEFAULT_READY_POLL_INTERVAL_MS = 250;
|
|
10
10
|
const DEFAULT_STOP_TIMEOUT_MS = 10_000;
|
|
@@ -295,43 +295,11 @@ function normalizeNonEmptyString(value) {
|
|
|
295
295
|
return typeof value === "string" && value.trim() !== "" ? value : undefined;
|
|
296
296
|
}
|
|
297
297
|
async function resolveRelayfileMountCommand() {
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
process.env.RELAYFILE_MOUNT_BIN,
|
|
304
|
-
fileURLToPath(new URL("../../../../bin/relayfile-mount", import.meta.url))
|
|
305
|
-
];
|
|
306
|
-
for (const candidate of candidates) {
|
|
307
|
-
if (!candidate) {
|
|
308
|
-
continue;
|
|
309
|
-
}
|
|
310
|
-
if (await isExecutable(candidate)) {
|
|
311
|
-
return candidate;
|
|
312
|
-
}
|
|
313
|
-
}
|
|
314
|
-
return "relayfile-mount";
|
|
315
|
-
}
|
|
316
|
-
async function findExecutableInPath(command) {
|
|
317
|
-
const pathValue = process.env.PATH ?? "";
|
|
318
|
-
const pathEntries = pathValue.split(path.delimiter).filter(Boolean);
|
|
319
|
-
for (const entry of pathEntries) {
|
|
320
|
-
const candidate = path.join(entry, command);
|
|
321
|
-
if (await isExecutable(candidate)) {
|
|
322
|
-
return candidate;
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
return null;
|
|
326
|
-
}
|
|
327
|
-
async function isExecutable(candidate) {
|
|
328
|
-
try {
|
|
329
|
-
await access(candidate, fsConstants.X_OK);
|
|
330
|
-
return true;
|
|
331
|
-
}
|
|
332
|
-
catch {
|
|
333
|
-
return false;
|
|
334
|
-
}
|
|
298
|
+
// Delegates to the shared resolver, which checks the RELAYFILE_MOUNT_BIN
|
|
299
|
+
// override, local source-checkout builds, the platform-specific optional-dep
|
|
300
|
+
// package (@relayfile/mount-<platform>-<arch>), then PATH. Falls back to the
|
|
301
|
+
// bare command name so spawn surfaces a clear ENOENT if nothing is found.
|
|
302
|
+
return getRelayfileMountBinaryPath() ?? "relayfile-mount";
|
|
335
303
|
}
|
|
336
304
|
async function rotateMountLogIfNeeded(logPath) {
|
|
337
305
|
try {
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export declare function getOptionalDepPackageName(platform?: string, arch?: string): string;
|
|
2
|
+
/**
|
|
3
|
+
* Resolve the relayfile-mount binary path.
|
|
4
|
+
*
|
|
5
|
+
* Search order:
|
|
6
|
+
* 1. Explicit env override (RELAYFILE_MOUNT_BIN)
|
|
7
|
+
* 2. Local source-checkout build (bin/ or dist/), when loaded from a checkout
|
|
8
|
+
* 3. Platform-specific optional-dep package — primary production path
|
|
9
|
+
* 4. PATH lookup
|
|
10
|
+
*
|
|
11
|
+
* @returns Absolute path to the binary, or null if none is found.
|
|
12
|
+
*/
|
|
13
|
+
export declare function getRelayfileMountBinaryPath(): string | null;
|
|
14
|
+
/**
|
|
15
|
+
* Human-readable error explaining that the optional-dep package for the
|
|
16
|
+
* current platform/arch isn't installed.
|
|
17
|
+
*/
|
|
18
|
+
export declare function formatMountNotFoundError(): string;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolves the relayfile-mount binary path at runtime.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors the agent-relay broker resolver (`@agent-relay/harness-driver`'s
|
|
5
|
+
* broker-path): the binary ships as platform-specific optional-dependency
|
|
6
|
+
* packages (`@relayfile/mount-<platform>-<arch>`) that npm installs only for
|
|
7
|
+
* the matching os/cpu, and the SDK locates the right one via `require.resolve`.
|
|
8
|
+
* No postinstall download is involved.
|
|
9
|
+
*
|
|
10
|
+
* Usage:
|
|
11
|
+
* import { getRelayfileMountBinaryPath } from "@relayfile/sdk/mount-path"
|
|
12
|
+
* const binPath = getRelayfileMountBinaryPath()
|
|
13
|
+
*/
|
|
14
|
+
import { existsSync } from "node:fs";
|
|
15
|
+
import { createRequire } from "node:module";
|
|
16
|
+
import { delimiter, dirname, join, resolve } from "node:path";
|
|
17
|
+
import { fileURLToPath } from "node:url";
|
|
18
|
+
const MOUNT_BIN = "relayfile-mount";
|
|
19
|
+
/**
|
|
20
|
+
* Node's `process.arch` ("x64"/"arm64") differs from Go's GOARCH
|
|
21
|
+
* ("amd64"/"arm64"). The optional-dep package name follows Node's convention
|
|
22
|
+
* (matching the broker packages); the source-checkout `dist/` file names follow
|
|
23
|
+
* Go's. This maps Node arch -> Go arch for dev resolution.
|
|
24
|
+
*/
|
|
25
|
+
function goArch(arch = process.arch) {
|
|
26
|
+
return arch === "x64" ? "amd64" : arch;
|
|
27
|
+
}
|
|
28
|
+
export function getOptionalDepPackageName(platform = process.platform, arch = process.arch) {
|
|
29
|
+
return `@relayfile/mount-${platform}-${arch}`;
|
|
30
|
+
}
|
|
31
|
+
function getCurrentModuleDir() {
|
|
32
|
+
try {
|
|
33
|
+
return dirname(fileURLToPath(import.meta.url));
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function addUnique(paths, candidate) {
|
|
40
|
+
if (candidate && !paths.includes(candidate)) {
|
|
41
|
+
paths.push(candidate);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Anchors from which to run `require.resolve` for the optional-dep package.
|
|
46
|
+
* Covers the SDK's own location, the entry script (CLI consumers / bundled
|
|
47
|
+
* installs where the SDK lives under the consumer's node_modules), and the
|
|
48
|
+
* consumer's cwd.
|
|
49
|
+
*/
|
|
50
|
+
function getResolutionReferences() {
|
|
51
|
+
const refs = [];
|
|
52
|
+
const moduleDir = getCurrentModuleDir();
|
|
53
|
+
addUnique(refs, moduleDir ? join(moduleDir, "mount-path.js") : null);
|
|
54
|
+
if (process.argv[1]) {
|
|
55
|
+
addUnique(refs, process.argv[1]);
|
|
56
|
+
}
|
|
57
|
+
addUnique(refs, join(process.cwd(), "package.json"));
|
|
58
|
+
return refs;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Resolve the binary via the platform-specific optional-dependency package.
|
|
62
|
+
* Returns null when the optional dep is not installed (expected under
|
|
63
|
+
* --omit=optional, or before the package has been published for a platform).
|
|
64
|
+
*/
|
|
65
|
+
function getOptionalDepBinaryPath() {
|
|
66
|
+
const pkgName = getOptionalDepPackageName();
|
|
67
|
+
for (const ref of getResolutionReferences()) {
|
|
68
|
+
try {
|
|
69
|
+
const pkgJsonPath = createRequire(ref).resolve(`${pkgName}/package.json`);
|
|
70
|
+
const binPath = join(dirname(pkgJsonPath), "bin", MOUNT_BIN);
|
|
71
|
+
if (existsSync(binPath)) {
|
|
72
|
+
return binPath;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// Try the next reference.
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return null;
|
|
80
|
+
}
|
|
81
|
+
function isSourceCheckoutRoot(candidate) {
|
|
82
|
+
const root = resolve(candidate);
|
|
83
|
+
return (existsSync(join(root, "go.mod")) &&
|
|
84
|
+
existsSync(join(root, "cmd", "relayfile-mount", "main.go")));
|
|
85
|
+
}
|
|
86
|
+
function findAncestorSourceCheckoutRoot(start) {
|
|
87
|
+
let current = resolve(start);
|
|
88
|
+
for (let i = 0; i < 8; i += 1) {
|
|
89
|
+
if (isSourceCheckoutRoot(current)) {
|
|
90
|
+
return current;
|
|
91
|
+
}
|
|
92
|
+
const parent = resolve(current, "..");
|
|
93
|
+
if (parent === current) {
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
current = parent;
|
|
97
|
+
}
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Local `make build`/`make build-all` outputs, used when the SDK is loaded
|
|
102
|
+
* from a relayfile source checkout.
|
|
103
|
+
*/
|
|
104
|
+
function getSourceCheckoutBinaryPaths() {
|
|
105
|
+
const paths = [];
|
|
106
|
+
const roots = new Set();
|
|
107
|
+
const addRoot = (candidate) => {
|
|
108
|
+
if (!candidate) {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
const root = resolve(candidate);
|
|
112
|
+
if (!isSourceCheckoutRoot(root) || roots.has(root)) {
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
roots.add(root);
|
|
116
|
+
addUnique(paths, join(root, "bin", MOUNT_BIN));
|
|
117
|
+
addUnique(paths, join(root, "dist", `relayfile-mount-${process.platform}-${goArch()}`));
|
|
118
|
+
};
|
|
119
|
+
addRoot(findAncestorSourceCheckoutRoot(process.cwd()));
|
|
120
|
+
const moduleDir = getCurrentModuleDir();
|
|
121
|
+
if (moduleDir) {
|
|
122
|
+
// packages/sdk/typescript/dist -> repo root is four levels up.
|
|
123
|
+
addRoot(findAncestorSourceCheckoutRoot(moduleDir));
|
|
124
|
+
}
|
|
125
|
+
return paths;
|
|
126
|
+
}
|
|
127
|
+
function findExecutableInPath() {
|
|
128
|
+
const ext = process.platform === "win32" ? ".exe" : "";
|
|
129
|
+
const entries = (process.env.PATH ?? "").split(delimiter).filter(Boolean);
|
|
130
|
+
for (const entry of entries) {
|
|
131
|
+
const candidate = join(entry, `${MOUNT_BIN}${ext}`);
|
|
132
|
+
if (existsSync(candidate)) {
|
|
133
|
+
return candidate;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return null;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Resolve the relayfile-mount binary path.
|
|
140
|
+
*
|
|
141
|
+
* Search order:
|
|
142
|
+
* 1. Explicit env override (RELAYFILE_MOUNT_BIN)
|
|
143
|
+
* 2. Local source-checkout build (bin/ or dist/), when loaded from a checkout
|
|
144
|
+
* 3. Platform-specific optional-dep package — primary production path
|
|
145
|
+
* 4. PATH lookup
|
|
146
|
+
*
|
|
147
|
+
* @returns Absolute path to the binary, or null if none is found.
|
|
148
|
+
*/
|
|
149
|
+
export function getRelayfileMountBinaryPath() {
|
|
150
|
+
const override = process.env.RELAYFILE_MOUNT_BIN;
|
|
151
|
+
if (override) {
|
|
152
|
+
const resolved = resolve(override);
|
|
153
|
+
if (existsSync(resolved)) {
|
|
154
|
+
return resolved;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
for (const sourcePath of getSourceCheckoutBinaryPaths()) {
|
|
158
|
+
if (existsSync(sourcePath)) {
|
|
159
|
+
return sourcePath;
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
const optionalDepBinary = getOptionalDepBinaryPath();
|
|
163
|
+
if (optionalDepBinary) {
|
|
164
|
+
return optionalDepBinary;
|
|
165
|
+
}
|
|
166
|
+
return findExecutableInPath();
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Human-readable error explaining that the optional-dep package for the
|
|
170
|
+
* current platform/arch isn't installed.
|
|
171
|
+
*/
|
|
172
|
+
export function formatMountNotFoundError() {
|
|
173
|
+
const pkgName = getOptionalDepPackageName();
|
|
174
|
+
return (`relayfile couldn't find a relayfile-mount binary for ` +
|
|
175
|
+
`${process.platform}-${process.arch}. The optional dependency ${pkgName} ` +
|
|
176
|
+
`is expected to be installed alongside @relayfile/sdk. Try reinstalling ` +
|
|
177
|
+
`with --include=optional, or set RELAYFILE_MOUNT_BIN to a binary you've ` +
|
|
178
|
+
`built or downloaded manually.`);
|
|
179
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@relayfile/sdk",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.20",
|
|
4
4
|
"description": "TypeScript SDK for relayfile — real-time filesystem for humans and agents",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -26,6 +26,10 @@
|
|
|
26
26
|
"types": "./dist/mount-harness.d.ts",
|
|
27
27
|
"default": "./dist/mount-harness.js"
|
|
28
28
|
},
|
|
29
|
+
"./mount-path": {
|
|
30
|
+
"types": "./dist/mount-path.d.ts",
|
|
31
|
+
"default": "./dist/mount-path.js"
|
|
32
|
+
},
|
|
29
33
|
"./workspace-seeder": {
|
|
30
34
|
"types": "./dist/workspace-seeder.d.ts",
|
|
31
35
|
"default": "./dist/workspace-seeder.js"
|
|
@@ -55,10 +59,16 @@
|
|
|
55
59
|
"prepublishOnly": "npm run build"
|
|
56
60
|
},
|
|
57
61
|
"dependencies": {
|
|
58
|
-
"@relayfile/core": "0.8.
|
|
62
|
+
"@relayfile/core": "0.8.20",
|
|
59
63
|
"ignore": "^7.0.5",
|
|
60
64
|
"tar": "^7.5.10"
|
|
61
65
|
},
|
|
66
|
+
"optionalDependencies": {
|
|
67
|
+
"@relayfile/mount-darwin-arm64": "0.8.20",
|
|
68
|
+
"@relayfile/mount-darwin-x64": "0.8.20",
|
|
69
|
+
"@relayfile/mount-linux-arm64": "0.8.20",
|
|
70
|
+
"@relayfile/mount-linux-x64": "0.8.20"
|
|
71
|
+
},
|
|
62
72
|
"peerDependencies": {},
|
|
63
73
|
"devDependencies": {
|
|
64
74
|
"typescript": "^5.7.3",
|