@agent-relay/sandbox 0.0.0 → 0.1.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/README.md +8 -4
- package/dist/daytona/runtime.d.ts +117 -0
- package/dist/daytona/runtime.d.ts.map +1 -0
- package/dist/daytona/runtime.js +765 -0
- package/dist/daytona/runtime.js.map +1 -0
- package/dist/e2b/runtime.d.ts +167 -0
- package/dist/e2b/runtime.d.ts.map +1 -0
- package/dist/e2b/runtime.js +362 -0
- package/dist/e2b/runtime.js.map +1 -0
- package/dist/index.d.ts +26 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -3
- package/dist/index.js.map +1 -1
- package/dist/local/runtime.d.ts +63 -0
- package/dist/local/runtime.d.ts.map +1 -0
- package/dist/local/runtime.js +315 -0
- package/dist/local/runtime.js.map +1 -0
- package/dist/mount-script.d.ts +162 -0
- package/dist/mount-script.d.ts.map +1 -0
- package/dist/mount-script.js +461 -0
- package/dist/mount-script.js.map +1 -0
- package/dist/orchestrator.d.ts +110 -0
- package/dist/orchestrator.d.ts.map +1 -0
- package/dist/orchestrator.js +553 -0
- package/dist/orchestrator.js.map +1 -0
- package/dist/port.d.ts +126 -0
- package/dist/port.d.ts.map +1 -0
- package/dist/port.js +35 -0
- package/dist/port.js.map +1 -0
- package/dist/types.d.ts +71 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/package.json +16 -1
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell snippets for running the `relayfile-mount` daemon inside a sandbox.
|
|
3
|
+
*
|
|
4
|
+
* Callers that drive the mount — a command-at-a-time executor, a runner that
|
|
5
|
+
* submits one multi-line script, and a generator that emits sandbox-resident
|
|
6
|
+
* bootstrap JS — would otherwise each hand-roll near-identical bash. This
|
|
7
|
+
* module is the single builder for all of them, and owns the command
|
|
8
|
+
* templates the bootstrap generator embeds.
|
|
9
|
+
*
|
|
10
|
+
* The contract: helpers take primitives, do their own shell quoting, and
|
|
11
|
+
* return ready-to-run bash. Callers must not re-quote.
|
|
12
|
+
*/
|
|
13
|
+
export type RelayfileMountShellOptions = {
|
|
14
|
+
/** Relayfile base URL, e.g. `https://your-relayfile-host.example`. */
|
|
15
|
+
baseUrl: string;
|
|
16
|
+
/** Workspace id the path-scoped token is bound to. */
|
|
17
|
+
workspaceId: string;
|
|
18
|
+
/** Local mirror root inside the sandbox, e.g. `/home/<user>/workspace`. */
|
|
19
|
+
localDir: string;
|
|
20
|
+
/**
|
|
21
|
+
* Private relayfile-mount state directory. Required: it is sandbox-image
|
|
22
|
+
* specific, and it must sit OUTSIDE the mounted workspace so sync metadata
|
|
23
|
+
* never appears in the Relayfile tree.
|
|
24
|
+
*/
|
|
25
|
+
stateDir: string;
|
|
26
|
+
/** Path-scoped relayfile token (`relay_pa_*`). */
|
|
27
|
+
token: string;
|
|
28
|
+
/**
|
|
29
|
+
* Optional logical path scopes. The daemon accepts repeated
|
|
30
|
+
* `--remote-path` args; callers pass the scopes they care about here so the
|
|
31
|
+
* continuous sync never pulls a full workspace export.
|
|
32
|
+
*/
|
|
33
|
+
paths?: readonly string[];
|
|
34
|
+
/**
|
|
35
|
+
* Whether relayfile-mount should use the WebSocket event stream. Omit to use
|
|
36
|
+
* the CLI default. Set false to fall back to bounded `/fs/events` polling,
|
|
37
|
+
* which suits hosts that cannot hold a long-lived WebSocket request open.
|
|
38
|
+
*/
|
|
39
|
+
websocket?: boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Lazily materialize GitHub repo subtrees on first access instead of eagerly
|
|
42
|
+
* hydrating every repo file during bootstrap.
|
|
43
|
+
*/
|
|
44
|
+
lazyRepos?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Path to a JSON creds file (`{"token": "relay_pa_…", "mintedAt"?, "expiresAt"?}`)
|
|
47
|
+
* the daemon re-reads on 401 so a refreshed token heals the mount without a
|
|
48
|
+
* restart. Passed as the RELAYFILE_MOUNT_CREDS_FILE env var rather than a
|
|
49
|
+
* `--creds-file` flag for the same version-skew reason as
|
|
50
|
+
* RELAYFILE_MOUNT_LOCAL_LAYOUT above: pre-creds binaries reject an unknown
|
|
51
|
+
* flag but ignore the env var, so one spelling works across every binary a
|
|
52
|
+
* snapshot may carry. `--token` stays as the launch credential either way.
|
|
53
|
+
*/
|
|
54
|
+
credsFilePath?: string;
|
|
55
|
+
};
|
|
56
|
+
export type RelayfileMountInitialSyncOptions = RelayfileMountShellOptions & {
|
|
57
|
+
/**
|
|
58
|
+
* Optional timeout for a pre-handler sync. When set, the command uses
|
|
59
|
+
* coreutils `timeout`; if it is unavailable, the sync fails so callers can
|
|
60
|
+
* gracefully continue without risking an unbounded pre-handler sync.
|
|
61
|
+
*/
|
|
62
|
+
timeoutSeconds?: number;
|
|
63
|
+
/**
|
|
64
|
+
* Optional idle timeout for pre-handler sync. Unlike timeoutSeconds, this
|
|
65
|
+
* cancels only when mount state stops progressing for N seconds.
|
|
66
|
+
*/
|
|
67
|
+
idleTimeoutSeconds?: number;
|
|
68
|
+
};
|
|
69
|
+
export type RelayfileMountDaemonOptions = RelayfileMountShellOptions & {
|
|
70
|
+
/** Daemon sync interval. Defaults to `1s` for near-real-time writeback. */
|
|
71
|
+
interval?: string;
|
|
72
|
+
/** Path the daemon redirects stdout/stderr to. Defaults to `/tmp/relayfile-mount.log`. */
|
|
73
|
+
logPath?: string;
|
|
74
|
+
};
|
|
75
|
+
export type RelayfileMountShellTemplate = {
|
|
76
|
+
startShellTemplate: string;
|
|
77
|
+
flushShellTemplate: string;
|
|
78
|
+
pathArgsPlaceholderArg: string;
|
|
79
|
+
pathArgTemplate: string;
|
|
80
|
+
placeholders: {
|
|
81
|
+
baseUrl: string;
|
|
82
|
+
workspaceId: string;
|
|
83
|
+
localDir: string;
|
|
84
|
+
token: string;
|
|
85
|
+
pathArgs: string;
|
|
86
|
+
path: string;
|
|
87
|
+
};
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Bash command that starts a `relayfile-mount` daemon in the background and
|
|
91
|
+
* echoes the daemon PID on stdout (so callers can capture it and kill the
|
|
92
|
+
* process later). The daemon redirects all output to `logPath` so it does
|
|
93
|
+
* not pollute the caller's stdout/stderr.
|
|
94
|
+
*
|
|
95
|
+
* Mirrors the inline command originally in
|
|
96
|
+
* `executor.ts:startRelayfileMount` (#???) — see the file-level comment for
|
|
97
|
+
* the migration story.
|
|
98
|
+
*/
|
|
99
|
+
export declare function buildRelayfileMountStartShell(opts: RelayfileMountDaemonOptions): string;
|
|
100
|
+
/**
|
|
101
|
+
* Bash command that runs a one-time relayfile-mount sync (`--once`). Pushes
|
|
102
|
+
* any pending local writes upstream and exits. Use this:
|
|
103
|
+
* - As an explicit pre-handler sync so the mount mirror is populated
|
|
104
|
+
* before the handler reads from it (executor's initial-sync pattern).
|
|
105
|
+
* - As a post-handler flush before sandbox teardown so writeback drafts
|
|
106
|
+
* the handler created (e.g. `ctx.github.comment` files) reach
|
|
107
|
+
* relayfile cloud before the sandbox stops.
|
|
108
|
+
*/
|
|
109
|
+
export declare function buildRelayfileMountFlushShell(opts: RelayfileMountShellOptions): string;
|
|
110
|
+
/**
|
|
111
|
+
* Post-handler CLEANUP flush command — the durable cure for cleanup flushes
|
|
112
|
+
* that time out on large mirrors. Identical to
|
|
113
|
+
* {@link buildRelayfileMountFlushShell} EXCEPT the mode flag is the shell
|
|
114
|
+
* variable `$relayfile_mount_flush_mode`, which the lifecycle shell probes
|
|
115
|
+
* once into `--flush-outbox-once` (O(durable outbox); flushes only
|
|
116
|
+
* `.relay/outbox/pending` and exits WITHOUT a full-tree reconcile —
|
|
117
|
+
* scanLocalFiles/pushLocal/pullRemote — so a large mirror can't blow the
|
|
118
|
+
* cleanup `timeout`) on daemons that support it, else `--once` on older ones,
|
|
119
|
+
* whose behavior is unchanged. Emitted as a SINGLE command (the flag is one
|
|
120
|
+
* expanded token) so it stays valid inside the cleanup's `timeout Ns ...`
|
|
121
|
+
* wrapper — an inline `if/fi` would break `timeout`. The flag choice does not
|
|
122
|
+
* change the exit-code/`.relay/state.json` contract the cleanup gate reads: a
|
|
123
|
+
* real outbox-flush failure still exits nonzero and leaves pending, so the
|
|
124
|
+
* loud-fail stays load-bearing.
|
|
125
|
+
*/
|
|
126
|
+
export declare function buildRelayfileMountCleanupFlushShell(opts: RelayfileMountShellOptions): string;
|
|
127
|
+
export declare function buildRelayfileMountInitialSyncShell(opts: RelayfileMountInitialSyncOptions): string;
|
|
128
|
+
export declare const RELAYFILE_INITIAL_SYNC_SCRIPT_PATH = "/tmp/relayfile-initial-sync.sh";
|
|
129
|
+
export declare const RELAYFILE_INITIAL_SYNC_EXIT_PATH = "/tmp/relayfile-initial-sync.exit";
|
|
130
|
+
export declare const RELAYFILE_INITIAL_SYNC_LOG_PATH = "/tmp/relayfile-initial-sync.log";
|
|
131
|
+
export declare const RELAYFILE_INITIAL_SYNC_PID_PATH = "/tmp/relayfile-initial-sync.pid";
|
|
132
|
+
export type RelayfileMountInitialSyncRunOptions = {
|
|
133
|
+
runId?: string;
|
|
134
|
+
};
|
|
135
|
+
/**
|
|
136
|
+
* Bash that launches the (idle-watched) initial sync in the background and
|
|
137
|
+
* returns immediately, echoing the launcher PID. Daytona's exec path cannot
|
|
138
|
+
* host a single long-running command: the proxy read-times-out around 120s
|
|
139
|
+
* (a gateway timeout) and callers add their own client-side fail-fast, so a
|
|
140
|
+
* first materialization with real data (a populated /github tree, a cold
|
|
141
|
+
* workspace export) gets killed mid-sync. Instead the sync runs detached in
|
|
142
|
+
* the sandbox — preserving the in-sandbox idle watchdog — and callers poll
|
|
143
|
+
* `buildRelayfileMountInitialSyncStatusShell` with short execs until the
|
|
144
|
+
* exit sentinel appears.
|
|
145
|
+
*/
|
|
146
|
+
export declare function buildRelayfileMountInitialSyncBackgroundShell(opts: RelayfileMountInitialSyncOptions, runOptions?: RelayfileMountInitialSyncRunOptions): string;
|
|
147
|
+
/** Short, idempotent status probe for the backgrounded initial sync. */
|
|
148
|
+
export declare function buildRelayfileMountInitialSyncStatusShell(runOptions?: RelayfileMountInitialSyncRunOptions): string;
|
|
149
|
+
export declare function buildRelayfileMountInitialSyncKillShell(runOptions?: RelayfileMountInitialSyncRunOptions): string;
|
|
150
|
+
export declare function buildRelayfileMountInitialSyncLogTailShell(lines?: number, runOptions?: RelayfileMountInitialSyncRunOptions): string;
|
|
151
|
+
export type RelayfileMountInitialSyncStatus = {
|
|
152
|
+
state: "running";
|
|
153
|
+
} | {
|
|
154
|
+
state: "exited";
|
|
155
|
+
exitCode: number;
|
|
156
|
+
} | {
|
|
157
|
+
state: "unknown";
|
|
158
|
+
};
|
|
159
|
+
export declare function parseRelayfileMountInitialSyncStatus(output: string): RelayfileMountInitialSyncStatus;
|
|
160
|
+
export declare function buildRelayfileMountPathArgsShell(paths: readonly string[]): string;
|
|
161
|
+
export declare function buildRelayfileMountShellTemplate(placeholders: Partial<RelayfileMountShellTemplate["placeholders"]> | undefined, options: Pick<RelayfileMountDaemonOptions, "stateDir"> & Partial<Pick<RelayfileMountDaemonOptions, "interval" | "websocket">>): RelayfileMountShellTemplate;
|
|
162
|
+
//# sourceMappingURL=mount-script.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount-script.d.ts","sourceRoot":"","sources":["../src/mount-script.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,461 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shell snippets for running the `relayfile-mount` daemon inside a sandbox.
|
|
3
|
+
*
|
|
4
|
+
* Callers that drive the mount — a command-at-a-time executor, a runner that
|
|
5
|
+
* submits one multi-line script, and a generator that emits sandbox-resident
|
|
6
|
+
* bootstrap JS — would otherwise each hand-roll near-identical bash. This
|
|
7
|
+
* module is the single builder for all of them, and owns the command
|
|
8
|
+
* templates the bootstrap generator embeds.
|
|
9
|
+
*
|
|
10
|
+
* The contract: helpers take primitives, do their own shell quoting, and
|
|
11
|
+
* return ready-to-run bash. Callers must not re-quote.
|
|
12
|
+
*/
|
|
13
|
+
/**
|
|
14
|
+
* Pin the daemon's local layout to `scoped` (remote path appended under
|
|
15
|
+
* --local-dir) on every invocation.
|
|
16
|
+
*
|
|
17
|
+
* Newer daemon releases made the layout explicit: they default to `exact`
|
|
18
|
+
* (--local-dir IS the mirror root) and hard-error on multiple --remote-path
|
|
19
|
+
* values unless `--local-layout=scoped`. All builders in this module
|
|
20
|
+
* pre-compute an UNSCOPED local dir (see `unscopedLocalDir`) and rely on the
|
|
21
|
+
* daemon appending the remote path, which is what older binaries did
|
|
22
|
+
* implicitly. Without this pin, a newer binary breaks two ways: multi-path
|
|
23
|
+
* mounts fail at startup, and single-path mounts silently mirror at the wrong
|
|
24
|
+
* depth.
|
|
25
|
+
*
|
|
26
|
+
* Pinned via env var rather than the `--local-layout` flag on purpose: older
|
|
27
|
+
* binaries reject the unknown flag but ignore the env var, while newer ones
|
|
28
|
+
* read RELAYFILE_MOUNT_LOCAL_LAYOUT as the flag default. One spelling
|
|
29
|
+
* therefore yields an identical on-disk layout across every binary version a
|
|
30
|
+
* sandbox image may carry — which matters because the image and this code are
|
|
31
|
+
* versioned independently. The pathless case is safe: scoped layout with
|
|
32
|
+
* remote path "/" is a no-op join (normalizeMountRemotePath("/") → localDir).
|
|
33
|
+
*
|
|
34
|
+
* Spelled `env VAR=… relayfile-mount` (not the bare `VAR=… relayfile-mount`
|
|
35
|
+
* shell form) because initial-sync commands get wrapped by coreutils
|
|
36
|
+
* `timeout`, which execs its argument instead of shell-parsing it — a bare
|
|
37
|
+
* assignment prefix would make `timeout '20s' VAR=… relayfile-mount` fail
|
|
38
|
+
* with "failed to run command". `env` is a real executable, so the same
|
|
39
|
+
* prefix composes under `timeout`, `nohup`, and direct execution alike.
|
|
40
|
+
*/
|
|
41
|
+
const SCOPED_LOCAL_LAYOUT_ENV = "env RELAYFILE_MOUNT_LOCAL_LAYOUT=scoped ";
|
|
42
|
+
/**
|
|
43
|
+
* `env`-prefix for every relayfile-mount invocation: always pins the scoped
|
|
44
|
+
* local layout, and when the caller provides a creds file, also points the
|
|
45
|
+
* daemon at it via RELAYFILE_MOUNT_CREDS_FILE (see `credsFilePath` docs for
|
|
46
|
+
* the version-skew rationale).
|
|
47
|
+
*/
|
|
48
|
+
function mountEnvPrefix(opts) {
|
|
49
|
+
if (!opts.credsFilePath) {
|
|
50
|
+
return SCOPED_LOCAL_LAYOUT_ENV;
|
|
51
|
+
}
|
|
52
|
+
return `env RELAYFILE_MOUNT_LOCAL_LAYOUT=scoped RELAYFILE_MOUNT_CREDS_FILE=${shellQuote(opts.credsFilePath)} `;
|
|
53
|
+
}
|
|
54
|
+
const DEFAULT_TEMPLATE_PLACEHOLDERS = {
|
|
55
|
+
baseUrl: "__relayfile_base_url__",
|
|
56
|
+
workspaceId: "__relayfile_workspace_id__",
|
|
57
|
+
localDir: "__relayfile_local_dir__",
|
|
58
|
+
token: "__relayfile_token__",
|
|
59
|
+
pathArgs: "__relayfile_path_args__",
|
|
60
|
+
path: "__relayfile_path__",
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Bash command that starts a `relayfile-mount` daemon in the background and
|
|
64
|
+
* echoes the daemon PID on stdout (so callers can capture it and kill the
|
|
65
|
+
* process later). The daemon redirects all output to `logPath` so it does
|
|
66
|
+
* not pollute the caller's stdout/stderr.
|
|
67
|
+
*
|
|
68
|
+
* Mirrors the inline command originally in
|
|
69
|
+
* `executor.ts:startRelayfileMount` (#???) — see the file-level comment for
|
|
70
|
+
* the migration story.
|
|
71
|
+
*/
|
|
72
|
+
export function buildRelayfileMountStartShell(opts) {
|
|
73
|
+
const scopedRoots = scopedRemoteRoots(opts.paths ?? [], { allowProviderRoot: true });
|
|
74
|
+
const localDir = unscopedLocalDir(opts.localDir, scopedRoots);
|
|
75
|
+
const args = buildMountArgs({ ...opts, localDir, paths: scopedRoots });
|
|
76
|
+
const interval = opts.interval ?? "1s";
|
|
77
|
+
const logPath = opts.logPath ?? "/tmp/relayfile-mount.log";
|
|
78
|
+
const startShell = [
|
|
79
|
+
`${mountEnvPrefix(opts)}nohup relayfile-mount`,
|
|
80
|
+
...args,
|
|
81
|
+
`--interval ${shellQuote(interval)}`,
|
|
82
|
+
`> ${shellQuote(logPath)} 2>&1 & echo $!`,
|
|
83
|
+
].join(" ");
|
|
84
|
+
if (scopedRoots.length <= 1) {
|
|
85
|
+
return startShell;
|
|
86
|
+
}
|
|
87
|
+
// `paths-file` is the new-daemon sentinel: the release that added it also
|
|
88
|
+
// added repeated `--remote-path` support. The Go flag package prints
|
|
89
|
+
// `-paths-file` in help while the command accepts `--paths-file`, so probe
|
|
90
|
+
// for the flag name without assuming dash style.
|
|
91
|
+
return [
|
|
92
|
+
"if relayfile-mount --help 2>&1 | grep -q -- 'paths-file'; then",
|
|
93
|
+
`${startShell};`,
|
|
94
|
+
"else",
|
|
95
|
+
"echo 'relayfile-mount multi-path filters unsupported; starting one daemon per remote path' >&2;",
|
|
96
|
+
`${buildRelayfileMountFallbackStartShell({ ...opts, paths: scopedRoots })};`,
|
|
97
|
+
"fi",
|
|
98
|
+
].join(" ");
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Bash command that runs a one-time relayfile-mount sync (`--once`). Pushes
|
|
102
|
+
* any pending local writes upstream and exits. Use this:
|
|
103
|
+
* - As an explicit pre-handler sync so the mount mirror is populated
|
|
104
|
+
* before the handler reads from it (executor's initial-sync pattern).
|
|
105
|
+
* - As a post-handler flush before sandbox teardown so writeback drafts
|
|
106
|
+
* the handler created (e.g. `ctx.github.comment` files) reach
|
|
107
|
+
* relayfile cloud before the sandbox stops.
|
|
108
|
+
*/
|
|
109
|
+
export function buildRelayfileMountFlushShell(opts) {
|
|
110
|
+
const scopedRoots = scopedRemoteRoots(opts.paths ?? [], { allowProviderRoot: true });
|
|
111
|
+
const localDir = unscopedLocalDir(opts.localDir, scopedRoots);
|
|
112
|
+
const args = buildMountArgs({ ...opts, localDir, paths: scopedRoots });
|
|
113
|
+
return [`${mountEnvPrefix(opts)}relayfile-mount --once`, ...args].join(" ");
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Post-handler CLEANUP flush command — the durable cure for cleanup flushes
|
|
117
|
+
* that time out on large mirrors. Identical to
|
|
118
|
+
* {@link buildRelayfileMountFlushShell} EXCEPT the mode flag is the shell
|
|
119
|
+
* variable `$relayfile_mount_flush_mode`, which the lifecycle shell probes
|
|
120
|
+
* once into `--flush-outbox-once` (O(durable outbox); flushes only
|
|
121
|
+
* `.relay/outbox/pending` and exits WITHOUT a full-tree reconcile —
|
|
122
|
+
* scanLocalFiles/pushLocal/pullRemote — so a large mirror can't blow the
|
|
123
|
+
* cleanup `timeout`) on daemons that support it, else `--once` on older ones,
|
|
124
|
+
* whose behavior is unchanged. Emitted as a SINGLE command (the flag is one
|
|
125
|
+
* expanded token) so it stays valid inside the cleanup's `timeout Ns ...`
|
|
126
|
+
* wrapper — an inline `if/fi` would break `timeout`. The flag choice does not
|
|
127
|
+
* change the exit-code/`.relay/state.json` contract the cleanup gate reads: a
|
|
128
|
+
* real outbox-flush failure still exits nonzero and leaves pending, so the
|
|
129
|
+
* loud-fail stays load-bearing.
|
|
130
|
+
*/
|
|
131
|
+
export function buildRelayfileMountCleanupFlushShell(opts) {
|
|
132
|
+
const scopedRoots = scopedRemoteRoots(opts.paths ?? [], { allowProviderRoot: true });
|
|
133
|
+
const localDir = unscopedLocalDir(opts.localDir, scopedRoots);
|
|
134
|
+
const args = buildMountArgs({ ...opts, localDir, paths: scopedRoots });
|
|
135
|
+
return [
|
|
136
|
+
`${mountEnvPrefix(opts)}relayfile-mount "$relayfile_mount_flush_mode"`,
|
|
137
|
+
...args,
|
|
138
|
+
].join(" ");
|
|
139
|
+
}
|
|
140
|
+
export function buildRelayfileMountInitialSyncShell(opts) {
|
|
141
|
+
const commands = buildInitialSyncCommands(opts);
|
|
142
|
+
const command = commands.join(" && ");
|
|
143
|
+
if (opts.idleTimeoutSeconds && opts.idleTimeoutSeconds > 0) {
|
|
144
|
+
return buildIdleWatchedCommand(command, initialSyncProgressFiles(opts), opts.idleTimeoutSeconds);
|
|
145
|
+
}
|
|
146
|
+
if (!opts.timeoutSeconds || opts.timeoutSeconds <= 0) {
|
|
147
|
+
return command;
|
|
148
|
+
}
|
|
149
|
+
const timeout = `${Math.ceil(opts.timeoutSeconds)}s`;
|
|
150
|
+
const timedCommand = commands
|
|
151
|
+
.map((entry) => `timeout ${shellQuote(timeout)} ${entry}`)
|
|
152
|
+
.join(" && ");
|
|
153
|
+
return [
|
|
154
|
+
"{",
|
|
155
|
+
"if command -v timeout >/dev/null 2>&1; then",
|
|
156
|
+
`${timedCommand};`,
|
|
157
|
+
"else",
|
|
158
|
+
"echo 'timeout command unavailable for relayfile initial sync' >&2;",
|
|
159
|
+
"false;",
|
|
160
|
+
"fi;",
|
|
161
|
+
"}",
|
|
162
|
+
].join(" ");
|
|
163
|
+
}
|
|
164
|
+
export const RELAYFILE_INITIAL_SYNC_SCRIPT_PATH = "/tmp/relayfile-initial-sync.sh";
|
|
165
|
+
export const RELAYFILE_INITIAL_SYNC_EXIT_PATH = "/tmp/relayfile-initial-sync.exit";
|
|
166
|
+
export const RELAYFILE_INITIAL_SYNC_LOG_PATH = "/tmp/relayfile-initial-sync.log";
|
|
167
|
+
export const RELAYFILE_INITIAL_SYNC_PID_PATH = "/tmp/relayfile-initial-sync.pid";
|
|
168
|
+
function relayfileInitialSyncPath(path, runId) {
|
|
169
|
+
if (!runId) {
|
|
170
|
+
return path;
|
|
171
|
+
}
|
|
172
|
+
const safeRunId = runId.replace(/[^A-Za-z0-9_.-]/g, "_");
|
|
173
|
+
return `${path}.${safeRunId}`;
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Bash that launches the (idle-watched) initial sync in the background and
|
|
177
|
+
* returns immediately, echoing the launcher PID. Daytona's exec path cannot
|
|
178
|
+
* host a single long-running command: the proxy read-times-out around 120s
|
|
179
|
+
* (a gateway timeout) and callers add their own client-side fail-fast, so a
|
|
180
|
+
* first materialization with real data (a populated /github tree, a cold
|
|
181
|
+
* workspace export) gets killed mid-sync. Instead the sync runs detached in
|
|
182
|
+
* the sandbox — preserving the in-sandbox idle watchdog — and callers poll
|
|
183
|
+
* `buildRelayfileMountInitialSyncStatusShell` with short execs until the
|
|
184
|
+
* exit sentinel appears.
|
|
185
|
+
*/
|
|
186
|
+
export function buildRelayfileMountInitialSyncBackgroundShell(opts, runOptions = {}) {
|
|
187
|
+
const scriptPath = relayfileInitialSyncPath(RELAYFILE_INITIAL_SYNC_SCRIPT_PATH, runOptions.runId);
|
|
188
|
+
const exitPath = relayfileInitialSyncPath(RELAYFILE_INITIAL_SYNC_EXIT_PATH, runOptions.runId);
|
|
189
|
+
const logPath = relayfileInitialSyncPath(RELAYFILE_INITIAL_SYNC_LOG_PATH, runOptions.runId);
|
|
190
|
+
const pidPath = relayfileInitialSyncPath(RELAYFILE_INITIAL_SYNC_PID_PATH, runOptions.runId);
|
|
191
|
+
const syncShell = buildRelayfileMountInitialSyncShell(opts);
|
|
192
|
+
const runner = [
|
|
193
|
+
"if command -v setsid >/dev/null 2>&1; then",
|
|
194
|
+
` setsid sh ${shellQuote(scriptPath)} > ${shellQuote(logPath)} 2>&1 &`,
|
|
195
|
+
"else",
|
|
196
|
+
` sh ${shellQuote(scriptPath)} > ${shellQuote(logPath)} 2>&1 &`,
|
|
197
|
+
"fi;",
|
|
198
|
+
"relayfile_initial_sync_pid=$!;",
|
|
199
|
+
`echo "$relayfile_initial_sync_pid" > ${shellQuote(pidPath)};`,
|
|
200
|
+
'wait "$relayfile_initial_sync_pid";',
|
|
201
|
+
`echo $? > ${shellQuote(exitPath)}`,
|
|
202
|
+
].join(" ");
|
|
203
|
+
return [
|
|
204
|
+
"set -e",
|
|
205
|
+
`rm -f ${shellQuote(scriptPath)} ${shellQuote(exitPath)} ${shellQuote(logPath)} ${shellQuote(pidPath)} &&`,
|
|
206
|
+
// Quoted heredoc delimiter: the sync shell lands in the script file
|
|
207
|
+
// verbatim, with no re-quoting hazards from nesting it in `sh -c`.
|
|
208
|
+
`cat > ${shellQuote(scriptPath)} <<'RELAYFILE_INITIAL_SYNC_EOF'
|
|
209
|
+
${syncShell}
|
|
210
|
+
RELAYFILE_INITIAL_SYNC_EOF
|
|
211
|
+
`,
|
|
212
|
+
`nohup sh -c ${shellQuote(runner)} >/dev/null 2>&1 & echo $!`,
|
|
213
|
+
].join("\n");
|
|
214
|
+
}
|
|
215
|
+
const RELAYFILE_INITIAL_SYNC_EXIT_MARKER = "relayfile-initial-sync-exit:";
|
|
216
|
+
const RELAYFILE_INITIAL_SYNC_RUNNING_MARKER = "relayfile-initial-sync-running";
|
|
217
|
+
/** Short, idempotent status probe for the backgrounded initial sync. */
|
|
218
|
+
export function buildRelayfileMountInitialSyncStatusShell(runOptions = {}) {
|
|
219
|
+
const exitPath = relayfileInitialSyncPath(RELAYFILE_INITIAL_SYNC_EXIT_PATH, runOptions.runId);
|
|
220
|
+
const pidPath = relayfileInitialSyncPath(RELAYFILE_INITIAL_SYNC_PID_PATH, runOptions.runId);
|
|
221
|
+
return [
|
|
222
|
+
`if [ -f ${shellQuote(exitPath)} ]; then`,
|
|
223
|
+
`echo "${RELAYFILE_INITIAL_SYNC_EXIT_MARKER}$(cat ${shellQuote(exitPath)})";`,
|
|
224
|
+
`elif [ -f ${shellQuote(pidPath)} ]; then`,
|
|
225
|
+
`relayfile_initial_sync_pid=$(cat ${shellQuote(pidPath)} 2>/dev/null || true);`,
|
|
226
|
+
'case "$relayfile_initial_sync_pid" in',
|
|
227
|
+
` ''|*[!0-9]*) echo ${RELAYFILE_INITIAL_SYNC_RUNNING_MARKER} ;;`,
|
|
228
|
+
' *)',
|
|
229
|
+
' if kill -0 "$relayfile_initial_sync_pid" 2>/dev/null; then',
|
|
230
|
+
` echo ${RELAYFILE_INITIAL_SYNC_RUNNING_MARKER};`,
|
|
231
|
+
" else",
|
|
232
|
+
` echo "${RELAYFILE_INITIAL_SYNC_EXIT_MARKER}127";`,
|
|
233
|
+
" fi",
|
|
234
|
+
" ;;",
|
|
235
|
+
"esac",
|
|
236
|
+
"else",
|
|
237
|
+
`echo ${RELAYFILE_INITIAL_SYNC_RUNNING_MARKER};`,
|
|
238
|
+
"fi",
|
|
239
|
+
].join(" ");
|
|
240
|
+
}
|
|
241
|
+
export function buildRelayfileMountInitialSyncKillShell(runOptions = {}) {
|
|
242
|
+
const pidPath = relayfileInitialSyncPath(RELAYFILE_INITIAL_SYNC_PID_PATH, runOptions.runId);
|
|
243
|
+
return [
|
|
244
|
+
`if [ -f ${shellQuote(pidPath)} ]; then`,
|
|
245
|
+
`relayfile_initial_sync_pid=$(cat ${shellQuote(pidPath)} 2>/dev/null || true);`,
|
|
246
|
+
'case "$relayfile_initial_sync_pid" in',
|
|
247
|
+
" ''|*[!0-9]*) ;;",
|
|
248
|
+
' *)',
|
|
249
|
+
' kill -TERM -- "-$relayfile_initial_sync_pid" 2>/dev/null || true;',
|
|
250
|
+
' kill "$relayfile_initial_sync_pid" 2>/dev/null || true',
|
|
251
|
+
" ;;",
|
|
252
|
+
"esac",
|
|
253
|
+
"fi",
|
|
254
|
+
].join(" ");
|
|
255
|
+
}
|
|
256
|
+
export function buildRelayfileMountInitialSyncLogTailShell(lines = 40, runOptions = {}) {
|
|
257
|
+
const logPath = relayfileInitialSyncPath(RELAYFILE_INITIAL_SYNC_LOG_PATH, runOptions.runId);
|
|
258
|
+
return `tail -n ${Math.max(1, Math.floor(lines))} ${shellQuote(logPath)} 2>/dev/null || true`;
|
|
259
|
+
}
|
|
260
|
+
export function parseRelayfileMountInitialSyncStatus(output) {
|
|
261
|
+
const match = output.match(new RegExp(`${RELAYFILE_INITIAL_SYNC_EXIT_MARKER}(-?\\d+)`));
|
|
262
|
+
const exitCode = match?.[1];
|
|
263
|
+
if (exitCode !== undefined) {
|
|
264
|
+
return { state: "exited", exitCode: Number.parseInt(exitCode, 10) };
|
|
265
|
+
}
|
|
266
|
+
if (output.includes(RELAYFILE_INITIAL_SYNC_RUNNING_MARKER)) {
|
|
267
|
+
return { state: "running" };
|
|
268
|
+
}
|
|
269
|
+
return { state: "unknown" };
|
|
270
|
+
}
|
|
271
|
+
export function buildRelayfileMountPathArgsShell(paths) {
|
|
272
|
+
return scopedRemoteRoots(paths, { allowProviderRoot: true })
|
|
273
|
+
.map(buildMountPathArg)
|
|
274
|
+
.join("");
|
|
275
|
+
}
|
|
276
|
+
export function buildRelayfileMountShellTemplate(placeholders = {},
|
|
277
|
+
// `stateDir` is required (sandbox-image specific); `interval` / `websocket`
|
|
278
|
+
// stay optional.
|
|
279
|
+
options) {
|
|
280
|
+
const resolved = { ...DEFAULT_TEMPLATE_PLACEHOLDERS, ...placeholders };
|
|
281
|
+
const baseOpts = {
|
|
282
|
+
baseUrl: resolved.baseUrl,
|
|
283
|
+
workspaceId: resolved.workspaceId,
|
|
284
|
+
localDir: resolved.localDir,
|
|
285
|
+
token: resolved.token,
|
|
286
|
+
...options,
|
|
287
|
+
};
|
|
288
|
+
const pathArgsPlaceholderArg = buildMountPathArg(resolved.pathArgs);
|
|
289
|
+
const pathArgTemplate = buildMountPathArg(resolved.path);
|
|
290
|
+
const startShellWithoutPaths = buildRelayfileMountStartShell(baseOpts);
|
|
291
|
+
const flushShellWithoutPaths = buildRelayfileMountFlushShell(baseOpts);
|
|
292
|
+
return {
|
|
293
|
+
startShellTemplate: insertStartTemplatePathArgs(startShellWithoutPaths, pathArgsPlaceholderArg),
|
|
294
|
+
flushShellTemplate: `${flushShellWithoutPaths}${pathArgsPlaceholderArg}`,
|
|
295
|
+
pathArgsPlaceholderArg,
|
|
296
|
+
pathArgTemplate,
|
|
297
|
+
placeholders: resolved,
|
|
298
|
+
};
|
|
299
|
+
}
|
|
300
|
+
function buildMountArgs(opts) {
|
|
301
|
+
return [
|
|
302
|
+
`--base-url ${shellQuote(opts.baseUrl)}`,
|
|
303
|
+
`--workspace ${shellQuote(opts.workspaceId)}`,
|
|
304
|
+
`--local-dir ${shellQuote(opts.localDir)}`,
|
|
305
|
+
`--state-dir ${shellQuote(opts.stateDir)}`,
|
|
306
|
+
`--token ${shellQuote(opts.token)}`,
|
|
307
|
+
...(opts.websocket === false ? ["--websocket=false"] : []),
|
|
308
|
+
...(opts.lazyRepos ? ["--lazy-repos"] : []),
|
|
309
|
+
...scopedRemoteRoots(opts.paths ?? [], { allowProviderRoot: true })
|
|
310
|
+
.map((path) => `--remote-path ${shellQuote(path)}`),
|
|
311
|
+
];
|
|
312
|
+
}
|
|
313
|
+
function buildInitialSyncCommands(opts) {
|
|
314
|
+
const roots = scopedRemoteRoots(opts.paths ?? []);
|
|
315
|
+
if (roots.length === 0) {
|
|
316
|
+
return [buildRelayfileMountFlushShell(opts)];
|
|
317
|
+
}
|
|
318
|
+
const localDir = unscopedLocalDir(opts.localDir, roots);
|
|
319
|
+
return roots
|
|
320
|
+
.map((remoteRoot, index) => {
|
|
321
|
+
const args = [
|
|
322
|
+
...buildMountArgs({ ...opts, localDir, paths: [] }),
|
|
323
|
+
`--remote-path ${shellQuote(remoteRoot)}`,
|
|
324
|
+
`--state-file ${shellQuote(`/tmp/relayfile-mount-initial-sync-${index}.json`)}`,
|
|
325
|
+
];
|
|
326
|
+
return [`${mountEnvPrefix(opts)}relayfile-mount --once`, ...args].join(" ");
|
|
327
|
+
});
|
|
328
|
+
}
|
|
329
|
+
function initialSyncProgressFiles(opts) {
|
|
330
|
+
const roots = scopedRemoteRoots(opts.paths ?? []);
|
|
331
|
+
if (roots.length === 0) {
|
|
332
|
+
const stateDir = opts.stateDir;
|
|
333
|
+
return [
|
|
334
|
+
`${stateDir.replace(/\/+$/u, "")}/.relayfile-mount-state.json`,
|
|
335
|
+
];
|
|
336
|
+
}
|
|
337
|
+
return roots.map((_remoteRoot, index) => `/tmp/relayfile-mount-initial-sync-${index}.json`);
|
|
338
|
+
}
|
|
339
|
+
function buildIdleWatchedCommand(command, progressFiles, idleTimeoutSeconds) {
|
|
340
|
+
const idle = Math.max(1, Math.ceil(idleTimeoutSeconds));
|
|
341
|
+
const poll = Math.max(1, Math.min(5, Math.floor(idle / 3) || 1));
|
|
342
|
+
const progressArgs = progressFiles.map(shellQuote).join(" ");
|
|
343
|
+
return [
|
|
344
|
+
"(",
|
|
345
|
+
`set -- ${progressArgs};`,
|
|
346
|
+
"relayfile_mount_marker=$(mktemp /tmp/relayfile-mount-progress.XXXXXX) || exit 1;",
|
|
347
|
+
'touch "$relayfile_mount_marker";',
|
|
348
|
+
`(${command}) &`,
|
|
349
|
+
"relayfile_mount_sync_pid=$!;",
|
|
350
|
+
"relayfile_mount_status=0;",
|
|
351
|
+
'while kill -0 "$relayfile_mount_sync_pid" 2>/dev/null; do',
|
|
352
|
+
' for relayfile_mount_progress_file in "$@"; do',
|
|
353
|
+
' if [ -f "$relayfile_mount_progress_file" ] && [ "$relayfile_mount_progress_file" -nt "$relayfile_mount_marker" ]; then',
|
|
354
|
+
' touch "$relayfile_mount_marker";',
|
|
355
|
+
" fi;",
|
|
356
|
+
" done;",
|
|
357
|
+
" relayfile_mount_now=$(date +%s);",
|
|
358
|
+
' relayfile_mount_marker_mtime=$(date -r "$relayfile_mount_marker" +%s 2>/dev/null || stat -c %Y "$relayfile_mount_marker" 2>/dev/null || echo "$relayfile_mount_now");',
|
|
359
|
+
` if [ $((relayfile_mount_now - relayfile_mount_marker_mtime)) -ge ${idle} ]; then`,
|
|
360
|
+
` echo 'relayfile initial sync made no progress for ${idle}s; canceling' >&2;`,
|
|
361
|
+
' kill "$relayfile_mount_sync_pid" 2>/dev/null || true;',
|
|
362
|
+
' wait "$relayfile_mount_sync_pid" 2>/dev/null || true;',
|
|
363
|
+
' rm -f "$relayfile_mount_marker";',
|
|
364
|
+
" exit 124;",
|
|
365
|
+
" fi;",
|
|
366
|
+
` sleep ${poll};`,
|
|
367
|
+
"done;",
|
|
368
|
+
'wait "$relayfile_mount_sync_pid" || relayfile_mount_status=$?;',
|
|
369
|
+
'rm -f "$relayfile_mount_marker";',
|
|
370
|
+
'exit "$relayfile_mount_status";',
|
|
371
|
+
")",
|
|
372
|
+
].join(" ");
|
|
373
|
+
}
|
|
374
|
+
function scopedRemoteRoots(paths, options = {}) {
|
|
375
|
+
const roots = new Set();
|
|
376
|
+
for (const path of paths) {
|
|
377
|
+
const root = scopedRemoteRoot(path, options);
|
|
378
|
+
if (root) {
|
|
379
|
+
roots.add(root);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
return [...roots].sort();
|
|
383
|
+
}
|
|
384
|
+
function scopedRemoteRoot(path, options = {}) {
|
|
385
|
+
const trimmed = path.trim();
|
|
386
|
+
if (!trimmed.startsWith("/")) {
|
|
387
|
+
return null;
|
|
388
|
+
}
|
|
389
|
+
const withoutGlob = trimmed.endsWith("/**") ? trimmed.slice(0, -3) : trimmed;
|
|
390
|
+
const normalized = withoutGlob.replace(/\/{2,}/g, "/").replace(/\/$/u, "");
|
|
391
|
+
if (!normalized || normalized === "/" || normalized.includes("*")) {
|
|
392
|
+
return null;
|
|
393
|
+
}
|
|
394
|
+
if (!options.allowProviderRoot && normalized.slice(1).split("/").length < 2) {
|
|
395
|
+
return null;
|
|
396
|
+
}
|
|
397
|
+
return normalized;
|
|
398
|
+
}
|
|
399
|
+
function unscopedLocalDir(localRoot, remoteRoots) {
|
|
400
|
+
let normalizedRoot = localRoot.replace(/\/+$/u, "");
|
|
401
|
+
const suffixes = remoteRoots
|
|
402
|
+
.map((remoteRoot) => remoteRoot.replace(/^\/+/u, "").replace(/\/+$/u, ""))
|
|
403
|
+
.filter(Boolean)
|
|
404
|
+
.sort((left, right) => right.length - left.length);
|
|
405
|
+
for (const suffix of suffixes) {
|
|
406
|
+
if (!suffix) {
|
|
407
|
+
continue;
|
|
408
|
+
}
|
|
409
|
+
if (normalizedRoot === suffix) {
|
|
410
|
+
normalizedRoot = "";
|
|
411
|
+
continue;
|
|
412
|
+
}
|
|
413
|
+
if (normalizedRoot.endsWith(`/${suffix}`)) {
|
|
414
|
+
normalizedRoot = normalizedRoot.slice(0, -suffix.length).replace(/\/+$/u, "");
|
|
415
|
+
continue;
|
|
416
|
+
}
|
|
417
|
+
const nestedSuffix = `/${suffix}/`;
|
|
418
|
+
const nestedIndex = normalizedRoot.indexOf(nestedSuffix);
|
|
419
|
+
if (nestedIndex !== -1) {
|
|
420
|
+
normalizedRoot = normalizedRoot.slice(0, nestedIndex).replace(/\/+$/u, "");
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
return normalizedRoot || "/";
|
|
424
|
+
}
|
|
425
|
+
function buildMountPathArg(path) {
|
|
426
|
+
return ` --remote-path ${shellQuote(path)}`;
|
|
427
|
+
}
|
|
428
|
+
function insertStartTemplatePathArgs(shell, pathArgsPlaceholderArg) {
|
|
429
|
+
return shell.replace(" --interval ", `${pathArgsPlaceholderArg} --interval `);
|
|
430
|
+
}
|
|
431
|
+
function buildRelayfileMountFallbackStartShell(opts) {
|
|
432
|
+
const roots = scopedRemoteRoots(opts.paths ?? [], { allowProviderRoot: true });
|
|
433
|
+
const localDir = unscopedLocalDir(opts.localDir, roots);
|
|
434
|
+
const interval = opts.interval ?? "1s";
|
|
435
|
+
const logPath = opts.logPath ?? "/tmp/relayfile-mount.log";
|
|
436
|
+
const starts = roots.map((root) => [
|
|
437
|
+
`${mountEnvPrefix(opts)}relayfile-mount`,
|
|
438
|
+
...buildMountArgs({ ...opts, localDir, paths: [root] }),
|
|
439
|
+
`--interval ${shellQuote(interval)}`,
|
|
440
|
+
`>> ${shellQuote(logPath)} 2>&1 &`,
|
|
441
|
+
"relayfile_mount_pids=\"$relayfile_mount_pids $!\";",
|
|
442
|
+
].join(" "));
|
|
443
|
+
return [
|
|
444
|
+
"(",
|
|
445
|
+
"relayfile_mount_pids='';",
|
|
446
|
+
...starts,
|
|
447
|
+
"trap 'kill $relayfile_mount_pids 2>/dev/null || true; wait' INT TERM EXIT;",
|
|
448
|
+
"wait",
|
|
449
|
+
") >/dev/null 2>&1 & echo $!",
|
|
450
|
+
].join(" ");
|
|
451
|
+
}
|
|
452
|
+
/**
|
|
453
|
+
* POSIX-safe single-quote escape. `foo` → `'foo'`, `foo's` → `'foo'\''s'`.
|
|
454
|
+
* Conservative — quotes every value, even ones that don't strictly need it,
|
|
455
|
+
* so callers never have to think about characters that would otherwise be
|
|
456
|
+
* shell-interpreted (spaces, `$`, etc.).
|
|
457
|
+
*/
|
|
458
|
+
function shellQuote(value) {
|
|
459
|
+
return `'${value.replace(/'/g, "'\\''")}'`;
|
|
460
|
+
}
|
|
461
|
+
//# sourceMappingURL=mount-script.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mount-script.js","sourceRoot":"","sources":["../src/mount-script.ts"],"names":[],"mappings":"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"}
|