@boxes-dev/dvb 0.2.45 → 0.2.47
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/dvb.cjs +495 -345
- package/dist/bin/dvbd.cjs +228 -124
- package/dist/devbox/commands/init/codex/prompts.d.ts.map +1 -1
- package/dist/devbox/commands/init/codex/prompts.js +20 -5
- package/dist/devbox/commands/init/codex/prompts.js.map +1 -1
- package/dist/devbox/commands/init/index.d.ts.map +1 -1
- package/dist/devbox/commands/init/index.js +236 -171
- package/dist/devbox/commands/init/index.js.map +1 -1
- package/dist/devbox/commands/init/remote.d.ts.map +1 -1
- package/dist/devbox/commands/init/remote.js +1 -17
- package/dist/devbox/commands/init/remote.js.map +1 -1
- package/package.json +1 -1
|
@@ -42,6 +42,93 @@ const ensurePrivateDir = async (dir) => {
|
|
|
42
42
|
// best effort on filesystems that do not support chmod
|
|
43
43
|
}
|
|
44
44
|
};
|
|
45
|
+
const DEFAULT_INIT_STEP_RETRIES = 3;
|
|
46
|
+
const INIT_STEP_RETRYABLE_STATUSES = new Set([
|
|
47
|
+
408, 409, 425, 429, 500, 502, 503, 504,
|
|
48
|
+
]);
|
|
49
|
+
const delay = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
50
|
+
const computeRetryDelayMs = (retryIndex) => {
|
|
51
|
+
// retryIndex is 1-based (1..N)
|
|
52
|
+
const base = 500;
|
|
53
|
+
const cap = 5000;
|
|
54
|
+
const exp = Math.min(cap, base * 2 ** Math.max(0, retryIndex - 1));
|
|
55
|
+
const jitter = Math.floor(Math.random() * 150);
|
|
56
|
+
return exp + jitter;
|
|
57
|
+
};
|
|
58
|
+
const getErrorCode = (error) => {
|
|
59
|
+
if (!error || typeof error !== "object")
|
|
60
|
+
return undefined;
|
|
61
|
+
const record = error;
|
|
62
|
+
const code = record.code;
|
|
63
|
+
return typeof code === "string" || typeof code === "number"
|
|
64
|
+
? String(code)
|
|
65
|
+
: undefined;
|
|
66
|
+
};
|
|
67
|
+
const parseExecUnexpectedResponseStatus = (error) => {
|
|
68
|
+
if (!(error instanceof Error))
|
|
69
|
+
return null;
|
|
70
|
+
const match = /Unexpected server response: (\\d{3})/.exec(error.message);
|
|
71
|
+
if (!match)
|
|
72
|
+
return null;
|
|
73
|
+
const status = Number(match[1]);
|
|
74
|
+
return Number.isFinite(status) ? status : null;
|
|
75
|
+
};
|
|
76
|
+
const isRetryableInitError = (error) => {
|
|
77
|
+
if (error instanceof SpritesApiError) {
|
|
78
|
+
return INIT_STEP_RETRYABLE_STATUSES.has(error.status);
|
|
79
|
+
}
|
|
80
|
+
// Node's fetch() throws TypeError for network failures.
|
|
81
|
+
if (error instanceof TypeError)
|
|
82
|
+
return true;
|
|
83
|
+
if (error instanceof Error &&
|
|
84
|
+
(error.name === "AbortError" || error.message.includes("aborted"))) {
|
|
85
|
+
return true;
|
|
86
|
+
}
|
|
87
|
+
const execStatus = parseExecUnexpectedResponseStatus(error);
|
|
88
|
+
if (execStatus !== null) {
|
|
89
|
+
return INIT_STEP_RETRYABLE_STATUSES.has(execStatus);
|
|
90
|
+
}
|
|
91
|
+
const code = getErrorCode(error);
|
|
92
|
+
return (code === "ECONNRESET" ||
|
|
93
|
+
code === "ETIMEDOUT" ||
|
|
94
|
+
code === "EAI_AGAIN" ||
|
|
95
|
+
code === "ENOTFOUND" ||
|
|
96
|
+
code === "ECONNREFUSED");
|
|
97
|
+
};
|
|
98
|
+
const retryInitStep = async ({ status, title, retries = DEFAULT_INIT_STEP_RETRIES, shouldRetry = isRetryableInitError, fn, }) => {
|
|
99
|
+
let lastError = null;
|
|
100
|
+
const maxRetries = Math.max(0, Math.floor(retries));
|
|
101
|
+
const attempts = maxRetries + 1;
|
|
102
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
103
|
+
try {
|
|
104
|
+
return await fn();
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
lastError = error;
|
|
108
|
+
const retryIndex = attempt; // 1-based retry count for the next attempt
|
|
109
|
+
if (retryIndex > maxRetries || !shouldRetry(error)) {
|
|
110
|
+
throw error;
|
|
111
|
+
}
|
|
112
|
+
status.stage(`${title} (retry ${retryIndex}/${maxRetries})`);
|
|
113
|
+
logger.warn("init_step_retry", {
|
|
114
|
+
title,
|
|
115
|
+
retry: retryIndex,
|
|
116
|
+
retries: maxRetries,
|
|
117
|
+
errorName: error instanceof Error ? error.name : undefined,
|
|
118
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
119
|
+
errorCode: getErrorCode(error),
|
|
120
|
+
...(error instanceof SpritesApiError ? { status: error.status } : {}),
|
|
121
|
+
...(parseExecUnexpectedResponseStatus(error) !== null
|
|
122
|
+
? { execStatus: parseExecUnexpectedResponseStatus(error) }
|
|
123
|
+
: {}),
|
|
124
|
+
});
|
|
125
|
+
await delay(computeRetryDelayMs(retryIndex));
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
throw lastError instanceof Error
|
|
129
|
+
? lastError
|
|
130
|
+
: new Error(`Init step failed: ${title}`);
|
|
131
|
+
};
|
|
45
132
|
const migrateLegacyRepoDevboxDir = async ({ repoRoot, projectDir, }) => {
|
|
46
133
|
const legacyDir = path.join(repoRoot, ".devbox");
|
|
47
134
|
try {
|
|
@@ -210,14 +297,26 @@ const toRepoRelativePath = (repoRoot, filePath) => {
|
|
|
210
297
|
return toPosixPath(relative);
|
|
211
298
|
};
|
|
212
299
|
const isOutsideRepoPath = (relativePath) => relativePath === ".." || relativePath.startsWith(`..${path.posix.sep}`);
|
|
213
|
-
const ensureWorkdirOwnership = async ({ client, canonical, workdir, status,
|
|
300
|
+
const ensureWorkdirOwnership = async ({ client, canonical, workdir, status, }) => {
|
|
214
301
|
const checkResult = await client.exec(canonical, [
|
|
215
302
|
"/bin/bash",
|
|
216
303
|
"-lc",
|
|
217
|
-
|
|
304
|
+
[
|
|
305
|
+
"set -euo pipefail",
|
|
306
|
+
`dir=${shellQuote(workdir)}`,
|
|
307
|
+
'if [ ! -d "$dir" ]; then',
|
|
308
|
+
' echo "Missing workdir: $dir" >&2',
|
|
309
|
+
" exit 1",
|
|
310
|
+
"fi",
|
|
311
|
+
'stat -c %U "$dir"',
|
|
312
|
+
].join("\n"),
|
|
218
313
|
]);
|
|
219
|
-
if (checkResult.exitCode !== 0)
|
|
220
|
-
|
|
314
|
+
if (checkResult.exitCode !== 0) {
|
|
315
|
+
const details = checkResult.stderr || checkResult.stdout || "";
|
|
316
|
+
throw new Error(details
|
|
317
|
+
? `Failed to check workdir ownership: ${details.trim()}`
|
|
318
|
+
: `Failed to check workdir ownership (exit ${checkResult.exitCode})`);
|
|
319
|
+
}
|
|
221
320
|
const owner = checkResult.stdout.trim();
|
|
222
321
|
if (!owner || owner === "sprite")
|
|
223
322
|
return;
|
|
@@ -228,15 +327,10 @@ const ensureWorkdirOwnership = async ({ client, canonical, workdir, status, json
|
|
|
228
327
|
`sudo -n chown -R sprite:sprite ${shellQuote(workdir)}`,
|
|
229
328
|
]);
|
|
230
329
|
if (chownResult.exitCode !== 0) {
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
workdir
|
|
234
|
-
|
|
235
|
-
});
|
|
236
|
-
if (!json) {
|
|
237
|
-
status.stop();
|
|
238
|
-
console.warn("Warning: failed to update workdir ownership. Git may refuse to operate until ownership is fixed.");
|
|
239
|
-
}
|
|
330
|
+
const details = chownResult.stderr || chownResult.stdout || "";
|
|
331
|
+
throw new Error(details
|
|
332
|
+
? `Failed to update workdir ownership: ${details.trim()}`
|
|
333
|
+
: `Failed to update workdir ownership (exit ${chownResult.exitCode})`);
|
|
240
334
|
}
|
|
241
335
|
};
|
|
242
336
|
const ensureGitSafeDirectory = async ({ client, canonical, workdir, status, }) => {
|
|
@@ -573,7 +667,7 @@ export const runInit = async (args) => {
|
|
|
573
667
|
fingerprint,
|
|
574
668
|
phase: label,
|
|
575
669
|
});
|
|
576
|
-
|
|
670
|
+
throw new Error("Checkpoint ID missing.");
|
|
577
671
|
}
|
|
578
672
|
const record = { id, comment, createdAt };
|
|
579
673
|
if (initState) {
|
|
@@ -738,13 +832,17 @@ export const runInit = async (args) => {
|
|
|
738
832
|
});
|
|
739
833
|
await runInitStep({
|
|
740
834
|
enabled: progressEnabled,
|
|
741
|
-
title: "Snapshotting filesystem (pre-setup)
|
|
742
|
-
fn: async ({ fail, ok }) => {
|
|
835
|
+
title: "Snapshotting filesystem (pre-setup)",
|
|
836
|
+
fn: async ({ status, fail, ok }) => {
|
|
743
837
|
try {
|
|
744
|
-
const checkpoint = await
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
838
|
+
const checkpoint = await retryInitStep({
|
|
839
|
+
status,
|
|
840
|
+
title: "Snapshotting filesystem (pre-setup)",
|
|
841
|
+
fn: async () => await recordCodexCheckpoint({
|
|
842
|
+
client,
|
|
843
|
+
canonical,
|
|
844
|
+
phase: "preCodexSetup",
|
|
845
|
+
}),
|
|
748
846
|
});
|
|
749
847
|
if (checkpoint.id) {
|
|
750
848
|
ok(`Snapshot created: ${checkpoint.id}`);
|
|
@@ -757,10 +855,8 @@ export const runInit = async (args) => {
|
|
|
757
855
|
phase: "pre-codex-setup",
|
|
758
856
|
error: error instanceof Error ? error.message : String(error),
|
|
759
857
|
});
|
|
760
|
-
fail("Snapshotting filesystem (pre-setup) (
|
|
761
|
-
|
|
762
|
-
console.warn("Warning: failed to create pre-setup filesystem snapshot. Continuing without it.");
|
|
763
|
-
}
|
|
858
|
+
fail("Snapshotting filesystem (pre-setup) (failed)");
|
|
859
|
+
throw error;
|
|
764
860
|
}
|
|
765
861
|
},
|
|
766
862
|
});
|
|
@@ -796,13 +892,17 @@ export const runInit = async (args) => {
|
|
|
796
892
|
});
|
|
797
893
|
await runInitStep({
|
|
798
894
|
enabled: progressEnabled,
|
|
799
|
-
title: "Snapshotting filesystem (post-setup)
|
|
800
|
-
fn: async ({ fail, ok }) => {
|
|
895
|
+
title: "Snapshotting filesystem (post-setup)",
|
|
896
|
+
fn: async ({ status, fail, ok }) => {
|
|
801
897
|
try {
|
|
802
|
-
const checkpoint = await
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
898
|
+
const checkpoint = await retryInitStep({
|
|
899
|
+
status,
|
|
900
|
+
title: "Snapshotting filesystem (post-setup)",
|
|
901
|
+
fn: async () => await recordCodexCheckpoint({
|
|
902
|
+
client,
|
|
903
|
+
canonical,
|
|
904
|
+
phase: "postCodexSetup",
|
|
905
|
+
}),
|
|
806
906
|
});
|
|
807
907
|
if (checkpoint.id) {
|
|
808
908
|
ok(`Snapshot created: ${checkpoint.id}`);
|
|
@@ -815,10 +915,8 @@ export const runInit = async (args) => {
|
|
|
815
915
|
phase: "post-codex-setup",
|
|
816
916
|
error: error instanceof Error ? error.message : String(error),
|
|
817
917
|
});
|
|
818
|
-
fail("Snapshotting filesystem (post-setup) (
|
|
819
|
-
|
|
820
|
-
console.warn("Warning: failed to create post-setup filesystem snapshot. Continuing without it.");
|
|
821
|
-
}
|
|
918
|
+
fail("Snapshotting filesystem (post-setup) (failed)");
|
|
919
|
+
throw error;
|
|
822
920
|
}
|
|
823
921
|
},
|
|
824
922
|
});
|
|
@@ -956,25 +1054,20 @@ export const runInit = async (args) => {
|
|
|
956
1054
|
localPaths: projectLocalPaths,
|
|
957
1055
|
});
|
|
958
1056
|
const updateRegistryProjectStatus = async (initStatus) => {
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
});
|
|
963
|
-
}
|
|
964
|
-
catch (error) {
|
|
965
|
-
logger.warn("registry_project_update_failed", {
|
|
966
|
-
box: canonical,
|
|
967
|
-
status: initStatus,
|
|
968
|
-
error: String(error),
|
|
969
|
-
});
|
|
970
|
-
}
|
|
1057
|
+
await requestJson(socketInfo.socketPath, "POST", "/registry/upsert", DAEMON_TIMEOUT_MS.registry, {
|
|
1058
|
+
project: buildProjectEntry(initStatus),
|
|
1059
|
+
});
|
|
971
1060
|
};
|
|
972
1061
|
await runInitStep({
|
|
973
1062
|
enabled: progressEnabled,
|
|
974
1063
|
title: "Bootstrapping devbox",
|
|
975
|
-
fn: async ({ fail }) => {
|
|
1064
|
+
fn: async ({ status, fail }) => {
|
|
976
1065
|
try {
|
|
977
|
-
await
|
|
1066
|
+
await retryInitStep({
|
|
1067
|
+
status,
|
|
1068
|
+
title: "Bootstrapping devbox",
|
|
1069
|
+
fn: async () => await bootstrapDevbox(client, canonical),
|
|
1070
|
+
});
|
|
978
1071
|
}
|
|
979
1072
|
catch (error) {
|
|
980
1073
|
logger.warn("devbox_bootstrap_failed", {
|
|
@@ -982,12 +1075,7 @@ export const runInit = async (args) => {
|
|
|
982
1075
|
error: String(error),
|
|
983
1076
|
});
|
|
984
1077
|
fail("Bootstrapping devbox (failed)");
|
|
985
|
-
|
|
986
|
-
const message = error instanceof Error && error.message
|
|
987
|
-
? error.message
|
|
988
|
-
: String(error);
|
|
989
|
-
console.warn(`Warning: devbox bootstrap failed. ${message}`);
|
|
990
|
-
}
|
|
1078
|
+
throw error;
|
|
991
1079
|
}
|
|
992
1080
|
},
|
|
993
1081
|
});
|
|
@@ -1019,7 +1107,7 @@ export const runInit = async (args) => {
|
|
|
1019
1107
|
await runInitStep({
|
|
1020
1108
|
enabled: progressEnabled,
|
|
1021
1109
|
title: "Installing sprite daemon",
|
|
1022
|
-
fn: async ({ fail }) => {
|
|
1110
|
+
fn: async ({ status, fail }) => {
|
|
1023
1111
|
try {
|
|
1024
1112
|
const convexUrl = getConvexUrl();
|
|
1025
1113
|
if (!controlPlaneToken) {
|
|
@@ -1036,12 +1124,16 @@ export const runInit = async (args) => {
|
|
|
1036
1124
|
if (!heartbeatToken) {
|
|
1037
1125
|
throw new Error("Daemon token unavailable.");
|
|
1038
1126
|
}
|
|
1039
|
-
await
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1127
|
+
await retryInitStep({
|
|
1128
|
+
status,
|
|
1129
|
+
title: "Installing sprite daemon",
|
|
1130
|
+
fn: async () => await installSpriteDaemon({
|
|
1131
|
+
client,
|
|
1132
|
+
spriteName: canonical,
|
|
1133
|
+
release,
|
|
1134
|
+
convexUrl,
|
|
1135
|
+
heartbeatToken,
|
|
1136
|
+
}),
|
|
1045
1137
|
});
|
|
1046
1138
|
await updateInitState({ steps: { daemonInstalled: true } });
|
|
1047
1139
|
}
|
|
@@ -1051,12 +1143,7 @@ export const runInit = async (args) => {
|
|
|
1051
1143
|
error: String(error),
|
|
1052
1144
|
});
|
|
1053
1145
|
fail("Installing sprite daemon (failed)");
|
|
1054
|
-
|
|
1055
|
-
const message = error instanceof Error && error.message
|
|
1056
|
-
? error.message
|
|
1057
|
-
: String(error);
|
|
1058
|
-
console.warn(`Warning: failed to install sprite daemon. ${message}`);
|
|
1059
|
-
}
|
|
1146
|
+
throw error;
|
|
1060
1147
|
}
|
|
1061
1148
|
},
|
|
1062
1149
|
});
|
|
@@ -1064,9 +1151,13 @@ export const runInit = async (args) => {
|
|
|
1064
1151
|
await runInitStep({
|
|
1065
1152
|
enabled: progressEnabled,
|
|
1066
1153
|
title: "Ensuring sprite daemon service",
|
|
1067
|
-
fn: async ({ fail }) => {
|
|
1154
|
+
fn: async ({ status, fail }) => {
|
|
1068
1155
|
try {
|
|
1069
|
-
await
|
|
1156
|
+
await retryInitStep({
|
|
1157
|
+
status,
|
|
1158
|
+
title: "Ensuring sprite daemon service",
|
|
1159
|
+
fn: async () => await ensureSpriteDaemonService({ client, spriteName: canonical }),
|
|
1160
|
+
});
|
|
1070
1161
|
await updateInitState({ steps: { daemonServiceEnsured: true } });
|
|
1071
1162
|
}
|
|
1072
1163
|
catch (error) {
|
|
@@ -1075,12 +1166,7 @@ export const runInit = async (args) => {
|
|
|
1075
1166
|
error: String(error),
|
|
1076
1167
|
});
|
|
1077
1168
|
fail("Ensuring sprite daemon service (failed)");
|
|
1078
|
-
|
|
1079
|
-
const message = error instanceof Error && error.message
|
|
1080
|
-
? error.message
|
|
1081
|
-
: String(error);
|
|
1082
|
-
console.warn(`Warning: failed to ensure sprite daemon service. ${message}`);
|
|
1083
|
-
}
|
|
1169
|
+
throw error;
|
|
1084
1170
|
}
|
|
1085
1171
|
},
|
|
1086
1172
|
});
|
|
@@ -1897,12 +1983,15 @@ export const runInit = async (args) => {
|
|
|
1897
1983
|
enabled: progressEnabled,
|
|
1898
1984
|
title: "Ensuring workdir ownership",
|
|
1899
1985
|
fn: async ({ status }) => {
|
|
1900
|
-
await
|
|
1901
|
-
client,
|
|
1902
|
-
canonical,
|
|
1903
|
-
workdir: expandedWorkdir,
|
|
1986
|
+
await retryInitStep({
|
|
1904
1987
|
status,
|
|
1905
|
-
|
|
1988
|
+
title: "Ensuring workdir ownership",
|
|
1989
|
+
fn: async () => await ensureWorkdirOwnership({
|
|
1990
|
+
client,
|
|
1991
|
+
canonical,
|
|
1992
|
+
workdir: expandedWorkdir,
|
|
1993
|
+
status,
|
|
1994
|
+
}),
|
|
1906
1995
|
});
|
|
1907
1996
|
},
|
|
1908
1997
|
});
|
|
@@ -1927,13 +2016,19 @@ export const runInit = async (args) => {
|
|
|
1927
2016
|
await runInitStep({
|
|
1928
2017
|
enabled: progressEnabled,
|
|
1929
2018
|
title: "Configuring SSH mount access",
|
|
1930
|
-
fn: async ({ fail }) => {
|
|
2019
|
+
fn: async ({ status, fail }) => {
|
|
1931
2020
|
try {
|
|
1932
|
-
await
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1936
|
-
|
|
2021
|
+
await retryInitStep({
|
|
2022
|
+
status,
|
|
2023
|
+
title: "Configuring SSH mount access",
|
|
2024
|
+
fn: async () => {
|
|
2025
|
+
await ensureLocalMountKey();
|
|
2026
|
+
await ensureKnownHostsFile();
|
|
2027
|
+
const publicKey = await readLocalMountPublicKey();
|
|
2028
|
+
await ensureRemoteMountAccess(client, canonical, publicKey);
|
|
2029
|
+
await ensureSshdService(client, canonical);
|
|
2030
|
+
},
|
|
2031
|
+
});
|
|
1937
2032
|
await updateInitState({ steps: { sshdConfigured: true } });
|
|
1938
2033
|
}
|
|
1939
2034
|
catch (error) {
|
|
@@ -1942,13 +2037,7 @@ export const runInit = async (args) => {
|
|
|
1942
2037
|
error: String(error),
|
|
1943
2038
|
});
|
|
1944
2039
|
fail("Configuring SSH mount access (failed)");
|
|
1945
|
-
|
|
1946
|
-
const message = error instanceof Error && error.message
|
|
1947
|
-
? error.message
|
|
1948
|
-
: String(error);
|
|
1949
|
-
console.warn(`Warning: failed to configure SSH mount access. ${message}`);
|
|
1950
|
-
console.warn(`To retry later: dvb mount ${alias}`);
|
|
1951
|
-
}
|
|
2040
|
+
throw error;
|
|
1952
2041
|
}
|
|
1953
2042
|
},
|
|
1954
2043
|
});
|
|
@@ -2086,10 +2175,12 @@ export const runInit = async (args) => {
|
|
|
2086
2175
|
}
|
|
2087
2176
|
const weztermMuxPresent = await runInitStep({
|
|
2088
2177
|
enabled: progressEnabled,
|
|
2089
|
-
title: "Ensuring WezTerm mux server
|
|
2090
|
-
fn: async ({
|
|
2091
|
-
|
|
2092
|
-
|
|
2178
|
+
title: "Ensuring WezTerm mux server",
|
|
2179
|
+
fn: async ({ status }) => {
|
|
2180
|
+
const installResult = await retryInitStep({
|
|
2181
|
+
status,
|
|
2182
|
+
title: "Ensuring WezTerm mux server",
|
|
2183
|
+
fn: async () => !shouldResume || !initState?.steps.weztermMuxInstalled
|
|
2093
2184
|
? await ensureWeztermMuxInstalled({
|
|
2094
2185
|
client,
|
|
2095
2186
|
spriteName: canonical,
|
|
@@ -2100,52 +2191,29 @@ export const runInit = async (args) => {
|
|
|
2100
2191
|
spriteName: canonical,
|
|
2101
2192
|
// If the mux is missing on resume, we still need to resolve a GitHub asset.
|
|
2102
2193
|
allowResolveAsset: true,
|
|
2103
|
-
})
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
}
|
|
2107
|
-
return
|
|
2108
|
-
}
|
|
2109
|
-
catch (error) {
|
|
2110
|
-
logger.warn("wezterm_mux_install_failed", {
|
|
2111
|
-
box: canonical,
|
|
2112
|
-
error: error instanceof Error ? error.message : String(error),
|
|
2113
|
-
});
|
|
2114
|
-
fail("Ensuring WezTerm mux server (optional) (failed)");
|
|
2115
|
-
if (!parsed.json) {
|
|
2116
|
-
const message = error instanceof Error && error.message
|
|
2117
|
-
? error.message
|
|
2118
|
-
: String(error);
|
|
2119
|
-
console.warn(`Warning: failed to install WezTerm mux server (optional). ${message}\n` +
|
|
2120
|
-
"Tip: re-run with DEVBOX_LOG_LEVEL=info to see Sprite exec logs on stderr.");
|
|
2121
|
-
}
|
|
2122
|
-
return false;
|
|
2194
|
+
}),
|
|
2195
|
+
});
|
|
2196
|
+
if (installResult.muxPresent) {
|
|
2197
|
+
await updateInitState({ steps: { weztermMuxInstalled: true } });
|
|
2198
|
+
return true;
|
|
2123
2199
|
}
|
|
2200
|
+
throw new Error("WezTerm mux server unavailable.");
|
|
2124
2201
|
},
|
|
2125
2202
|
});
|
|
2126
|
-
if (
|
|
2127
|
-
(!shouldResume || !initState?.steps.weztermMuxServiceEnsured)) {
|
|
2203
|
+
if (!shouldResume || !initState?.steps.weztermMuxServiceEnsured) {
|
|
2128
2204
|
await runInitStep({
|
|
2129
2205
|
enabled: progressEnabled,
|
|
2130
|
-
title: "Ensuring WezTerm mux service
|
|
2131
|
-
fn: async ({
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
await updateInitState({ steps: { weztermMuxServiceEnsured: true } });
|
|
2135
|
-
}
|
|
2136
|
-
catch (error) {
|
|
2137
|
-
logger.warn("wezterm_mux_service_failed", {
|
|
2138
|
-
box: canonical,
|
|
2139
|
-
error: error instanceof Error ? error.message : String(error),
|
|
2140
|
-
});
|
|
2141
|
-
fail("Ensuring WezTerm mux service (optional) (failed)");
|
|
2142
|
-
if (!parsed.json) {
|
|
2143
|
-
const message = error instanceof Error && error.message
|
|
2144
|
-
? error.message
|
|
2145
|
-
: String(error);
|
|
2146
|
-
console.warn(`Warning: failed to ensure WezTerm mux service (optional). ${message}`);
|
|
2147
|
-
}
|
|
2206
|
+
title: "Ensuring WezTerm mux service",
|
|
2207
|
+
fn: async ({ status }) => {
|
|
2208
|
+
if (!weztermMuxPresent) {
|
|
2209
|
+
throw new Error("WezTerm mux server unavailable.");
|
|
2148
2210
|
}
|
|
2211
|
+
await retryInitStep({
|
|
2212
|
+
status,
|
|
2213
|
+
title: "Ensuring WezTerm mux service",
|
|
2214
|
+
fn: async () => await ensureWeztermMuxService({ client, spriteName: canonical }),
|
|
2215
|
+
});
|
|
2216
|
+
await updateInitState({ steps: { weztermMuxServiceEnsured: true } });
|
|
2149
2217
|
},
|
|
2150
2218
|
});
|
|
2151
2219
|
}
|
|
@@ -2213,20 +2281,13 @@ export const runInit = async (args) => {
|
|
|
2213
2281
|
});
|
|
2214
2282
|
await runInitStep({
|
|
2215
2283
|
enabled: progressEnabled,
|
|
2216
|
-
title: "Updating Codex config on sprite
|
|
2217
|
-
fn: async ({
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
error: String(error),
|
|
2224
|
-
});
|
|
2225
|
-
fail("Updating Codex config on sprite (optional) (failed)");
|
|
2226
|
-
if (!parsed.json) {
|
|
2227
|
-
console.warn("Warning: failed to update /home/sprite/.codex/config.toml for full-access sandbox settings.");
|
|
2228
|
-
}
|
|
2229
|
-
}
|
|
2284
|
+
title: "Updating Codex config on sprite",
|
|
2285
|
+
fn: async ({ status }) => {
|
|
2286
|
+
await retryInitStep({
|
|
2287
|
+
status,
|
|
2288
|
+
title: "Updating Codex config on sprite",
|
|
2289
|
+
fn: async () => await writeRemoteCodexConfig(client, canonical, repoName),
|
|
2290
|
+
});
|
|
2230
2291
|
},
|
|
2231
2292
|
});
|
|
2232
2293
|
const skipSetupArtifactsStage = skipCodexApply ||
|
|
@@ -2251,13 +2312,17 @@ export const runInit = async (args) => {
|
|
|
2251
2312
|
if (!skipCodexApply) {
|
|
2252
2313
|
await runInitStep({
|
|
2253
2314
|
enabled: progressEnabled,
|
|
2254
|
-
title: "Snapshotting filesystem (pre-setup)
|
|
2255
|
-
fn: async ({ fail, ok }) => {
|
|
2315
|
+
title: "Snapshotting filesystem (pre-setup)",
|
|
2316
|
+
fn: async ({ status, fail, ok }) => {
|
|
2256
2317
|
try {
|
|
2257
|
-
const checkpoint = await
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2318
|
+
const checkpoint = await retryInitStep({
|
|
2319
|
+
status,
|
|
2320
|
+
title: "Snapshotting filesystem (pre-setup)",
|
|
2321
|
+
fn: async () => await recordCodexCheckpoint({
|
|
2322
|
+
client,
|
|
2323
|
+
canonical,
|
|
2324
|
+
phase: "preCodexSetup",
|
|
2325
|
+
}),
|
|
2261
2326
|
});
|
|
2262
2327
|
if (checkpoint.id) {
|
|
2263
2328
|
ok(`Snapshot created: ${checkpoint.id}`);
|
|
@@ -2270,10 +2335,8 @@ export const runInit = async (args) => {
|
|
|
2270
2335
|
phase: "pre-codex-setup",
|
|
2271
2336
|
error: error instanceof Error ? error.message : String(error),
|
|
2272
2337
|
});
|
|
2273
|
-
fail("Snapshotting filesystem (pre-setup) (
|
|
2274
|
-
|
|
2275
|
-
console.warn("Warning: failed to create pre-setup filesystem snapshot. Continuing without it.");
|
|
2276
|
-
}
|
|
2338
|
+
fail("Snapshotting filesystem (pre-setup) (failed)");
|
|
2339
|
+
throw error;
|
|
2277
2340
|
}
|
|
2278
2341
|
},
|
|
2279
2342
|
});
|
|
@@ -2314,13 +2377,17 @@ export const runInit = async (args) => {
|
|
|
2314
2377
|
await updateRegistryProjectStatus(resolveInitStatus(initState?.steps, initState?.complete));
|
|
2315
2378
|
await runInitStep({
|
|
2316
2379
|
enabled: progressEnabled,
|
|
2317
|
-
title: "Snapshotting filesystem (post-setup)
|
|
2318
|
-
fn: async ({ fail, ok }) => {
|
|
2380
|
+
title: "Snapshotting filesystem (post-setup)",
|
|
2381
|
+
fn: async ({ status, fail, ok }) => {
|
|
2319
2382
|
try {
|
|
2320
|
-
const checkpoint = await
|
|
2321
|
-
|
|
2322
|
-
|
|
2323
|
-
|
|
2383
|
+
const checkpoint = await retryInitStep({
|
|
2384
|
+
status,
|
|
2385
|
+
title: "Snapshotting filesystem (post-setup)",
|
|
2386
|
+
fn: async () => await recordCodexCheckpoint({
|
|
2387
|
+
client,
|
|
2388
|
+
canonical,
|
|
2389
|
+
phase: "postCodexSetup",
|
|
2390
|
+
}),
|
|
2324
2391
|
});
|
|
2325
2392
|
if (checkpoint.id) {
|
|
2326
2393
|
ok(`Snapshot created: ${checkpoint.id}`);
|
|
@@ -2333,10 +2400,8 @@ export const runInit = async (args) => {
|
|
|
2333
2400
|
phase: "post-codex-setup",
|
|
2334
2401
|
error: error instanceof Error ? error.message : String(error),
|
|
2335
2402
|
});
|
|
2336
|
-
fail("Snapshotting filesystem (post-setup) (
|
|
2337
|
-
|
|
2338
|
-
console.warn("Warning: failed to create post-setup filesystem snapshot. Continuing without it.");
|
|
2339
|
-
}
|
|
2403
|
+
fail("Snapshotting filesystem (post-setup) (failed)");
|
|
2404
|
+
throw error;
|
|
2340
2405
|
}
|
|
2341
2406
|
},
|
|
2342
2407
|
});
|