@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
package/dist/bin/dvb.cjs
CHANGED
|
@@ -423,7 +423,7 @@ var init_repo = __esm({
|
|
|
423
423
|
});
|
|
424
424
|
|
|
425
425
|
// ../core/src/sprites.ts
|
|
426
|
-
var import_node_crypto, import_node_util, import_ws, SpritesApiError, logger, USE_INTERNAL_SERVICE_API, INTERNAL_SERVICE_SIGNAL_TIMEOUT_SECONDS, toWebSocketErrorInfo, toWsUrl, shellQuote, requestJson, listSprites, requestNdjson, writeFile, normalizeServiceRecord, readFile, openExecSocket, attachExecSocket, openProxySocket, listExecSessions, listServices, internalServicesRequest, createCheckpointInternal, listServicesInternal, getServiceInternal, createServiceInternal, startServiceInternal, stopServiceInternal, execCommand, createSpritesClient;
|
|
426
|
+
var import_node_crypto, import_node_util, import_ws, SpritesApiError, logger, USE_INTERNAL_SERVICE_API, INTERNAL_SERVICE_SIGNAL_TIMEOUT_SECONDS, toWebSocketErrorInfo, toWsUrl, shellQuote, DEFAULT_SPRITES_HTTP_TIMEOUT_MS_IDEMPOTENT, DEFAULT_SPRITES_HTTP_TIMEOUT_MS_NON_IDEMPOTENT, DEFAULT_SPRITES_HTTP_MAX_ATTEMPTS, SPRITES_HTTP_RETRYABLE_STATUSES, delay, isIdempotentMethod, computeRetryDelayMs, isAbortError, getErrorCode, isRetryableFetchError, shouldRetrySpritesRequest, withSpritesRetry, requestJson, listSprites, requestNdjson, writeFile, normalizeServiceRecord, readFile, openExecSocket, attachExecSocket, openProxySocket, listExecSessions, listServices, internalServicesRequest, createCheckpointInternal, listServicesInternal, getServiceInternal, createServiceInternal, startServiceInternal, stopServiceInternal, execCommand, createSpritesClient;
|
|
427
427
|
var init_sprites = __esm({
|
|
428
428
|
"../core/src/sprites.ts"() {
|
|
429
429
|
"use strict";
|
|
@@ -491,39 +491,126 @@ var init_sprites = __esm({
|
|
|
491
491
|
return new URL(path26, `${protocol}//${base.host}`);
|
|
492
492
|
};
|
|
493
493
|
shellQuote = (value) => `'${value.replace(/'/g, `'\\''`)}'`;
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
const
|
|
505
|
-
|
|
506
|
-
|
|
494
|
+
DEFAULT_SPRITES_HTTP_TIMEOUT_MS_IDEMPOTENT = 5e3;
|
|
495
|
+
DEFAULT_SPRITES_HTTP_TIMEOUT_MS_NON_IDEMPOTENT = 2e4;
|
|
496
|
+
DEFAULT_SPRITES_HTTP_MAX_ATTEMPTS = 5;
|
|
497
|
+
SPRITES_HTTP_RETRYABLE_STATUSES = /* @__PURE__ */ new Set([408, 409, 425, 429, 500, 502, 503, 504]);
|
|
498
|
+
delay = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
499
|
+
isIdempotentMethod = (method) => {
|
|
500
|
+
const normalized = method.toUpperCase();
|
|
501
|
+
return normalized === "GET" || normalized === "HEAD" || normalized === "PUT" || normalized === "DELETE" || normalized === "OPTIONS";
|
|
502
|
+
};
|
|
503
|
+
computeRetryDelayMs = (attempt) => {
|
|
504
|
+
const base = 250;
|
|
505
|
+
const cap = 2500;
|
|
506
|
+
const exp = Math.min(cap, base * 2 ** Math.max(0, attempt - 1));
|
|
507
|
+
const jitter = Math.floor(Math.random() * 120);
|
|
508
|
+
return exp + jitter;
|
|
509
|
+
};
|
|
510
|
+
isAbortError = (error) => error instanceof Error && (error.name === "AbortError" || error.message.includes("aborted"));
|
|
511
|
+
getErrorCode = (error) => {
|
|
512
|
+
if (!error || typeof error !== "object") return void 0;
|
|
513
|
+
const record = error;
|
|
514
|
+
const code2 = record.code;
|
|
515
|
+
return typeof code2 === "string" || typeof code2 === "number" ? String(code2) : void 0;
|
|
516
|
+
};
|
|
517
|
+
isRetryableFetchError = (error) => {
|
|
518
|
+
if (isAbortError(error)) return true;
|
|
519
|
+
if (error instanceof TypeError) return true;
|
|
520
|
+
const code2 = getErrorCode(error);
|
|
521
|
+
return code2 === "ECONNRESET" || code2 === "ETIMEDOUT" || code2 === "EAI_AGAIN" || code2 === "ENOTFOUND" || code2 === "ECONNREFUSED";
|
|
522
|
+
};
|
|
523
|
+
shouldRetrySpritesRequest = (method, error) => {
|
|
524
|
+
if (!isIdempotentMethod(method)) return false;
|
|
525
|
+
if (error instanceof SpritesApiError) {
|
|
526
|
+
return SPRITES_HTTP_RETRYABLE_STATUSES.has(error.status);
|
|
527
|
+
}
|
|
528
|
+
return isRetryableFetchError(error);
|
|
529
|
+
};
|
|
530
|
+
withSpritesRetry = async (options) => {
|
|
531
|
+
const opId = (0, import_node_crypto.randomUUID)();
|
|
532
|
+
const timeoutMs = options.timeoutMs ?? (isIdempotentMethod(options.method) ? DEFAULT_SPRITES_HTTP_TIMEOUT_MS_IDEMPOTENT : DEFAULT_SPRITES_HTTP_TIMEOUT_MS_NON_IDEMPOTENT);
|
|
533
|
+
const maxAttemptsRaw = options.maxAttempts ?? DEFAULT_SPRITES_HTTP_MAX_ATTEMPTS;
|
|
534
|
+
const maxAttempts = isIdempotentMethod(options.method) ? Math.max(1, maxAttemptsRaw) : 1;
|
|
535
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
536
|
+
const requestId = (0, import_node_crypto.randomUUID)();
|
|
537
|
+
const controller = new AbortController();
|
|
538
|
+
const timeoutHandle = typeof timeoutMs === "number" && timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
539
|
+
try {
|
|
540
|
+
logger.info("sprites_request", {
|
|
541
|
+
opId,
|
|
542
|
+
attempt,
|
|
543
|
+
requestId,
|
|
544
|
+
method: options.method,
|
|
545
|
+
path: options.path,
|
|
546
|
+
timeoutMs
|
|
547
|
+
});
|
|
548
|
+
return await options.run(controller.signal, requestId);
|
|
549
|
+
} catch (error) {
|
|
550
|
+
const retryable = shouldRetrySpritesRequest(options.method, error);
|
|
551
|
+
const remaining = maxAttempts - attempt;
|
|
552
|
+
if (!retryable || remaining <= 0) {
|
|
553
|
+
throw error;
|
|
554
|
+
}
|
|
555
|
+
const delayMs = computeRetryDelayMs(attempt);
|
|
556
|
+
logger.warn("sprites_http_retry", {
|
|
557
|
+
opId,
|
|
558
|
+
attempt,
|
|
559
|
+
requestId,
|
|
560
|
+
method: options.method,
|
|
561
|
+
path: options.path,
|
|
562
|
+
timeoutMs,
|
|
563
|
+
delayMs,
|
|
564
|
+
remainingAttempts: remaining,
|
|
565
|
+
errorName: error instanceof Error ? error.name : void 0,
|
|
566
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
567
|
+
errorCode: getErrorCode(error),
|
|
568
|
+
...error instanceof SpritesApiError ? { status: error.status } : {}
|
|
569
|
+
});
|
|
570
|
+
await delay(delayMs);
|
|
571
|
+
} finally {
|
|
572
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
573
|
+
}
|
|
507
574
|
}
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
requestId,
|
|
575
|
+
throw new Error(`Sprites request failed: ${options.method} ${options.path}`);
|
|
576
|
+
};
|
|
577
|
+
requestJson = async (apiBaseUrl, token, method, path26, body) => {
|
|
578
|
+
return await withSpritesRetry({
|
|
513
579
|
method,
|
|
514
580
|
path: path26,
|
|
515
|
-
|
|
581
|
+
run: async (signal, requestId) => {
|
|
582
|
+
const url = new URL(path26, apiBaseUrl);
|
|
583
|
+
const headers = {
|
|
584
|
+
authorization: `Bearer ${token}`,
|
|
585
|
+
"x-request-id": requestId
|
|
586
|
+
};
|
|
587
|
+
if (body) {
|
|
588
|
+
headers["content-type"] = "application/json";
|
|
589
|
+
}
|
|
590
|
+
const init = { method, headers, signal };
|
|
591
|
+
if (body) {
|
|
592
|
+
init.body = JSON.stringify(body);
|
|
593
|
+
}
|
|
594
|
+
const response = await fetch(url, init);
|
|
595
|
+
const text = await response.text();
|
|
596
|
+
logger.info("sprites_response", {
|
|
597
|
+
requestId,
|
|
598
|
+
method,
|
|
599
|
+
path: path26,
|
|
600
|
+
status: response.status
|
|
601
|
+
});
|
|
602
|
+
if (!response.ok) {
|
|
603
|
+
const snippet = text.trim().slice(0, 200);
|
|
604
|
+
throw new SpritesApiError(response.status, method, path26, snippet);
|
|
605
|
+
}
|
|
606
|
+
if (!text) return null;
|
|
607
|
+
try {
|
|
608
|
+
return JSON.parse(text);
|
|
609
|
+
} catch {
|
|
610
|
+
return text;
|
|
611
|
+
}
|
|
612
|
+
}
|
|
516
613
|
});
|
|
517
|
-
if (!response.ok) {
|
|
518
|
-
const snippet = text.trim().slice(0, 200);
|
|
519
|
-
throw new SpritesApiError(response.status, method, path26, snippet);
|
|
520
|
-
}
|
|
521
|
-
if (!text) return null;
|
|
522
|
-
try {
|
|
523
|
-
return JSON.parse(text);
|
|
524
|
-
} catch {
|
|
525
|
-
return text;
|
|
526
|
-
}
|
|
527
614
|
};
|
|
528
615
|
listSprites = async (apiBaseUrl, token, options) => {
|
|
529
616
|
const params = new URLSearchParams();
|
|
@@ -564,88 +651,99 @@ var init_sprites = __esm({
|
|
|
564
651
|
return response;
|
|
565
652
|
};
|
|
566
653
|
requestNdjson = async (apiBaseUrl, token, method, path26, body) => {
|
|
567
|
-
|
|
568
|
-
const url = new URL(path26, apiBaseUrl);
|
|
569
|
-
const headers = {
|
|
570
|
-
authorization: `Bearer ${token}`,
|
|
571
|
-
"x-request-id": requestId
|
|
572
|
-
};
|
|
573
|
-
if (body) {
|
|
574
|
-
headers["content-type"] = "application/json";
|
|
575
|
-
}
|
|
576
|
-
const init = { method, headers };
|
|
577
|
-
if (body) {
|
|
578
|
-
init.body = JSON.stringify(body);
|
|
579
|
-
}
|
|
580
|
-
logger.info("sprites_request", { requestId, method, path: path26 });
|
|
581
|
-
const response = await fetch(url, init);
|
|
582
|
-
logger.info("sprites_response", {
|
|
583
|
-
requestId,
|
|
654
|
+
return await withSpritesRetry({
|
|
584
655
|
method,
|
|
585
656
|
path: path26,
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
|
|
657
|
+
run: async (signal, requestId) => {
|
|
658
|
+
const url = new URL(path26, apiBaseUrl);
|
|
659
|
+
const headers = {
|
|
660
|
+
authorization: `Bearer ${token}`,
|
|
661
|
+
"x-request-id": requestId
|
|
662
|
+
};
|
|
663
|
+
if (body) {
|
|
664
|
+
headers["content-type"] = "application/json";
|
|
665
|
+
}
|
|
666
|
+
const init = { method, headers, signal };
|
|
667
|
+
if (body) {
|
|
668
|
+
init.body = JSON.stringify(body);
|
|
669
|
+
}
|
|
670
|
+
const response = await fetch(url, init);
|
|
671
|
+
logger.info("sprites_response", {
|
|
672
|
+
requestId,
|
|
673
|
+
method,
|
|
674
|
+
path: path26,
|
|
675
|
+
status: response.status
|
|
676
|
+
});
|
|
677
|
+
const text = await response.text();
|
|
678
|
+
if (!response.ok) {
|
|
679
|
+
const snippet = text.trim().slice(0, 200);
|
|
680
|
+
throw new SpritesApiError(response.status, method, path26, snippet);
|
|
681
|
+
}
|
|
682
|
+
const lines = text.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
683
|
+
const events = [];
|
|
684
|
+
for (const line of lines) {
|
|
685
|
+
try {
|
|
686
|
+
const parsed = JSON.parse(line);
|
|
687
|
+
if (Array.isArray(parsed)) {
|
|
688
|
+
for (const entry of parsed) {
|
|
689
|
+
if (entry && typeof entry === "object") {
|
|
690
|
+
events.push(entry);
|
|
691
|
+
} else {
|
|
692
|
+
events.push({ value: entry });
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
continue;
|
|
696
|
+
}
|
|
697
|
+
if (parsed && typeof parsed === "object") {
|
|
698
|
+
events.push(parsed);
|
|
699
|
+
continue;
|
|
604
700
|
}
|
|
701
|
+
events.push({ value: parsed });
|
|
702
|
+
} catch {
|
|
703
|
+
events.push({ raw: line });
|
|
605
704
|
}
|
|
606
|
-
continue;
|
|
607
705
|
}
|
|
608
|
-
|
|
609
|
-
events.push(parsed);
|
|
610
|
-
continue;
|
|
611
|
-
}
|
|
612
|
-
events.push({ value: parsed });
|
|
613
|
-
} catch {
|
|
614
|
-
events.push({ raw: line });
|
|
706
|
+
return events;
|
|
615
707
|
}
|
|
616
|
-
}
|
|
617
|
-
return events;
|
|
708
|
+
});
|
|
618
709
|
};
|
|
619
710
|
writeFile = async (apiBaseUrl, token, name, remotePath, data) => {
|
|
620
|
-
const requestId = (0, import_node_crypto.randomUUID)();
|
|
621
711
|
const path26 = `/v1/sprites/${name}/fs/write`;
|
|
622
712
|
const url = new URL(path26, apiBaseUrl);
|
|
623
713
|
url.searchParams.set("path", remotePath);
|
|
624
714
|
url.searchParams.set("mkdir", "true");
|
|
625
|
-
|
|
626
|
-
requestId,
|
|
627
|
-
path: path26,
|
|
628
|
-
name,
|
|
629
|
-
remotePath,
|
|
630
|
-
size: data.length
|
|
631
|
-
});
|
|
632
|
-
const response = await fetch(url, {
|
|
715
|
+
await withSpritesRetry({
|
|
633
716
|
method: "PUT",
|
|
634
|
-
headers: {
|
|
635
|
-
authorization: `Bearer ${token}`,
|
|
636
|
-
"content-type": "application/octet-stream",
|
|
637
|
-
"x-request-id": requestId
|
|
638
|
-
},
|
|
639
|
-
body: data
|
|
640
|
-
});
|
|
641
|
-
logger.info("sprites_fs_write_response", {
|
|
642
|
-
requestId,
|
|
643
717
|
path: path26,
|
|
644
|
-
|
|
718
|
+
run: async (signal, requestId) => {
|
|
719
|
+
logger.info("sprites_fs_write", {
|
|
720
|
+
requestId,
|
|
721
|
+
path: path26,
|
|
722
|
+
name,
|
|
723
|
+
remotePath,
|
|
724
|
+
size: data.length
|
|
725
|
+
});
|
|
726
|
+
const response = await fetch(url, {
|
|
727
|
+
method: "PUT",
|
|
728
|
+
headers: {
|
|
729
|
+
authorization: `Bearer ${token}`,
|
|
730
|
+
"content-type": "application/octet-stream",
|
|
731
|
+
"x-request-id": requestId
|
|
732
|
+
},
|
|
733
|
+
body: data,
|
|
734
|
+
signal
|
|
735
|
+
});
|
|
736
|
+
logger.info("sprites_fs_write_response", {
|
|
737
|
+
requestId,
|
|
738
|
+
path: path26,
|
|
739
|
+
status: response.status
|
|
740
|
+
});
|
|
741
|
+
if (!response.ok) {
|
|
742
|
+
const snippet = (await response.text()).trim().slice(0, 200);
|
|
743
|
+
throw new SpritesApiError(response.status, "PUT", path26, snippet);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
645
746
|
});
|
|
646
|
-
if (!response.ok) {
|
|
647
|
-
throw new Error(`Sprites FS write failed: ${response.status}`);
|
|
648
|
-
}
|
|
649
747
|
};
|
|
650
748
|
normalizeServiceRecord = (entry) => {
|
|
651
749
|
const rawName = entry.name;
|
|
@@ -676,38 +774,44 @@ var init_sprites = __esm({
|
|
|
676
774
|
return service;
|
|
677
775
|
};
|
|
678
776
|
readFile = async (apiBaseUrl, token, name, options) => {
|
|
679
|
-
const requestId = (0, import_node_crypto.randomUUID)();
|
|
680
777
|
const path26 = `/v1/sprites/${name}/fs/read`;
|
|
681
778
|
const url = new URL(path26, apiBaseUrl);
|
|
682
779
|
url.searchParams.set("path", options.path);
|
|
683
780
|
if (options.workingDir) {
|
|
684
781
|
url.searchParams.set("workingDir", options.workingDir);
|
|
685
782
|
}
|
|
686
|
-
|
|
687
|
-
requestId,
|
|
688
|
-
path: path26,
|
|
689
|
-
name,
|
|
690
|
-
remotePath: options.path,
|
|
691
|
-
workingDir: options.workingDir
|
|
692
|
-
});
|
|
693
|
-
const response = await fetch(url, {
|
|
783
|
+
return await withSpritesRetry({
|
|
694
784
|
method: "GET",
|
|
695
|
-
headers: {
|
|
696
|
-
authorization: `Bearer ${token}`,
|
|
697
|
-
"x-request-id": requestId
|
|
698
|
-
}
|
|
699
|
-
});
|
|
700
|
-
logger.info("sprites_fs_read_response", {
|
|
701
|
-
requestId,
|
|
702
785
|
path: path26,
|
|
703
|
-
|
|
786
|
+
run: async (signal, requestId) => {
|
|
787
|
+
logger.info("sprites_fs_read", {
|
|
788
|
+
requestId,
|
|
789
|
+
path: path26,
|
|
790
|
+
name,
|
|
791
|
+
remotePath: options.path,
|
|
792
|
+
workingDir: options.workingDir
|
|
793
|
+
});
|
|
794
|
+
const response = await fetch(url, {
|
|
795
|
+
method: "GET",
|
|
796
|
+
headers: {
|
|
797
|
+
authorization: `Bearer ${token}`,
|
|
798
|
+
"x-request-id": requestId
|
|
799
|
+
},
|
|
800
|
+
signal
|
|
801
|
+
});
|
|
802
|
+
logger.info("sprites_fs_read_response", {
|
|
803
|
+
requestId,
|
|
804
|
+
path: path26,
|
|
805
|
+
status: response.status
|
|
806
|
+
});
|
|
807
|
+
if (!response.ok) {
|
|
808
|
+
const snippet = (await response.text()).trim().slice(0, 200);
|
|
809
|
+
throw new SpritesApiError(response.status, "GET", path26, snippet);
|
|
810
|
+
}
|
|
811
|
+
const buffer = await response.arrayBuffer();
|
|
812
|
+
return new Uint8Array(buffer);
|
|
813
|
+
}
|
|
704
814
|
});
|
|
705
|
-
if (!response.ok) {
|
|
706
|
-
const snippet = (await response.text()).trim().slice(0, 200);
|
|
707
|
-
throw new SpritesApiError(response.status, "GET", path26, snippet);
|
|
708
|
-
}
|
|
709
|
-
const buffer = await response.arrayBuffer();
|
|
710
|
-
return new Uint8Array(buffer);
|
|
711
815
|
};
|
|
712
816
|
openExecSocket = (apiBaseUrl, token, name, options) => {
|
|
713
817
|
const url = toWsUrl(apiBaseUrl, `/v1/sprites/${name}/exec`);
|
|
@@ -4748,27 +4852,27 @@ var init_authentication_manager = __esm({
|
|
|
4748
4852
|
);
|
|
4749
4853
|
return;
|
|
4750
4854
|
}
|
|
4751
|
-
let
|
|
4855
|
+
let delay3 = Math.min(
|
|
4752
4856
|
MAXIMUM_REFRESH_DELAY,
|
|
4753
4857
|
(tokenValiditySeconds - this.refreshTokenLeewaySeconds) * 1e3
|
|
4754
4858
|
);
|
|
4755
|
-
if (
|
|
4859
|
+
if (delay3 <= 0) {
|
|
4756
4860
|
this.logger.warn(
|
|
4757
4861
|
`Refetching auth token immediately, configured leeway ${this.refreshTokenLeewaySeconds}s is larger than the token's lifetime ${tokenValiditySeconds}s`
|
|
4758
4862
|
);
|
|
4759
|
-
|
|
4863
|
+
delay3 = 0;
|
|
4760
4864
|
}
|
|
4761
4865
|
const refetchTokenTimeoutId = setTimeout(() => {
|
|
4762
4866
|
this._logVerbose("running scheduled token refetch");
|
|
4763
4867
|
void this.refetchToken();
|
|
4764
|
-
},
|
|
4868
|
+
}, delay3);
|
|
4765
4869
|
this.setAuthState({
|
|
4766
4870
|
state: "waitingForScheduledRefetch",
|
|
4767
4871
|
refetchTokenTimeoutId,
|
|
4768
4872
|
config: this.authState.config
|
|
4769
4873
|
});
|
|
4770
4874
|
this._logVerbose(
|
|
4771
|
-
`scheduled preemptive auth token refetching in ${
|
|
4875
|
+
`scheduled preemptive auth token refetching in ${delay3}ms`
|
|
4772
4876
|
);
|
|
4773
4877
|
}
|
|
4774
4878
|
// Protects against simultaneous calls to `setConfig`
|
|
@@ -19763,8 +19867,8 @@ var init_connect = __esm({
|
|
|
19763
19867
|
pendingPortLogs.set(event.port, token2);
|
|
19764
19868
|
const delays = [30, 60, 120, 200];
|
|
19765
19869
|
void (async () => {
|
|
19766
|
-
for (const
|
|
19767
|
-
await new Promise((resolve) => setTimeout(resolve,
|
|
19870
|
+
for (const delay3 of delays) {
|
|
19871
|
+
await new Promise((resolve) => setTimeout(resolve, delay3));
|
|
19768
19872
|
if (pendingPortLogs.get(event.port) !== token2) {
|
|
19769
19873
|
return;
|
|
19770
19874
|
}
|
|
@@ -22339,7 +22443,7 @@ var init_weztermMux = __esm({
|
|
|
22339
22443
|
});
|
|
22340
22444
|
|
|
22341
22445
|
// src/devbox/commands/init/remote.ts
|
|
22342
|
-
var import_node_crypto10, DAEMON_DIR, DAEMON_TARBALL, DAEMON_BUNDLE_DIR, DAEMON_ENTRY, DAEMON_WRAPPER, DAEMON_SERVICE_NAME, DAEMON_CONFIG_FILE, DEFAULT_DAEMON_BASE_URL, DEFAULT_HEARTBEAT_MS, BOOTSTRAP_EXEC_TIMEOUT_MS,
|
|
22446
|
+
var import_node_crypto10, DAEMON_DIR, DAEMON_TARBALL, DAEMON_BUNDLE_DIR, DAEMON_ENTRY, DAEMON_WRAPPER, DAEMON_SERVICE_NAME, DAEMON_CONFIG_FILE, DEFAULT_DAEMON_BASE_URL, DEFAULT_HEARTBEAT_MS, BOOTSTRAP_EXEC_TIMEOUT_MS, logger8, truncateTail, shellQuote3, expandHome2, execWithLog, writeRemoteFile, bootstrapDevbox, buildWeztermMuxConfig, buildWeztermMuxRunner, patchBashrc, writeRemoteCodexConfig, stageRemoteSetupArtifacts, resolveDaemonUrl, fetchDaemonBinary, buildDaemonConfig, isSameArgs, ensureSpriteDaemonService, installWeztermMux, ensureWeztermMuxService, hasWeztermMuxBinary, isWeztermMuxHealthy, installSpriteDaemon;
|
|
22343
22447
|
var init_remote = __esm({
|
|
22344
22448
|
"src/devbox/commands/init/remote.ts"() {
|
|
22345
22449
|
"use strict";
|
|
@@ -22358,7 +22462,6 @@ var init_remote = __esm({
|
|
|
22358
22462
|
DEFAULT_DAEMON_BASE_URL = process.env.SPRITE_DAEMON_BASE_URL?.trim() || "https://deploy-dev.boxes.dev";
|
|
22359
22463
|
DEFAULT_HEARTBEAT_MS = 3e4;
|
|
22360
22464
|
BOOTSTRAP_EXEC_TIMEOUT_MS = 9e4;
|
|
22361
|
-
BOOTSTRAP_EXEC_RETRY_DELAY_MS = 1e4;
|
|
22362
22465
|
logger8 = createLogger("devbox-init");
|
|
22363
22466
|
truncateTail = (value, maxChars) => {
|
|
22364
22467
|
if (value.length <= maxChars) return value;
|
|
@@ -22406,8 +22509,6 @@ var init_remote = __esm({
|
|
|
22406
22509
|
});
|
|
22407
22510
|
return result;
|
|
22408
22511
|
};
|
|
22409
|
-
isExecTimeoutError = (error) => error instanceof Error && typeof error.message === "string" && error.message.startsWith("Exec websocket timed out after ");
|
|
22410
|
-
delay = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
22411
22512
|
writeRemoteFile = async (client, canonical, path26, content, stage) => {
|
|
22412
22513
|
const requestId = (0, import_node_crypto10.randomUUID)();
|
|
22413
22514
|
logger8.info("sprites_request", {
|
|
@@ -22439,28 +22540,13 @@ var init_remote = __esm({
|
|
|
22439
22540
|
" sudo -n chown -R sprite:sprite /home/sprite/.devbox || true",
|
|
22440
22541
|
"fi"
|
|
22441
22542
|
].join("\n");
|
|
22442
|
-
|
|
22543
|
+
const permsResult = await execWithLog(
|
|
22443
22544
|
client,
|
|
22444
22545
|
canonical,
|
|
22445
22546
|
permissionsScript,
|
|
22446
22547
|
"bootstrap-permissions",
|
|
22447
22548
|
{ timeoutMs: BOOTSTRAP_EXEC_TIMEOUT_MS }
|
|
22448
|
-
)
|
|
22449
|
-
if (!isExecTimeoutError(error)) throw error;
|
|
22450
|
-
logger8.warn("sprites_exec_retry_after_timeout", {
|
|
22451
|
-
stage: "bootstrap-permissions",
|
|
22452
|
-
timeoutMs: BOOTSTRAP_EXEC_TIMEOUT_MS,
|
|
22453
|
-
delayMs: BOOTSTRAP_EXEC_RETRY_DELAY_MS
|
|
22454
|
-
});
|
|
22455
|
-
await delay(BOOTSTRAP_EXEC_RETRY_DELAY_MS);
|
|
22456
|
-
return await execWithLog(
|
|
22457
|
-
client,
|
|
22458
|
-
canonical,
|
|
22459
|
-
permissionsScript,
|
|
22460
|
-
"bootstrap-permissions",
|
|
22461
|
-
{ timeoutMs: BOOTSTRAP_EXEC_TIMEOUT_MS }
|
|
22462
|
-
);
|
|
22463
|
-
});
|
|
22549
|
+
);
|
|
22464
22550
|
if (permsResult.exitCode !== 0) {
|
|
22465
22551
|
const details = permsResult.stderr || permsResult.stdout || "";
|
|
22466
22552
|
throw new Error(
|
|
@@ -23943,17 +24029,26 @@ var init_template = __esm({
|
|
|
23943
24029
|
});
|
|
23944
24030
|
|
|
23945
24031
|
// src/devbox/commands/init/codex/prompts.ts
|
|
23946
|
-
var import_promises23, import_node_path17, resolvePromptsDir, readPromptTemplate, loadPrompt, loadLocalEnvSecretsScanPrompt, loadLocalExternalScanPrompt, loadLocalExtraArtifactsScanPrompt, loadLocalServicesScanPrompt;
|
|
24032
|
+
var import_node_fs5, import_promises23, import_node_path17, resolvePromptsDir, readPromptTemplate, loadPrompt, loadLocalEnvSecretsScanPrompt, loadLocalExternalScanPrompt, loadLocalExtraArtifactsScanPrompt, loadLocalServicesScanPrompt;
|
|
23947
24033
|
var init_prompts = __esm({
|
|
23948
24034
|
"src/devbox/commands/init/codex/prompts.ts"() {
|
|
23949
24035
|
"use strict";
|
|
24036
|
+
import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
23950
24037
|
import_promises23 = __toESM(require("node:fs/promises"), 1);
|
|
23951
24038
|
import_node_path17 = __toESM(require("node:path"), 1);
|
|
23952
24039
|
init_template();
|
|
23953
24040
|
resolvePromptsDir = () => {
|
|
23954
|
-
const
|
|
23955
|
-
if (
|
|
23956
|
-
|
|
24041
|
+
const argv1 = typeof process.argv[1] === "string" ? process.argv[1] : "";
|
|
24042
|
+
if (argv1) {
|
|
24043
|
+
try {
|
|
24044
|
+
const real = import_node_fs5.default.realpathSync(argv1);
|
|
24045
|
+
return import_node_path17.default.resolve(import_node_path17.default.dirname(real), "..", "prompts");
|
|
24046
|
+
} catch {
|
|
24047
|
+
}
|
|
24048
|
+
try {
|
|
24049
|
+
return import_node_path17.default.resolve(import_node_path17.default.dirname(argv1), "..", "prompts");
|
|
24050
|
+
} catch {
|
|
24051
|
+
}
|
|
23957
24052
|
}
|
|
23958
24053
|
return import_node_path17.default.resolve(process.cwd(), "prompts");
|
|
23959
24054
|
};
|
|
@@ -24475,18 +24570,18 @@ fi`
|
|
|
24475
24570
|
});
|
|
24476
24571
|
|
|
24477
24572
|
// src/devbox/commands/init/codex/plan.ts
|
|
24478
|
-
var import_node_path18,
|
|
24573
|
+
var import_node_path18, import_node_fs6, import_promises24, resolveSchemaPath, writeSetupEnvSecretsSchema, writeSetupExternalSchema, writeSetupExtraArtifactsSchema, writeServicesSchema, isObject4, isServicesSelection, isSetupPlan, isSetupEnvSecretsPlan, isSetupExternalPlan, isSetupExtraArtifactsPlan, isServicesPlan, readSetupPlan, readSetupEnvSecretsPlan, readSetupExternalPlan, readSetupExtraArtifactsPlan, readServicesPlan, writeSetupPlan, mergeSetupScans;
|
|
24479
24574
|
var init_plan = __esm({
|
|
24480
24575
|
"src/devbox/commands/init/codex/plan.ts"() {
|
|
24481
24576
|
"use strict";
|
|
24482
24577
|
import_node_path18 = __toESM(require("node:path"), 1);
|
|
24483
|
-
|
|
24578
|
+
import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
24484
24579
|
import_promises24 = __toESM(require("node:fs/promises"), 1);
|
|
24485
24580
|
resolveSchemaPath = (fileName) => {
|
|
24486
24581
|
const argv1 = typeof process.argv[1] === "string" ? process.argv[1] : "";
|
|
24487
24582
|
if (argv1) {
|
|
24488
24583
|
try {
|
|
24489
|
-
const real =
|
|
24584
|
+
const real = import_node_fs6.default.realpathSync(argv1);
|
|
24490
24585
|
return import_node_path18.default.resolve(import_node_path18.default.dirname(real), "..", "codex", fileName);
|
|
24491
24586
|
} catch {
|
|
24492
24587
|
}
|
|
@@ -24783,12 +24878,12 @@ ${bottom}
|
|
|
24783
24878
|
});
|
|
24784
24879
|
|
|
24785
24880
|
// src/devbox/commands/init/codex/local.ts
|
|
24786
|
-
var import_node_child_process9,
|
|
24881
|
+
var import_node_child_process9, import_node_fs7, import_promises25, import_node_path19, stripAnsi3, extractBoldText2, runCodexExec, runLocalSetupEnvSecretsScan, runLocalSetupExternalScan, runLocalSetupExtraArtifactsScan, runLocalServicesScan, toPosixPath, toRepoRelativePath, countSecretVars, buildEnvFileHint, buildExternalDependencyLabel, promptForPlanApproval, promptForServicesApproval;
|
|
24787
24882
|
var init_local = __esm({
|
|
24788
24883
|
"src/devbox/commands/init/codex/local.ts"() {
|
|
24789
24884
|
"use strict";
|
|
24790
24885
|
import_node_child_process9 = require("node:child_process");
|
|
24791
|
-
|
|
24886
|
+
import_node_fs7 = require("node:fs");
|
|
24792
24887
|
import_promises25 = __toESM(require("node:fs/promises"), 1);
|
|
24793
24888
|
import_node_path19 = __toESM(require("node:path"), 1);
|
|
24794
24889
|
init_dist2();
|
|
@@ -24807,11 +24902,11 @@ var init_local = __esm({
|
|
|
24807
24902
|
try {
|
|
24808
24903
|
if (stdoutLogPath) {
|
|
24809
24904
|
await import_promises25.default.mkdir(import_node_path19.default.dirname(stdoutLogPath), { recursive: true });
|
|
24810
|
-
stdoutStream = (0,
|
|
24905
|
+
stdoutStream = (0, import_node_fs7.createWriteStream)(stdoutLogPath, { flags: "a" });
|
|
24811
24906
|
}
|
|
24812
24907
|
if (stderrLogPath) {
|
|
24813
24908
|
await import_promises25.default.mkdir(import_node_path19.default.dirname(stderrLogPath), { recursive: true });
|
|
24814
|
-
stderrStream = (0,
|
|
24909
|
+
stderrStream = (0, import_node_fs7.createWriteStream)(stderrLogPath, { flags: "a" });
|
|
24815
24910
|
}
|
|
24816
24911
|
} catch {
|
|
24817
24912
|
stdoutStream = null;
|
|
@@ -26746,7 +26841,7 @@ var init_progress = __esm({
|
|
|
26746
26841
|
});
|
|
26747
26842
|
|
|
26748
26843
|
// src/devbox/commands/init/index.ts
|
|
26749
|
-
var import_node_path22, import_promises28, import_node_os9, resolveInitStatus, mergeLocalPaths, ensurePrivateDir, migrateLegacyRepoDevboxDir, buildServicesTomlUpdates, extractCheckpointId, writeRemoteServicesToml, enableRemoteServices, throwInitCanceled, promptBeforeOpenBrowser, toPosixPath2, toRepoRelativePath2, isOutsideRepoPath, ensureWorkdirOwnership, ensureGitSafeDirectory, runInit;
|
|
26844
|
+
var import_node_path22, import_promises28, import_node_os9, resolveInitStatus, mergeLocalPaths, ensurePrivateDir, DEFAULT_INIT_STEP_RETRIES, INIT_STEP_RETRYABLE_STATUSES, delay2, computeRetryDelayMs2, getErrorCode2, parseExecUnexpectedResponseStatus, isRetryableInitError, retryInitStep, migrateLegacyRepoDevboxDir, buildServicesTomlUpdates, extractCheckpointId, writeRemoteServicesToml, enableRemoteServices, throwInitCanceled, promptBeforeOpenBrowser, toPosixPath2, toRepoRelativePath2, isOutsideRepoPath, ensureWorkdirOwnership, ensureGitSafeDirectory, runInit;
|
|
26750
26845
|
var init_init = __esm({
|
|
26751
26846
|
"src/devbox/commands/init/index.ts"() {
|
|
26752
26847
|
"use strict";
|
|
@@ -26791,6 +26886,88 @@ var init_init = __esm({
|
|
|
26791
26886
|
} catch {
|
|
26792
26887
|
}
|
|
26793
26888
|
};
|
|
26889
|
+
DEFAULT_INIT_STEP_RETRIES = 3;
|
|
26890
|
+
INIT_STEP_RETRYABLE_STATUSES = /* @__PURE__ */ new Set([
|
|
26891
|
+
408,
|
|
26892
|
+
409,
|
|
26893
|
+
425,
|
|
26894
|
+
429,
|
|
26895
|
+
500,
|
|
26896
|
+
502,
|
|
26897
|
+
503,
|
|
26898
|
+
504
|
|
26899
|
+
]);
|
|
26900
|
+
delay2 = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
26901
|
+
computeRetryDelayMs2 = (retryIndex) => {
|
|
26902
|
+
const base = 500;
|
|
26903
|
+
const cap = 5e3;
|
|
26904
|
+
const exp = Math.min(cap, base * 2 ** Math.max(0, retryIndex - 1));
|
|
26905
|
+
const jitter = Math.floor(Math.random() * 150);
|
|
26906
|
+
return exp + jitter;
|
|
26907
|
+
};
|
|
26908
|
+
getErrorCode2 = (error) => {
|
|
26909
|
+
if (!error || typeof error !== "object") return void 0;
|
|
26910
|
+
const record = error;
|
|
26911
|
+
const code2 = record.code;
|
|
26912
|
+
return typeof code2 === "string" || typeof code2 === "number" ? String(code2) : void 0;
|
|
26913
|
+
};
|
|
26914
|
+
parseExecUnexpectedResponseStatus = (error) => {
|
|
26915
|
+
if (!(error instanceof Error)) return null;
|
|
26916
|
+
const match = /Unexpected server response: (\\d{3})/.exec(error.message);
|
|
26917
|
+
if (!match) return null;
|
|
26918
|
+
const status = Number(match[1]);
|
|
26919
|
+
return Number.isFinite(status) ? status : null;
|
|
26920
|
+
};
|
|
26921
|
+
isRetryableInitError = (error) => {
|
|
26922
|
+
if (error instanceof SpritesApiError) {
|
|
26923
|
+
return INIT_STEP_RETRYABLE_STATUSES.has(error.status);
|
|
26924
|
+
}
|
|
26925
|
+
if (error instanceof TypeError) return true;
|
|
26926
|
+
if (error instanceof Error && (error.name === "AbortError" || error.message.includes("aborted"))) {
|
|
26927
|
+
return true;
|
|
26928
|
+
}
|
|
26929
|
+
const execStatus = parseExecUnexpectedResponseStatus(error);
|
|
26930
|
+
if (execStatus !== null) {
|
|
26931
|
+
return INIT_STEP_RETRYABLE_STATUSES.has(execStatus);
|
|
26932
|
+
}
|
|
26933
|
+
const code2 = getErrorCode2(error);
|
|
26934
|
+
return code2 === "ECONNRESET" || code2 === "ETIMEDOUT" || code2 === "EAI_AGAIN" || code2 === "ENOTFOUND" || code2 === "ECONNREFUSED";
|
|
26935
|
+
};
|
|
26936
|
+
retryInitStep = async ({
|
|
26937
|
+
status,
|
|
26938
|
+
title,
|
|
26939
|
+
retries = DEFAULT_INIT_STEP_RETRIES,
|
|
26940
|
+
shouldRetry = isRetryableInitError,
|
|
26941
|
+
fn
|
|
26942
|
+
}) => {
|
|
26943
|
+
let lastError = null;
|
|
26944
|
+
const maxRetries = Math.max(0, Math.floor(retries));
|
|
26945
|
+
const attempts = maxRetries + 1;
|
|
26946
|
+
for (let attempt = 1; attempt <= attempts; attempt += 1) {
|
|
26947
|
+
try {
|
|
26948
|
+
return await fn();
|
|
26949
|
+
} catch (error) {
|
|
26950
|
+
lastError = error;
|
|
26951
|
+
const retryIndex = attempt;
|
|
26952
|
+
if (retryIndex > maxRetries || !shouldRetry(error)) {
|
|
26953
|
+
throw error;
|
|
26954
|
+
}
|
|
26955
|
+
status.stage(`${title} (retry ${retryIndex}/${maxRetries})`);
|
|
26956
|
+
logger7.warn("init_step_retry", {
|
|
26957
|
+
title,
|
|
26958
|
+
retry: retryIndex,
|
|
26959
|
+
retries: maxRetries,
|
|
26960
|
+
errorName: error instanceof Error ? error.name : void 0,
|
|
26961
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
26962
|
+
errorCode: getErrorCode2(error),
|
|
26963
|
+
...error instanceof SpritesApiError ? { status: error.status } : {},
|
|
26964
|
+
...parseExecUnexpectedResponseStatus(error) !== null ? { execStatus: parseExecUnexpectedResponseStatus(error) } : {}
|
|
26965
|
+
});
|
|
26966
|
+
await delay2(computeRetryDelayMs2(retryIndex));
|
|
26967
|
+
}
|
|
26968
|
+
}
|
|
26969
|
+
throw lastError instanceof Error ? lastError : new Error(`Init step failed: ${title}`);
|
|
26970
|
+
};
|
|
26794
26971
|
migrateLegacyRepoDevboxDir = async ({
|
|
26795
26972
|
repoRoot,
|
|
26796
26973
|
projectDir
|
|
@@ -26965,15 +27142,27 @@ var init_init = __esm({
|
|
|
26965
27142
|
client,
|
|
26966
27143
|
canonical,
|
|
26967
27144
|
workdir,
|
|
26968
|
-
status
|
|
26969
|
-
json
|
|
27145
|
+
status
|
|
26970
27146
|
}) => {
|
|
26971
27147
|
const checkResult = await client.exec(canonical, [
|
|
26972
27148
|
"/bin/bash",
|
|
26973
27149
|
"-lc",
|
|
26974
|
-
|
|
27150
|
+
[
|
|
27151
|
+
"set -euo pipefail",
|
|
27152
|
+
`dir=${shellQuote3(workdir)}`,
|
|
27153
|
+
'if [ ! -d "$dir" ]; then',
|
|
27154
|
+
' echo "Missing workdir: $dir" >&2',
|
|
27155
|
+
" exit 1",
|
|
27156
|
+
"fi",
|
|
27157
|
+
'stat -c %U "$dir"'
|
|
27158
|
+
].join("\n")
|
|
26975
27159
|
]);
|
|
26976
|
-
if (checkResult.exitCode !== 0)
|
|
27160
|
+
if (checkResult.exitCode !== 0) {
|
|
27161
|
+
const details = checkResult.stderr || checkResult.stdout || "";
|
|
27162
|
+
throw new Error(
|
|
27163
|
+
details ? `Failed to check workdir ownership: ${details.trim()}` : `Failed to check workdir ownership (exit ${checkResult.exitCode})`
|
|
27164
|
+
);
|
|
27165
|
+
}
|
|
26977
27166
|
const owner = checkResult.stdout.trim();
|
|
26978
27167
|
if (!owner || owner === "sprite") return;
|
|
26979
27168
|
status.stage("Fixing workdir ownership");
|
|
@@ -26983,17 +27172,10 @@ var init_init = __esm({
|
|
|
26983
27172
|
`sudo -n chown -R sprite:sprite ${shellQuote3(workdir)}`
|
|
26984
27173
|
]);
|
|
26985
27174
|
if (chownResult.exitCode !== 0) {
|
|
26986
|
-
|
|
26987
|
-
|
|
26988
|
-
workdir
|
|
26989
|
-
|
|
26990
|
-
});
|
|
26991
|
-
if (!json) {
|
|
26992
|
-
status.stop();
|
|
26993
|
-
console.warn(
|
|
26994
|
-
"Warning: failed to update workdir ownership. Git may refuse to operate until ownership is fixed."
|
|
26995
|
-
);
|
|
26996
|
-
}
|
|
27175
|
+
const details = chownResult.stderr || chownResult.stdout || "";
|
|
27176
|
+
throw new Error(
|
|
27177
|
+
details ? `Failed to update workdir ownership: ${details.trim()}` : `Failed to update workdir ownership (exit ${chownResult.exitCode})`
|
|
27178
|
+
);
|
|
26997
27179
|
}
|
|
26998
27180
|
};
|
|
26999
27181
|
ensureGitSafeDirectory = async ({
|
|
@@ -27357,7 +27539,7 @@ var init_init = __esm({
|
|
|
27357
27539
|
fingerprint,
|
|
27358
27540
|
phase: label
|
|
27359
27541
|
});
|
|
27360
|
-
|
|
27542
|
+
throw new Error("Checkpoint ID missing.");
|
|
27361
27543
|
}
|
|
27362
27544
|
const record = { id, comment, createdAt };
|
|
27363
27545
|
if (initState) {
|
|
@@ -27536,13 +27718,17 @@ var init_init = __esm({
|
|
|
27536
27718
|
});
|
|
27537
27719
|
await runInitStep({
|
|
27538
27720
|
enabled: progressEnabled,
|
|
27539
|
-
title: "Snapshotting filesystem (pre-setup)
|
|
27540
|
-
fn: async ({ fail, ok }) => {
|
|
27721
|
+
title: "Snapshotting filesystem (pre-setup)",
|
|
27722
|
+
fn: async ({ status, fail, ok }) => {
|
|
27541
27723
|
try {
|
|
27542
|
-
const checkpoint = await
|
|
27543
|
-
|
|
27544
|
-
|
|
27545
|
-
|
|
27724
|
+
const checkpoint = await retryInitStep({
|
|
27725
|
+
status,
|
|
27726
|
+
title: "Snapshotting filesystem (pre-setup)",
|
|
27727
|
+
fn: async () => await recordCodexCheckpoint({
|
|
27728
|
+
client: client2,
|
|
27729
|
+
canonical: canonical2,
|
|
27730
|
+
phase: "preCodexSetup"
|
|
27731
|
+
})
|
|
27546
27732
|
});
|
|
27547
27733
|
if (checkpoint.id) {
|
|
27548
27734
|
ok(`Snapshot created: ${checkpoint.id}`);
|
|
@@ -27554,12 +27740,8 @@ var init_init = __esm({
|
|
|
27554
27740
|
phase: "pre-codex-setup",
|
|
27555
27741
|
error: error instanceof Error ? error.message : String(error)
|
|
27556
27742
|
});
|
|
27557
|
-
fail("Snapshotting filesystem (pre-setup) (
|
|
27558
|
-
|
|
27559
|
-
console.warn(
|
|
27560
|
-
"Warning: failed to create pre-setup filesystem snapshot. Continuing without it."
|
|
27561
|
-
);
|
|
27562
|
-
}
|
|
27743
|
+
fail("Snapshotting filesystem (pre-setup) (failed)");
|
|
27744
|
+
throw error;
|
|
27563
27745
|
}
|
|
27564
27746
|
}
|
|
27565
27747
|
});
|
|
@@ -27595,13 +27777,17 @@ var init_init = __esm({
|
|
|
27595
27777
|
});
|
|
27596
27778
|
await runInitStep({
|
|
27597
27779
|
enabled: progressEnabled,
|
|
27598
|
-
title: "Snapshotting filesystem (post-setup)
|
|
27599
|
-
fn: async ({ fail, ok }) => {
|
|
27780
|
+
title: "Snapshotting filesystem (post-setup)",
|
|
27781
|
+
fn: async ({ status, fail, ok }) => {
|
|
27600
27782
|
try {
|
|
27601
|
-
const checkpoint = await
|
|
27602
|
-
|
|
27603
|
-
|
|
27604
|
-
|
|
27783
|
+
const checkpoint = await retryInitStep({
|
|
27784
|
+
status,
|
|
27785
|
+
title: "Snapshotting filesystem (post-setup)",
|
|
27786
|
+
fn: async () => await recordCodexCheckpoint({
|
|
27787
|
+
client: client2,
|
|
27788
|
+
canonical: canonical2,
|
|
27789
|
+
phase: "postCodexSetup"
|
|
27790
|
+
})
|
|
27605
27791
|
});
|
|
27606
27792
|
if (checkpoint.id) {
|
|
27607
27793
|
ok(`Snapshot created: ${checkpoint.id}`);
|
|
@@ -27613,12 +27799,8 @@ var init_init = __esm({
|
|
|
27613
27799
|
phase: "post-codex-setup",
|
|
27614
27800
|
error: error instanceof Error ? error.message : String(error)
|
|
27615
27801
|
});
|
|
27616
|
-
fail("Snapshotting filesystem (post-setup) (
|
|
27617
|
-
|
|
27618
|
-
console.warn(
|
|
27619
|
-
"Warning: failed to create post-setup filesystem snapshot. Continuing without it."
|
|
27620
|
-
);
|
|
27621
|
-
}
|
|
27802
|
+
fail("Snapshotting filesystem (post-setup) (failed)");
|
|
27803
|
+
throw error;
|
|
27622
27804
|
}
|
|
27623
27805
|
}
|
|
27624
27806
|
});
|
|
@@ -27784,40 +27966,33 @@ var init_init = __esm({
|
|
|
27784
27966
|
localPaths: projectLocalPaths
|
|
27785
27967
|
});
|
|
27786
27968
|
const updateRegistryProjectStatus = async (initStatus) => {
|
|
27787
|
-
|
|
27788
|
-
|
|
27789
|
-
|
|
27790
|
-
|
|
27791
|
-
|
|
27792
|
-
|
|
27793
|
-
|
|
27794
|
-
|
|
27795
|
-
|
|
27796
|
-
);
|
|
27797
|
-
} catch (error) {
|
|
27798
|
-
logger7.warn("registry_project_update_failed", {
|
|
27799
|
-
box: canonical,
|
|
27800
|
-
status: initStatus,
|
|
27801
|
-
error: String(error)
|
|
27802
|
-
});
|
|
27803
|
-
}
|
|
27969
|
+
await requestJson3(
|
|
27970
|
+
socketInfo.socketPath,
|
|
27971
|
+
"POST",
|
|
27972
|
+
"/registry/upsert",
|
|
27973
|
+
DAEMON_TIMEOUT_MS.registry,
|
|
27974
|
+
{
|
|
27975
|
+
project: buildProjectEntry(initStatus)
|
|
27976
|
+
}
|
|
27977
|
+
);
|
|
27804
27978
|
};
|
|
27805
27979
|
await runInitStep({
|
|
27806
27980
|
enabled: progressEnabled,
|
|
27807
27981
|
title: "Bootstrapping devbox",
|
|
27808
|
-
fn: async ({ fail }) => {
|
|
27982
|
+
fn: async ({ status, fail }) => {
|
|
27809
27983
|
try {
|
|
27810
|
-
await
|
|
27984
|
+
await retryInitStep({
|
|
27985
|
+
status,
|
|
27986
|
+
title: "Bootstrapping devbox",
|
|
27987
|
+
fn: async () => await bootstrapDevbox(client, canonical)
|
|
27988
|
+
});
|
|
27811
27989
|
} catch (error) {
|
|
27812
27990
|
logger7.warn("devbox_bootstrap_failed", {
|
|
27813
27991
|
box: canonical,
|
|
27814
27992
|
error: String(error)
|
|
27815
27993
|
});
|
|
27816
27994
|
fail("Bootstrapping devbox (failed)");
|
|
27817
|
-
|
|
27818
|
-
const message = error instanceof Error && error.message ? error.message : String(error);
|
|
27819
|
-
console.warn(`Warning: devbox bootstrap failed. ${message}`);
|
|
27820
|
-
}
|
|
27995
|
+
throw error;
|
|
27821
27996
|
}
|
|
27822
27997
|
}
|
|
27823
27998
|
});
|
|
@@ -27858,7 +28033,7 @@ var init_init = __esm({
|
|
|
27858
28033
|
await runInitStep({
|
|
27859
28034
|
enabled: progressEnabled,
|
|
27860
28035
|
title: "Installing sprite daemon",
|
|
27861
|
-
fn: async ({ fail }) => {
|
|
28036
|
+
fn: async ({ status, fail }) => {
|
|
27862
28037
|
try {
|
|
27863
28038
|
const convexUrl = getConvexUrl();
|
|
27864
28039
|
if (!controlPlaneToken) {
|
|
@@ -27880,12 +28055,16 @@ var init_init = __esm({
|
|
|
27880
28055
|
if (!heartbeatToken) {
|
|
27881
28056
|
throw new Error("Daemon token unavailable.");
|
|
27882
28057
|
}
|
|
27883
|
-
await
|
|
27884
|
-
|
|
27885
|
-
|
|
27886
|
-
|
|
27887
|
-
|
|
27888
|
-
|
|
28058
|
+
await retryInitStep({
|
|
28059
|
+
status,
|
|
28060
|
+
title: "Installing sprite daemon",
|
|
28061
|
+
fn: async () => await installSpriteDaemon({
|
|
28062
|
+
client,
|
|
28063
|
+
spriteName: canonical,
|
|
28064
|
+
release,
|
|
28065
|
+
convexUrl,
|
|
28066
|
+
heartbeatToken
|
|
28067
|
+
})
|
|
27889
28068
|
});
|
|
27890
28069
|
await updateInitState({ steps: { daemonInstalled: true } });
|
|
27891
28070
|
} catch (error) {
|
|
@@ -27894,12 +28073,7 @@ var init_init = __esm({
|
|
|
27894
28073
|
error: String(error)
|
|
27895
28074
|
});
|
|
27896
28075
|
fail("Installing sprite daemon (failed)");
|
|
27897
|
-
|
|
27898
|
-
const message = error instanceof Error && error.message ? error.message : String(error);
|
|
27899
|
-
console.warn(
|
|
27900
|
-
`Warning: failed to install sprite daemon. ${message}`
|
|
27901
|
-
);
|
|
27902
|
-
}
|
|
28076
|
+
throw error;
|
|
27903
28077
|
}
|
|
27904
28078
|
}
|
|
27905
28079
|
});
|
|
@@ -27907,9 +28081,13 @@ var init_init = __esm({
|
|
|
27907
28081
|
await runInitStep({
|
|
27908
28082
|
enabled: progressEnabled,
|
|
27909
28083
|
title: "Ensuring sprite daemon service",
|
|
27910
|
-
fn: async ({ fail }) => {
|
|
28084
|
+
fn: async ({ status, fail }) => {
|
|
27911
28085
|
try {
|
|
27912
|
-
await
|
|
28086
|
+
await retryInitStep({
|
|
28087
|
+
status,
|
|
28088
|
+
title: "Ensuring sprite daemon service",
|
|
28089
|
+
fn: async () => await ensureSpriteDaemonService({ client, spriteName: canonical })
|
|
28090
|
+
});
|
|
27913
28091
|
await updateInitState({ steps: { daemonServiceEnsured: true } });
|
|
27914
28092
|
} catch (error) {
|
|
27915
28093
|
logger7.warn("sprite_daemon_service_failed", {
|
|
@@ -27917,12 +28095,7 @@ var init_init = __esm({
|
|
|
27917
28095
|
error: String(error)
|
|
27918
28096
|
});
|
|
27919
28097
|
fail("Ensuring sprite daemon service (failed)");
|
|
27920
|
-
|
|
27921
|
-
const message = error instanceof Error && error.message ? error.message : String(error);
|
|
27922
|
-
console.warn(
|
|
27923
|
-
`Warning: failed to ensure sprite daemon service. ${message}`
|
|
27924
|
-
);
|
|
27925
|
-
}
|
|
28098
|
+
throw error;
|
|
27926
28099
|
}
|
|
27927
28100
|
}
|
|
27928
28101
|
});
|
|
@@ -28792,12 +28965,15 @@ var init_init = __esm({
|
|
|
28792
28965
|
enabled: progressEnabled,
|
|
28793
28966
|
title: "Ensuring workdir ownership",
|
|
28794
28967
|
fn: async ({ status }) => {
|
|
28795
|
-
await
|
|
28796
|
-
client,
|
|
28797
|
-
canonical,
|
|
28798
|
-
workdir: expandedWorkdir,
|
|
28968
|
+
await retryInitStep({
|
|
28799
28969
|
status,
|
|
28800
|
-
|
|
28970
|
+
title: "Ensuring workdir ownership",
|
|
28971
|
+
fn: async () => await ensureWorkdirOwnership({
|
|
28972
|
+
client,
|
|
28973
|
+
canonical,
|
|
28974
|
+
workdir: expandedWorkdir,
|
|
28975
|
+
status
|
|
28976
|
+
})
|
|
28801
28977
|
});
|
|
28802
28978
|
}
|
|
28803
28979
|
});
|
|
@@ -28822,13 +28998,19 @@ var init_init = __esm({
|
|
|
28822
28998
|
await runInitStep({
|
|
28823
28999
|
enabled: progressEnabled,
|
|
28824
29000
|
title: "Configuring SSH mount access",
|
|
28825
|
-
fn: async ({ fail }) => {
|
|
29001
|
+
fn: async ({ status, fail }) => {
|
|
28826
29002
|
try {
|
|
28827
|
-
await
|
|
28828
|
-
|
|
28829
|
-
|
|
28830
|
-
|
|
28831
|
-
|
|
29003
|
+
await retryInitStep({
|
|
29004
|
+
status,
|
|
29005
|
+
title: "Configuring SSH mount access",
|
|
29006
|
+
fn: async () => {
|
|
29007
|
+
await ensureLocalMountKey();
|
|
29008
|
+
await ensureKnownHostsFile();
|
|
29009
|
+
const publicKey = await readLocalMountPublicKey();
|
|
29010
|
+
await ensureRemoteMountAccess(client, canonical, publicKey);
|
|
29011
|
+
await ensureSshdService(client, canonical);
|
|
29012
|
+
}
|
|
29013
|
+
});
|
|
28832
29014
|
await updateInitState({ steps: { sshdConfigured: true } });
|
|
28833
29015
|
} catch (error) {
|
|
28834
29016
|
logger7.warn("sshd_config_failed", {
|
|
@@ -28836,13 +29018,7 @@ var init_init = __esm({
|
|
|
28836
29018
|
error: String(error)
|
|
28837
29019
|
});
|
|
28838
29020
|
fail("Configuring SSH mount access (failed)");
|
|
28839
|
-
|
|
28840
|
-
const message = error instanceof Error && error.message ? error.message : String(error);
|
|
28841
|
-
console.warn(
|
|
28842
|
-
`Warning: failed to configure SSH mount access. ${message}`
|
|
28843
|
-
);
|
|
28844
|
-
console.warn(`To retry later: dvb mount ${alias}`);
|
|
28845
|
-
}
|
|
29021
|
+
throw error;
|
|
28846
29022
|
}
|
|
28847
29023
|
}
|
|
28848
29024
|
});
|
|
@@ -29000,10 +29176,12 @@ var init_init = __esm({
|
|
|
29000
29176
|
}
|
|
29001
29177
|
const weztermMuxPresent = await runInitStep({
|
|
29002
29178
|
enabled: progressEnabled,
|
|
29003
|
-
title: "Ensuring WezTerm mux server
|
|
29004
|
-
fn: async ({
|
|
29005
|
-
|
|
29006
|
-
|
|
29179
|
+
title: "Ensuring WezTerm mux server",
|
|
29180
|
+
fn: async ({ status }) => {
|
|
29181
|
+
const installResult = await retryInitStep({
|
|
29182
|
+
status,
|
|
29183
|
+
title: "Ensuring WezTerm mux server",
|
|
29184
|
+
fn: async () => !shouldResume || !initState?.steps.weztermMuxInstalled ? await ensureWeztermMuxInstalled({
|
|
29007
29185
|
client,
|
|
29008
29186
|
spriteName: canonical,
|
|
29009
29187
|
allowResolveAsset: true
|
|
@@ -29012,49 +29190,29 @@ var init_init = __esm({
|
|
|
29012
29190
|
spriteName: canonical,
|
|
29013
29191
|
// If the mux is missing on resume, we still need to resolve a GitHub asset.
|
|
29014
29192
|
allowResolveAsset: true
|
|
29015
|
-
})
|
|
29016
|
-
|
|
29017
|
-
|
|
29018
|
-
}
|
|
29019
|
-
return
|
|
29020
|
-
} catch (error) {
|
|
29021
|
-
logger7.warn("wezterm_mux_install_failed", {
|
|
29022
|
-
box: canonical,
|
|
29023
|
-
error: error instanceof Error ? error.message : String(error)
|
|
29024
|
-
});
|
|
29025
|
-
fail("Ensuring WezTerm mux server (optional) (failed)");
|
|
29026
|
-
if (!parsed.json) {
|
|
29027
|
-
const message = error instanceof Error && error.message ? error.message : String(error);
|
|
29028
|
-
console.warn(
|
|
29029
|
-
`Warning: failed to install WezTerm mux server (optional). ${message}
|
|
29030
|
-
Tip: re-run with DEVBOX_LOG_LEVEL=info to see Sprite exec logs on stderr.`
|
|
29031
|
-
);
|
|
29032
|
-
}
|
|
29033
|
-
return false;
|
|
29193
|
+
})
|
|
29194
|
+
});
|
|
29195
|
+
if (installResult.muxPresent) {
|
|
29196
|
+
await updateInitState({ steps: { weztermMuxInstalled: true } });
|
|
29197
|
+
return true;
|
|
29034
29198
|
}
|
|
29199
|
+
throw new Error("WezTerm mux server unavailable.");
|
|
29035
29200
|
}
|
|
29036
29201
|
});
|
|
29037
|
-
if (
|
|
29202
|
+
if (!shouldResume || !initState?.steps.weztermMuxServiceEnsured) {
|
|
29038
29203
|
await runInitStep({
|
|
29039
29204
|
enabled: progressEnabled,
|
|
29040
|
-
title: "Ensuring WezTerm mux service
|
|
29041
|
-
fn: async ({
|
|
29042
|
-
|
|
29043
|
-
|
|
29044
|
-
await updateInitState({ steps: { weztermMuxServiceEnsured: true } });
|
|
29045
|
-
} catch (error) {
|
|
29046
|
-
logger7.warn("wezterm_mux_service_failed", {
|
|
29047
|
-
box: canonical,
|
|
29048
|
-
error: error instanceof Error ? error.message : String(error)
|
|
29049
|
-
});
|
|
29050
|
-
fail("Ensuring WezTerm mux service (optional) (failed)");
|
|
29051
|
-
if (!parsed.json) {
|
|
29052
|
-
const message = error instanceof Error && error.message ? error.message : String(error);
|
|
29053
|
-
console.warn(
|
|
29054
|
-
`Warning: failed to ensure WezTerm mux service (optional). ${message}`
|
|
29055
|
-
);
|
|
29056
|
-
}
|
|
29205
|
+
title: "Ensuring WezTerm mux service",
|
|
29206
|
+
fn: async ({ status }) => {
|
|
29207
|
+
if (!weztermMuxPresent) {
|
|
29208
|
+
throw new Error("WezTerm mux server unavailable.");
|
|
29057
29209
|
}
|
|
29210
|
+
await retryInitStep({
|
|
29211
|
+
status,
|
|
29212
|
+
title: "Ensuring WezTerm mux service",
|
|
29213
|
+
fn: async () => await ensureWeztermMuxService({ client, spriteName: canonical })
|
|
29214
|
+
});
|
|
29215
|
+
await updateInitState({ steps: { weztermMuxServiceEnsured: true } });
|
|
29058
29216
|
}
|
|
29059
29217
|
});
|
|
29060
29218
|
}
|
|
@@ -29121,21 +29279,13 @@ Tip: re-run with DEVBOX_LOG_LEVEL=info to see Sprite exec logs on stderr.`
|
|
|
29121
29279
|
});
|
|
29122
29280
|
await runInitStep({
|
|
29123
29281
|
enabled: progressEnabled,
|
|
29124
|
-
title: "Updating Codex config on sprite
|
|
29125
|
-
fn: async ({
|
|
29126
|
-
|
|
29127
|
-
|
|
29128
|
-
|
|
29129
|
-
|
|
29130
|
-
|
|
29131
|
-
});
|
|
29132
|
-
fail("Updating Codex config on sprite (optional) (failed)");
|
|
29133
|
-
if (!parsed.json) {
|
|
29134
|
-
console.warn(
|
|
29135
|
-
"Warning: failed to update /home/sprite/.codex/config.toml for full-access sandbox settings."
|
|
29136
|
-
);
|
|
29137
|
-
}
|
|
29138
|
-
}
|
|
29282
|
+
title: "Updating Codex config on sprite",
|
|
29283
|
+
fn: async ({ status }) => {
|
|
29284
|
+
await retryInitStep({
|
|
29285
|
+
status,
|
|
29286
|
+
title: "Updating Codex config on sprite",
|
|
29287
|
+
fn: async () => await writeRemoteCodexConfig(client, canonical, repoName)
|
|
29288
|
+
});
|
|
29139
29289
|
}
|
|
29140
29290
|
});
|
|
29141
29291
|
const skipSetupArtifactsStage = skipCodexApply || shouldResume && initState?.steps.setupArtifactsStaged;
|
|
@@ -29159,13 +29309,17 @@ Tip: re-run with DEVBOX_LOG_LEVEL=info to see Sprite exec logs on stderr.`
|
|
|
29159
29309
|
if (!skipCodexApply) {
|
|
29160
29310
|
await runInitStep({
|
|
29161
29311
|
enabled: progressEnabled,
|
|
29162
|
-
title: "Snapshotting filesystem (pre-setup)
|
|
29163
|
-
fn: async ({ fail, ok }) => {
|
|
29312
|
+
title: "Snapshotting filesystem (pre-setup)",
|
|
29313
|
+
fn: async ({ status, fail, ok }) => {
|
|
29164
29314
|
try {
|
|
29165
|
-
const checkpoint = await
|
|
29166
|
-
|
|
29167
|
-
|
|
29168
|
-
|
|
29315
|
+
const checkpoint = await retryInitStep({
|
|
29316
|
+
status,
|
|
29317
|
+
title: "Snapshotting filesystem (pre-setup)",
|
|
29318
|
+
fn: async () => await recordCodexCheckpoint({
|
|
29319
|
+
client,
|
|
29320
|
+
canonical,
|
|
29321
|
+
phase: "preCodexSetup"
|
|
29322
|
+
})
|
|
29169
29323
|
});
|
|
29170
29324
|
if (checkpoint.id) {
|
|
29171
29325
|
ok(`Snapshot created: ${checkpoint.id}`);
|
|
@@ -29177,12 +29331,8 @@ Tip: re-run with DEVBOX_LOG_LEVEL=info to see Sprite exec logs on stderr.`
|
|
|
29177
29331
|
phase: "pre-codex-setup",
|
|
29178
29332
|
error: error instanceof Error ? error.message : String(error)
|
|
29179
29333
|
});
|
|
29180
|
-
fail("Snapshotting filesystem (pre-setup) (
|
|
29181
|
-
|
|
29182
|
-
console.warn(
|
|
29183
|
-
"Warning: failed to create pre-setup filesystem snapshot. Continuing without it."
|
|
29184
|
-
);
|
|
29185
|
-
}
|
|
29334
|
+
fail("Snapshotting filesystem (pre-setup) (failed)");
|
|
29335
|
+
throw error;
|
|
29186
29336
|
}
|
|
29187
29337
|
}
|
|
29188
29338
|
});
|
|
@@ -29225,13 +29375,17 @@ Tip: re-run with DEVBOX_LOG_LEVEL=info to see Sprite exec logs on stderr.`
|
|
|
29225
29375
|
);
|
|
29226
29376
|
await runInitStep({
|
|
29227
29377
|
enabled: progressEnabled,
|
|
29228
|
-
title: "Snapshotting filesystem (post-setup)
|
|
29229
|
-
fn: async ({ fail, ok }) => {
|
|
29378
|
+
title: "Snapshotting filesystem (post-setup)",
|
|
29379
|
+
fn: async ({ status, fail, ok }) => {
|
|
29230
29380
|
try {
|
|
29231
|
-
const checkpoint = await
|
|
29232
|
-
|
|
29233
|
-
|
|
29234
|
-
|
|
29381
|
+
const checkpoint = await retryInitStep({
|
|
29382
|
+
status,
|
|
29383
|
+
title: "Snapshotting filesystem (post-setup)",
|
|
29384
|
+
fn: async () => await recordCodexCheckpoint({
|
|
29385
|
+
client,
|
|
29386
|
+
canonical,
|
|
29387
|
+
phase: "postCodexSetup"
|
|
29388
|
+
})
|
|
29235
29389
|
});
|
|
29236
29390
|
if (checkpoint.id) {
|
|
29237
29391
|
ok(`Snapshot created: ${checkpoint.id}`);
|
|
@@ -29243,12 +29397,8 @@ Tip: re-run with DEVBOX_LOG_LEVEL=info to see Sprite exec logs on stderr.`
|
|
|
29243
29397
|
phase: "post-codex-setup",
|
|
29244
29398
|
error: error instanceof Error ? error.message : String(error)
|
|
29245
29399
|
});
|
|
29246
|
-
fail("Snapshotting filesystem (post-setup) (
|
|
29247
|
-
|
|
29248
|
-
console.warn(
|
|
29249
|
-
"Warning: failed to create post-setup filesystem snapshot. Continuing without it."
|
|
29250
|
-
);
|
|
29251
|
-
}
|
|
29400
|
+
fail("Snapshotting filesystem (post-setup) (failed)");
|
|
29401
|
+
throw error;
|
|
29252
29402
|
}
|
|
29253
29403
|
}
|
|
29254
29404
|
});
|
|
@@ -32254,7 +32404,7 @@ var init_cli = __esm({
|
|
|
32254
32404
|
});
|
|
32255
32405
|
|
|
32256
32406
|
// src/bin/dvb.ts
|
|
32257
|
-
var
|
|
32407
|
+
var import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
32258
32408
|
var import_node_os11 = __toESM(require("node:os"), 1);
|
|
32259
32409
|
var import_node_path26 = __toESM(require("node:path"), 1);
|
|
32260
32410
|
init_src();
|
|
@@ -32312,8 +32462,8 @@ run().catch((error) => {
|
|
|
32312
32462
|
if (homeDir) {
|
|
32313
32463
|
try {
|
|
32314
32464
|
const logDir = import_node_path26.default.join(resolveDevboxDir(homeDir), "wezterm");
|
|
32315
|
-
|
|
32316
|
-
|
|
32465
|
+
import_node_fs8.default.mkdirSync(logDir, { recursive: true });
|
|
32466
|
+
import_node_fs8.default.appendFileSync(
|
|
32317
32467
|
import_node_path26.default.join(logDir, "proxy.log"),
|
|
32318
32468
|
`${(/* @__PURE__ */ new Date()).toISOString()} ${message}
|
|
32319
32469
|
`
|