@boxes-dev/dvb-runtime 1.0.181 → 1.0.183

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/bin/dvbd.cjs CHANGED
@@ -88612,8 +88612,8 @@ var init_otel = __esm({
88612
88612
  return trimmed && trimmed.length > 0 ? trimmed : void 0;
88613
88613
  };
88614
88614
  readBuildMetadata = () => {
88615
- const rawPackageVersion = "1.0.181";
88616
- const rawGitSha = "d32c924b084cca4cd3fe428533a251326c0ba0be";
88615
+ const rawPackageVersion = "1.0.183";
88616
+ const rawGitSha = "91c94b669da1929b3b7db136d8ccbb5e06200520";
88617
88617
  const packageVersion = typeof rawPackageVersion === "string" ? rawPackageVersion : void 0;
88618
88618
  const gitSha = typeof rawGitSha === "string" ? rawGitSha : void 0;
88619
88619
  return { packageVersion, gitSha };
@@ -120734,9 +120734,9 @@ var init_sentry = __esm({
120734
120734
  sentryEnabled = false;
120735
120735
  uncaughtExceptionMonitorInstalled = false;
120736
120736
  readBuildMetadata2 = () => {
120737
- const rawPackageVersion = "1.0.181";
120738
- const rawGitSha = "d32c924b084cca4cd3fe428533a251326c0ba0be";
120739
- const rawSentryRelease = "boxes-dev-dvb@1.0.181+d32c924b084cca4cd3fe428533a251326c0ba0be";
120737
+ const rawPackageVersion = "1.0.183";
120738
+ const rawGitSha = "91c94b669da1929b3b7db136d8ccbb5e06200520";
120739
+ const rawSentryRelease = "boxes-dev-dvb@1.0.183+91c94b669da1929b3b7db136d8ccbb5e06200520";
120740
120740
  const packageVersion = typeof rawPackageVersion === "string" ? rawPackageVersion : void 0;
120741
120741
  const gitSha = typeof rawGitSha === "string" ? rawGitSha : void 0;
120742
120742
  const sentryRelease = typeof rawSentryRelease === "string" ? rawSentryRelease : void 0;
@@ -124679,7 +124679,7 @@ var init_packageVersion = __esm({
124679
124679
  return import_node_path7.default.join(process.cwd(), "dvb");
124680
124680
  };
124681
124681
  readEmbeddedPackageVersion = () => {
124682
- const raw = "1.0.181";
124682
+ const raw = "1.0.183";
124683
124683
  return trimVersion(raw);
124684
124684
  };
124685
124685
  readNearestPackageMetadata = (basePath) => {
@@ -1,4 +1,4 @@
1
- declare const CODEX_INIT_EXEC_MODEL = "gpt-5.2-codex";
1
+ declare const CODEX_INIT_EXEC_MODEL = "gpt-5.4";
2
2
  declare const CODEX_INIT_EXEC_REASONING_EFFORT = "high";
3
3
  declare const buildCodexInitExecArgs: () => string[];
4
4
  export { CODEX_INIT_EXEC_MODEL, CODEX_INIT_EXEC_REASONING_EFFORT, buildCodexInitExecArgs, };
@@ -1 +1 @@
1
- {"version":3,"file":"execConfig.d.ts","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/execConfig.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,qBAAqB,kBAAkB,CAAC;AAC9C,QAAA,MAAM,gCAAgC,SAAS,CAAC;AAEhD,QAAA,MAAM,sBAAsB,gBAK3B,CAAC;AAEF,OAAO,EACL,qBAAqB,EACrB,gCAAgC,EAChC,sBAAsB,GACvB,CAAC"}
1
+ {"version":3,"file":"execConfig.d.ts","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/execConfig.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,qBAAqB,YAAY,CAAC;AACxC,QAAA,MAAM,gCAAgC,SAAS,CAAC;AAEhD,QAAA,MAAM,sBAAsB,gBAK3B,CAAC;AAEF,OAAO,EACL,qBAAqB,EACrB,gCAAgC,EAChC,sBAAsB,GACvB,CAAC"}
@@ -1,4 +1,4 @@
1
- const CODEX_INIT_EXEC_MODEL = "gpt-5.2-codex";
1
+ const CODEX_INIT_EXEC_MODEL = "gpt-5.4";
2
2
  const CODEX_INIT_EXEC_REASONING_EFFORT = "high";
3
3
  const buildCodexInitExecArgs = () => [
4
4
  "--model",
@@ -1 +1 @@
1
- {"version":3,"file":"execConfig.js","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/execConfig.ts"],"names":[],"mappings":"AAAA,MAAM,qBAAqB,GAAG,eAAe,CAAC;AAC9C,MAAM,gCAAgC,GAAG,MAAM,CAAC;AAEhD,MAAM,sBAAsB,GAAG,GAAG,EAAE,CAAC;IACnC,SAAS;IACT,qBAAqB;IACrB,UAAU;IACV,0BAA0B,gCAAgC,EAAE;CAC7D,CAAC;AAEF,OAAO,EACL,qBAAqB,EACrB,gCAAgC,EAChC,sBAAsB,GACvB,CAAC"}
1
+ {"version":3,"file":"execConfig.js","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/execConfig.ts"],"names":[],"mappings":"AAAA,MAAM,qBAAqB,GAAG,SAAS,CAAC;AACxC,MAAM,gCAAgC,GAAG,MAAM,CAAC;AAEhD,MAAM,sBAAsB,GAAG,GAAG,EAAE,CAAC;IACnC,SAAS;IACT,qBAAqB;IACrB,UAAU;IACV,0BAA0B,gCAAgC,EAAE;CAC7D,CAAC;AAEF,OAAO,EACL,qBAAqB,EACrB,gCAAgC,EAChC,sBAAsB,GACvB,CAAC"}
@@ -19,11 +19,7 @@ type ModalConnectToken = {
19
19
  url: string;
20
20
  token: string;
21
21
  };
22
- declare const shouldChunkModalFsWrite: (byteLength: number) => boolean;
23
- declare const resolveModalFsWriteControlTimeoutMs: (byteLength: number) => number;
24
- declare const resolveModalFsWriteAssembleTimeoutMs: (byteLength: number) => number;
25
- declare const buildModalFsWriteAssembleScript: (targetPath: string, assembledPath: string, partPaths: string[]) => string;
26
22
  declare const createModalRuntimeClient: ({ alias, appName: initialAppName, sandboxId: initialSandboxId, ensureActive, credentialMode, credentials, createConnectToken: _createConnectToken, createCheckpoint: createCheckpointViaControlPlane, cwd, serviceRole: requestedServiceRole, }: CreateModalRuntimeClientOptions) => InitRuntimeClient;
27
- export { buildModalFsWriteAssembleScript, createModalRuntimeClient, resolveModalFsWriteAssembleTimeoutMs, resolveModalFsWriteControlTimeoutMs, shouldChunkModalFsWrite, };
23
+ export { createModalRuntimeClient };
28
24
  export type { CreateModalRuntimeClientOptions };
29
25
  //# sourceMappingURL=modalRuntime.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"modalRuntime.d.ts","sourceRoot":"","sources":["../../../../src/devbox/commands/provider/modalRuntime.ts"],"names":[],"mappings":"AAKA,OAAO,EAYL,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAG5B,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,kBAAkB,IAAI,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAgBjF,KAAK,+BAA+B,GAAG;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,CACb,MAAM,EAAE,OAAO,GAAG,OAAO,KACtB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,WAAW,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC/C,kBAAkB,CAAC,EAAE,CACnB,MAAM,EAAE,OAAO,GAAG,OAAO,KACtB,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAChC,gBAAgB,CAAC,EAAE,CACjB,OAAO,CAAC,EAAE,MAAM,KACb,UAAU,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;CACjC,CAAC;AAKF,KAAK,iBAAiB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAkDxD,QAAA,MAAM,uBAAuB,GAAI,YAAY,MAAM,YACV,CAAC;AAE1C,QAAA,MAAM,mCAAmC,GAAI,YAAY,MAAM,WAK9D,CAAC;AAEF,QAAA,MAAM,oCAAoC,GAAI,YAAY,MAAM,WAG/D,CAAC;AAEF,QAAA,MAAM,+BAA+B,GACnC,YAAY,MAAM,EAClB,eAAe,MAAM,EACrB,WAAW,MAAM,EAAE,WAapB,CAAC;AAyfF,QAAA,MAAM,wBAAwB,GAAI,iPAW/B,+BAA+B,KAAG,iBA07BpC,CAAC;AAEF,OAAO,EACL,+BAA+B,EAC/B,wBAAwB,EACxB,oCAAoC,EACpC,mCAAmC,EACnC,uBAAuB,GACxB,CAAC;AACF,YAAY,EAAE,+BAA+B,EAAE,CAAC"}
1
+ {"version":3,"file":"modalRuntime.d.ts","sourceRoot":"","sources":["../../../../src/devbox/commands/provider/modalRuntime.ts"],"names":[],"mappings":"AAKA,OAAO,EAYL,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAG5B,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,kBAAkB,IAAI,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAiBjF,KAAK,+BAA+B,GAAG;IACrC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,CACb,MAAM,EAAE,OAAO,GAAG,OAAO,KACtB,OAAO,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACrD,cAAc,CAAC,EAAE,sBAAsB,CAAC;IACxC,WAAW,CAAC,EAAE,yBAAyB,GAAG,IAAI,CAAC;IAC/C,kBAAkB,CAAC,EAAE,CACnB,MAAM,EAAE,OAAO,GAAG,OAAO,KACtB,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAChC,gBAAgB,CAAC,EAAE,CACjB,OAAO,CAAC,EAAE,MAAM,KACb,UAAU,CAAC,iBAAiB,CAAC,kBAAkB,CAAC,CAAC,CAAC;IACvD,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;CACjC,CAAC;AAKF,KAAK,iBAAiB,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAuuBxD,QAAA,MAAM,wBAAwB,GAAI,iPAW/B,+BAA+B,KAAG,iBA48BpC,CAAC;AAEF,OAAO,EAAE,wBAAwB,EAAE,CAAC;AACpC,YAAY,EAAE,+BAA+B,EAAE,CAAC"}
@@ -1,10 +1,10 @@
1
- import { randomUUID } from "node:crypto";
1
+ import { createHash, randomUUID } from "node:crypto";
2
2
  import path from "node:path";
3
3
  import net from "node:net";
4
4
  import { ModalClient, NotFoundError } from "modal";
5
5
  import WebSocket, {} from "ws";
6
6
  import { createLogger, ProviderClientError, SpritesApiError, resolveModalClientCredentials, resolveSocketInfo, withDevboxSpan, } from "@boxes-dev/core";
7
- import { DAEMON_TIMEOUT_MS, ensureDaemonRunning, requestJson, requireDaemonFeatures, formatDaemonResponseError, } from "../../daemonClient.js";
7
+ import { DAEMON_TIMEOUT_MS, ensureDaemonRunning, requestJson, requireDaemonFeatures, formatDaemonResponseError, isDaemonConnectionError, } from "../../daemonClient.js";
8
8
  import { resolveModalEnvironmentName, resolveModalSandboxName, } from "./modalLifecycle.js";
9
9
  const SERVICE_NAME_PATTERN = /^[a-zA-Z0-9._-]+$/;
10
10
  const CORE_SERVICE_NAMES = new Set(["devbox-sprite-daemon", "devbox-sshd"]);
@@ -14,9 +14,13 @@ const MODAL_DAEMON_TTY_HANDSHAKE_TIMEOUT_MS = 30_000;
14
14
  const MODAL_SANDBOX_RESOLVE_TIMEOUT_MS = 30_000;
15
15
  const MODAL_DAEMON_CONTROL_HTTP_TIMEOUT_MS = 25_000;
16
16
  const MODAL_DAEMON_CONTROL_HTTP_TIMEOUT_PADDING_MS = 10_000;
17
- const MODAL_FS_WRITE_CHUNK_BYTES = 4 * 1024 * 1024;
18
- const MODAL_FS_WRITE_TIMEOUT_PER_MIB_MS = 4_000;
19
17
  const MODAL_DAEMON_TTY_WS_PATH = "/modal/tty";
18
+ const MODAL_DAEMON_INLINE_WRITE_MAX_BYTES = 8 * 1024 * 1024;
19
+ const MODAL_DAEMON_MULTIPART_WRITE_PART_SIZE_BYTES = 8 * 1024 * 1024;
20
+ const MODAL_DAEMON_MULTIPART_WRITE_CONCURRENCY = 3;
21
+ const MODAL_DAEMON_WRITE_TIMEOUT_BASE_MS = 5_000;
22
+ const MODAL_DAEMON_WRITE_TIMEOUT_PER_MIB_MS = 2_000;
23
+ const MODAL_DAEMON_MULTIPART_ASSEMBLE_MIN_TIMEOUT_MS = 30_000;
20
24
  const logger = createLogger("modal_runtime");
21
25
  const validateServiceName = (service) => {
22
26
  if (!SERVICE_NAME_PATTERN.test(service)) {
@@ -31,34 +35,90 @@ const clampModalControlTimeoutMs = (timeoutMs) => {
31
35
  }
32
36
  return Math.min(Math.max(Math.ceil(timeoutMs), MODAL_DAEMON_REQUEST_TIMEOUT_MS), MODAL_DAEMON_REQUEST_TIMEOUT_MAX_MS);
33
37
  };
34
- const shouldChunkModalFsWrite = (byteLength) => byteLength > MODAL_FS_WRITE_CHUNK_BYTES;
35
- const resolveModalFsWriteControlTimeoutMs = (byteLength) => {
36
- const mib = Math.max(1, Math.ceil(byteLength / (1024 * 1024)));
37
- return clampModalControlTimeoutMs(MODAL_DAEMON_REQUEST_TIMEOUT_MS + mib * MODAL_FS_WRITE_TIMEOUT_PER_MIB_MS);
38
+ const sha256Hex = (data) => createHash("sha256").update(data).digest("hex");
39
+ const estimateModalWriteTimeoutMs = (bytes) => {
40
+ const wholeMiB = Math.max(1, Math.ceil(bytes / (1024 * 1024)));
41
+ return clampModalControlTimeoutMs(MODAL_DAEMON_WRITE_TIMEOUT_BASE_MS +
42
+ wholeMiB * MODAL_DAEMON_WRITE_TIMEOUT_PER_MIB_MS);
38
43
  };
39
- const resolveModalFsWriteAssembleTimeoutMs = (byteLength) => {
40
- const mib = Math.max(1, Math.ceil(byteLength / (1024 * 1024)));
41
- return clampModalControlTimeoutMs(20_000 + mib * 1_000);
42
- };
43
- const buildModalFsWriteAssembleScript = (targetPath, assembledPath, partPaths) => {
44
- return [
45
- "set -euo pipefail",
46
- `target=${shellQuote(targetPath)}`,
47
- `assembled=${shellQuote(assembledPath)}`,
48
- 'cleanup() { rm -f "$assembled"; }',
49
- "trap cleanup EXIT",
50
- `cat ${partPaths.map((partPath) => shellQuote(partPath)).join(" ")} > "$assembled"`,
51
- 'mv "$assembled" "$target"',
52
- "trap - EXIT",
53
- `rm -f ${partPaths.map((partPath) => shellQuote(partPath)).join(" ")}`,
54
- ].join("\n");
55
- };
56
- const buildModalFsWriteCleanupScript = (paths) => {
57
- return [
58
- "set -euo pipefail",
59
- `rm -f ${paths.map((entry) => shellQuote(entry)).join(" ")}`,
60
- ].join("\n");
44
+ const normalizeConcurrency = (concurrency) => Math.max(1, Math.floor(concurrency));
45
+ const resolveBoundedConcurrency = (itemCount, concurrency) => Math.max(1, Math.min(itemCount, normalizeConcurrency(concurrency)));
46
+ const estimateModalMultipartPartTimeoutMs = (bytes, concurrency) => estimateModalWriteTimeoutMs(bytes * normalizeConcurrency(concurrency));
47
+ const estimateModalMultipartAssembleTimeoutMs = (bytes) => clampModalControlTimeoutMs(Math.max(MODAL_DAEMON_MULTIPART_ASSEMBLE_MIN_TIMEOUT_MS, estimateModalWriteTimeoutMs(bytes) * 2));
48
+ const buildModalMultipartWritePlan = (remotePath, data) => {
49
+ const normalizedRemotePath = path.posix.normalize(remotePath);
50
+ const remoteDir = path.posix.dirname(normalizedRemotePath);
51
+ const remoteBaseName = path.posix.basename(normalizedRemotePath);
52
+ const uploadId = randomUUID();
53
+ const partDir = path.posix.join(remoteDir, `.${remoteBaseName}.tmp-upload-${uploadId}`);
54
+ const assembledTmpPath = path.posix.join(remoteDir, `.${remoteBaseName}.tmp-assemble-${uploadId}`);
55
+ const parts = [];
56
+ for (let offset = 0, index = 0; offset < data.length; offset += MODAL_DAEMON_MULTIPART_WRITE_PART_SIZE_BYTES, index += 1) {
57
+ const partData = data.subarray(offset, Math.min(offset + MODAL_DAEMON_MULTIPART_WRITE_PART_SIZE_BYTES, data.length));
58
+ parts.push({
59
+ index,
60
+ remotePath: path.posix.join(partDir, `part-${String(index).padStart(5, "0")}`),
61
+ data: partData,
62
+ sizeBytes: partData.length,
63
+ sha256: sha256Hex(partData),
64
+ });
65
+ }
66
+ return {
67
+ partDir,
68
+ assembledTmpPath,
69
+ expectedSizeBytes: data.length,
70
+ expectedSha256: sha256Hex(data),
71
+ parts,
72
+ };
61
73
  };
74
+ const buildModalMultipartAssembleScript = (remotePath, plan) => [
75
+ "set -euo pipefail",
76
+ `target=${shellQuote(path.posix.normalize(remotePath))}`,
77
+ `part_dir=${shellQuote(plan.partDir)}`,
78
+ `assembled_tmp=${shellQuote(plan.assembledTmpPath)}`,
79
+ `expected_size=${plan.expectedSizeBytes}`,
80
+ `expected_sha=${shellQuote(plan.expectedSha256)}`,
81
+ "hash_file() {",
82
+ " if command -v sha256sum >/dev/null 2>&1; then",
83
+ " sha256sum \"$1\" | awk '{print $1}'",
84
+ " return 0",
85
+ " fi",
86
+ " if command -v shasum >/dev/null 2>&1; then",
87
+ " shasum -a 256 \"$1\" | awk '{print $1}'",
88
+ " return 0",
89
+ " fi",
90
+ ' echo "No SHA256 tool available (sha256sum/shasum)." >&2',
91
+ " return 1",
92
+ "}",
93
+ 'cleanup() { rm -f "$assembled_tmp"; }',
94
+ "trap cleanup EXIT",
95
+ 'mkdir -p "$(dirname "$target")"',
96
+ '[ -d "$part_dir" ] || { echo "Missing multipart upload directory: $part_dir" >&2; exit 1; }',
97
+ ': > "$assembled_tmp"',
98
+ ...plan.parts.flatMap((part) => [
99
+ `part_path=${shellQuote(part.remotePath)}`,
100
+ `part_expected_size=${part.sizeBytes}`,
101
+ `part_expected_sha=${shellQuote(part.sha256)}`,
102
+ '[ -f "$part_path" ] || { echo "Missing upload part: $part_path" >&2; exit 1; }',
103
+ 'part_size="$(wc -c < "$part_path" | tr -d \'[:space:]\')"',
104
+ 'if [ "$part_size" != "$part_expected_size" ]; then echo "Part size mismatch for $part_path: expected $part_expected_size got $part_size" >&2; exit 1; fi',
105
+ 'part_sha="$(hash_file "$part_path")"',
106
+ 'if [ "$part_sha" != "$part_expected_sha" ]; then echo "Part checksum mismatch for $part_path" >&2; exit 1; fi',
107
+ 'cat "$part_path" >> "$assembled_tmp"',
108
+ ]),
109
+ 'assembled_size="$(wc -c < "$assembled_tmp" | tr -d \'[:space:]\')"',
110
+ 'if [ "$assembled_size" != "$expected_size" ]; then echo "Assembled file size mismatch: expected $expected_size got $assembled_size" >&2; exit 1; fi',
111
+ 'assembled_sha="$(hash_file "$assembled_tmp")"',
112
+ 'if [ "$assembled_sha" != "$expected_sha" ]; then echo "Assembled file checksum mismatch" >&2; exit 1; fi',
113
+ 'mv "$assembled_tmp" "$target"',
114
+ 'rm -rf "$part_dir"',
115
+ "trap - EXIT",
116
+ ].join("\n");
117
+ const buildModalMultipartCleanupScript = (plan) => [
118
+ "set -euo pipefail",
119
+ `rm -rf ${shellQuote(plan.partDir)}`,
120
+ `rm -f ${shellQuote(plan.assembledTmpPath)}`,
121
+ ].join("\n");
62
122
  const buildModalControlTraceAttributes = (alias, requestPayload, expectedType, responseTimeoutMs) => {
63
123
  const requestType = typeof requestPayload.type === "string" ? requestPayload.type : "unknown";
64
124
  return {
@@ -88,6 +148,43 @@ const buildModalControlTraceAttributes = (alias, requestPayload, expectedType, r
88
148
  : {}),
89
149
  };
90
150
  };
151
+ const runWithConcurrency = async (items, concurrency, worker) => {
152
+ if (items.length === 0) {
153
+ return;
154
+ }
155
+ const boundedConcurrency = resolveBoundedConcurrency(items.length, concurrency);
156
+ let nextIndex = 0;
157
+ let firstError = null;
158
+ const workers = Array.from({ length: boundedConcurrency }, async () => {
159
+ while (true) {
160
+ if (firstError) {
161
+ return;
162
+ }
163
+ const currentIndex = nextIndex;
164
+ nextIndex += 1;
165
+ if (currentIndex >= items.length) {
166
+ return;
167
+ }
168
+ const item = items.at(currentIndex);
169
+ if (item === undefined) {
170
+ return;
171
+ }
172
+ try {
173
+ await worker(item);
174
+ }
175
+ catch (error) {
176
+ if (!firstError) {
177
+ firstError = error;
178
+ }
179
+ return;
180
+ }
181
+ }
182
+ });
183
+ await Promise.all(workers);
184
+ if (firstError) {
185
+ throw firstError;
186
+ }
187
+ };
91
188
  const resolveReadPath = (readPath, workingDir) => {
92
189
  if (path.posix.isAbsolute(readPath))
93
190
  return path.posix.normalize(readPath);
@@ -527,6 +624,7 @@ class ModalDaemonExecSocket {
527
624
  const createModalRuntimeClient = ({ alias, appName: initialAppName, sandboxId: initialSandboxId, ensureActive, credentialMode, credentials, createConnectToken: _createConnectToken, createCheckpoint: createCheckpointViaControlPlane, cwd, serviceRole: requestedServiceRole, }) => {
528
625
  let modal = null;
529
626
  let modalSandboxName = alias;
627
+ const socketPath = resolveSocketInfo().socketPath;
530
628
  try {
531
629
  const modalCredentials = resolveModalClientCredentials({
532
630
  ...(credentialMode ? { credentialMode } : {}),
@@ -612,6 +710,22 @@ const createModalRuntimeClient = ({ alias, appName: initialAppName, sandboxId: i
612
710
  const stderr = typeof response.stderr === "string" ? response.stderr : "";
613
711
  return { exitCode, stdout, stderr };
614
712
  };
713
+ const execShellScript = async (script, timeoutMs, failureMessage) => {
714
+ const result = await exec(alias, [
715
+ "/bin/bash",
716
+ "--noprofile",
717
+ "--norc",
718
+ "-e",
719
+ "-u",
720
+ "-o",
721
+ "pipefail",
722
+ "-c",
723
+ script,
724
+ ], { timeoutMs });
725
+ if (result.exitCode !== 0) {
726
+ throw new Error(result.stderr || result.stdout || failureMessage);
727
+ }
728
+ };
615
729
  const readFile = async (name, options) => {
616
730
  requireAlias(name);
617
731
  const resolvedPath = resolveReadPath(options.path, options.workingDir);
@@ -636,10 +750,14 @@ const createModalRuntimeClient = ({ alias, appName: initialAppName, sandboxId: i
636
750
  requireAlias(name);
637
751
  const total = data.length;
638
752
  options?.onProgress?.(0, total);
639
- const chunked = shouldChunkModalFsWrite(total);
640
- const partPaths = [];
641
- let assembledPath = null;
642
- const chunkCount = Math.ceil(total / MODAL_FS_WRITE_CHUNK_BYTES);
753
+ const chunked = total > MODAL_DAEMON_INLINE_WRITE_MAX_BYTES;
754
+ const chunkCount = chunked
755
+ ? Math.ceil(total / MODAL_DAEMON_MULTIPART_WRITE_PART_SIZE_BYTES)
756
+ : 0;
757
+ const plan = chunked ? buildModalMultipartWritePlan(remotePath, data) : null;
758
+ const multipartConcurrency = plan
759
+ ? resolveBoundedConcurrency(plan.parts.length, MODAL_DAEMON_MULTIPART_WRITE_CONCURRENCY)
760
+ : 1;
643
761
  await withDevboxSpan("modal.write_file", {
644
762
  "devbox.modal.alias": alias,
645
763
  "devbox.modal.path": remotePath,
@@ -654,8 +772,9 @@ const createModalRuntimeClient = ({ alias, appName: initialAppName, sandboxId: i
654
772
  chunked,
655
773
  ...(chunked
656
774
  ? {
657
- chunkBytes: MODAL_FS_WRITE_CHUNK_BYTES,
775
+ chunkBytes: MODAL_DAEMON_MULTIPART_WRITE_PART_SIZE_BYTES,
658
776
  chunkCount,
777
+ multipartConcurrency,
659
778
  }
660
779
  : {}),
661
780
  });
@@ -667,7 +786,7 @@ const createModalRuntimeClient = ({ alias, appName: initialAppName, sandboxId: i
667
786
  mkdir: true,
668
787
  data: Buffer.from(data).toString("base64"),
669
788
  }, "fs_write_result", {
670
- responseTimeoutMs: resolveModalFsWriteControlTimeoutMs(total),
789
+ responseTimeoutMs: estimateModalWriteTimeoutMs(total),
671
790
  });
672
791
  if (response.status !== "ok") {
673
792
  const { text } = parseControlError(response);
@@ -682,99 +801,54 @@ const createModalRuntimeClient = ({ alias, appName: initialAppName, sandboxId: i
682
801
  });
683
802
  return;
684
803
  }
685
- const uploadId = randomUUID().replace(/-/g, "");
686
- assembledPath = `${remotePath}.tmp-upload-${uploadId}.assembled`;
804
+ if (!plan) {
805
+ throw new Error("Missing multipart upload plan.");
806
+ }
687
807
  let uploadedBytes = 0;
688
- let chunkIndex = 0;
689
- for (let offset = 0; offset < total; offset += MODAL_FS_WRITE_CHUNK_BYTES) {
690
- const nextOffset = Math.min(offset + MODAL_FS_WRITE_CHUNK_BYTES, total);
691
- const chunk = data.subarray(offset, nextOffset);
692
- const partPath = `${remotePath}.tmp-upload-${uploadId}.part-${String(chunkIndex).padStart(4, "0")}`;
693
- partPaths.push(partPath);
808
+ await runWithConcurrency(plan.parts, multipartConcurrency, async (part) => {
694
809
  const response = await runControlRequest({
695
810
  type: "fs_write",
696
- path: partPath,
811
+ path: part.remotePath,
697
812
  mkdir: true,
698
- data: Buffer.from(chunk).toString("base64"),
813
+ data: Buffer.from(part.data).toString("base64"),
699
814
  }, "fs_write_result", {
700
- responseTimeoutMs: resolveModalFsWriteControlTimeoutMs(chunk.length),
815
+ responseTimeoutMs: estimateModalMultipartPartTimeoutMs(part.sizeBytes, multipartConcurrency),
701
816
  });
702
817
  if (response.status !== "ok") {
703
818
  const { text } = parseControlError(response);
704
819
  throw new Error(text);
705
820
  }
706
- uploadedBytes += chunk.length;
821
+ uploadedBytes += part.sizeBytes;
707
822
  logger.info("modal_fs_write_chunk_complete", {
708
823
  alias,
709
824
  remotePath,
710
- chunkIndex,
711
- chunkCount,
712
- chunkSizeBytes: chunk.length,
825
+ chunkIndex: part.index,
826
+ chunkCount: plan.parts.length,
827
+ chunkSizeBytes: part.sizeBytes,
713
828
  uploadedBytes,
714
829
  totalBytes: total,
715
830
  });
716
- chunkIndex += 1;
717
831
  options?.onProgress?.(uploadedBytes, total);
718
- }
719
- const assembleResult = await exec(name, [
720
- "/bin/bash",
721
- "--noprofile",
722
- "--norc",
723
- "-e",
724
- "-u",
725
- "-o",
726
- "pipefail",
727
- "-c",
728
- buildModalFsWriteAssembleScript(remotePath, assembledPath, partPaths),
729
- ], {
730
- timeoutMs: resolveModalFsWriteAssembleTimeoutMs(total),
731
832
  });
732
- if (assembleResult.exitCode !== 0) {
733
- throw new Error(assembleResult.stderr ||
734
- assembleResult.stdout ||
735
- "Failed to assemble chunked Modal upload.");
736
- }
833
+ await execShellScript(buildModalMultipartAssembleScript(remotePath, plan), estimateModalMultipartAssembleTimeoutMs(total), "Failed to assemble multipart Modal upload.");
737
834
  options?.onProgress?.(total, total);
738
835
  logger.info("modal_fs_write_complete", {
739
836
  alias,
740
837
  remotePath,
741
838
  sizeBytes: total,
742
839
  chunked: true,
743
- chunkCount: partPaths.length,
840
+ chunkCount: plan.parts.length,
744
841
  });
745
842
  }
746
843
  catch (error) {
747
- const cleanupPaths = chunked && (partPaths.length > 0 || assembledPath)
748
- ? [...partPaths, ...(assembledPath ? [assembledPath] : [])]
749
- : [];
750
- if (cleanupPaths.length > 0) {
844
+ if (plan) {
751
845
  try {
752
- const cleanupResult = await exec(name, [
753
- "/bin/bash",
754
- "--noprofile",
755
- "--norc",
756
- "-e",
757
- "-u",
758
- "-o",
759
- "pipefail",
760
- "-c",
761
- buildModalFsWriteCleanupScript(cleanupPaths),
762
- ], { timeoutMs: MODAL_DAEMON_REQUEST_TIMEOUT_MS });
763
- if (cleanupResult.exitCode !== 0) {
764
- logger.warn("modal_fs_write_cleanup_failed", {
765
- alias,
766
- remotePath,
767
- cleanupTargetCount: cleanupPaths.length,
768
- stderr: cleanupResult.stderr || undefined,
769
- stdout: cleanupResult.stdout || undefined,
770
- });
771
- }
846
+ await execShellScript(buildModalMultipartCleanupScript(plan), MODAL_DAEMON_REQUEST_TIMEOUT_MS, "Failed to clean up multipart Modal upload.");
772
847
  }
773
848
  catch (cleanupError) {
774
849
  logger.warn("modal_fs_write_cleanup_failed", {
775
850
  alias,
776
851
  remotePath,
777
- cleanupTargetCount: cleanupPaths.length,
778
852
  error: cleanupError instanceof Error
779
853
  ? cleanupError.message
780
854
  : String(cleanupError),
@@ -786,7 +860,6 @@ const createModalRuntimeClient = ({ alias, appName: initialAppName, sandboxId: i
786
860
  remotePath,
787
861
  sizeBytes: total,
788
862
  chunked,
789
- cleanupAttempted: cleanupPaths.length > 0,
790
863
  error: error instanceof Error ? error.message : String(error),
791
864
  });
792
865
  throw error;
@@ -1088,7 +1161,28 @@ const createModalRuntimeClient = ({ alias, appName: initialAppName, sandboxId: i
1088
1161
  return amount * 60_000;
1089
1162
  return undefined;
1090
1163
  };
1091
- const runControlRequest = async (requestPayload, expectedType, options) => {
1164
+ let modalControlReadyPromise = null;
1165
+ const ensureModalControlReady = async (force = false) => {
1166
+ if (!force && modalControlReadyPromise) {
1167
+ await modalControlReadyPromise;
1168
+ return;
1169
+ }
1170
+ const ready = (async () => {
1171
+ await ensureDaemonRunning(socketPath);
1172
+ await requireDaemonFeatures(socketPath, ["modal.control"]);
1173
+ })();
1174
+ modalControlReadyPromise = ready;
1175
+ try {
1176
+ await ready;
1177
+ }
1178
+ catch (error) {
1179
+ if (modalControlReadyPromise === ready) {
1180
+ modalControlReadyPromise = null;
1181
+ }
1182
+ throw error;
1183
+ }
1184
+ };
1185
+ const postControlRequest = async (requestPayload, expectedType, options) => {
1092
1186
  const socketInfo = resolveSocketInfo();
1093
1187
  await ensureDaemonRunning(socketInfo.socketPath);
1094
1188
  await requireDaemonFeatures(socketInfo.socketPath, ["modal.control"]);
@@ -1128,6 +1222,22 @@ const createModalRuntimeClient = ({ alias, appName: initialAppName, sandboxId: i
1128
1222
  return payload;
1129
1223
  });
1130
1224
  };
1225
+ const runControlRequest = async (requestPayload, expectedType, options) => {
1226
+ await ensureModalControlReady();
1227
+ let response;
1228
+ try {
1229
+ response = await postControlRequest(requestPayload, expectedType, options);
1230
+ }
1231
+ catch (error) {
1232
+ if (!isDaemonConnectionError(error)) {
1233
+ throw error;
1234
+ }
1235
+ modalControlReadyPromise = null;
1236
+ await ensureModalControlReady(true);
1237
+ response = await postControlRequest(requestPayload, expectedType, options);
1238
+ }
1239
+ return response;
1240
+ };
1131
1241
  const listExecSessions = async (name) => {
1132
1242
  requireAlias(name);
1133
1243
  const response = await runControlRequest({ type: "sessions_list" }, "sessions_list_result");
@@ -1229,5 +1339,5 @@ const createModalRuntimeClient = ({ alias, appName: initialAppName, sandboxId: i
1229
1339
  attachExecSession,
1230
1340
  };
1231
1341
  };
1232
- export { buildModalFsWriteAssembleScript, createModalRuntimeClient, resolveModalFsWriteAssembleTimeoutMs, resolveModalFsWriteControlTimeoutMs, shouldChunkModalFsWrite, };
1342
+ export { createModalRuntimeClient };
1233
1343
  //# sourceMappingURL=modalRuntime.js.map