@boxes-dev/dvb 0.2.45 → 0.2.46
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
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, BOOTSTRAP_EXEC_RETRY_DELAY_MS, logger8, truncateTail, shellQuote3, expandHome2, execWithLog, isExecTimeoutError,
|
|
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, BOOTSTRAP_EXEC_RETRY_DELAY_MS, logger8, truncateTail, shellQuote3, expandHome2, execWithLog, isExecTimeoutError, delay2, 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";
|
|
@@ -22407,7 +22511,7 @@ var init_remote = __esm({
|
|
|
22407
22511
|
return result;
|
|
22408
22512
|
};
|
|
22409
22513
|
isExecTimeoutError = (error) => error instanceof Error && typeof error.message === "string" && error.message.startsWith("Exec websocket timed out after ");
|
|
22410
|
-
|
|
22514
|
+
delay2 = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
22411
22515
|
writeRemoteFile = async (client, canonical, path26, content, stage) => {
|
|
22412
22516
|
const requestId = (0, import_node_crypto10.randomUUID)();
|
|
22413
22517
|
logger8.info("sprites_request", {
|
|
@@ -22452,7 +22556,7 @@ var init_remote = __esm({
|
|
|
22452
22556
|
timeoutMs: BOOTSTRAP_EXEC_TIMEOUT_MS,
|
|
22453
22557
|
delayMs: BOOTSTRAP_EXEC_RETRY_DELAY_MS
|
|
22454
22558
|
});
|
|
22455
|
-
await
|
|
22559
|
+
await delay2(BOOTSTRAP_EXEC_RETRY_DELAY_MS);
|
|
22456
22560
|
return await execWithLog(
|
|
22457
22561
|
client,
|
|
22458
22562
|
canonical,
|
|
@@ -23943,17 +24047,26 @@ var init_template = __esm({
|
|
|
23943
24047
|
});
|
|
23944
24048
|
|
|
23945
24049
|
// src/devbox/commands/init/codex/prompts.ts
|
|
23946
|
-
var import_promises23, import_node_path17, resolvePromptsDir, readPromptTemplate, loadPrompt, loadLocalEnvSecretsScanPrompt, loadLocalExternalScanPrompt, loadLocalExtraArtifactsScanPrompt, loadLocalServicesScanPrompt;
|
|
24050
|
+
var import_node_fs5, import_promises23, import_node_path17, resolvePromptsDir, readPromptTemplate, loadPrompt, loadLocalEnvSecretsScanPrompt, loadLocalExternalScanPrompt, loadLocalExtraArtifactsScanPrompt, loadLocalServicesScanPrompt;
|
|
23947
24051
|
var init_prompts = __esm({
|
|
23948
24052
|
"src/devbox/commands/init/codex/prompts.ts"() {
|
|
23949
24053
|
"use strict";
|
|
24054
|
+
import_node_fs5 = __toESM(require("node:fs"), 1);
|
|
23950
24055
|
import_promises23 = __toESM(require("node:fs/promises"), 1);
|
|
23951
24056
|
import_node_path17 = __toESM(require("node:path"), 1);
|
|
23952
24057
|
init_template();
|
|
23953
24058
|
resolvePromptsDir = () => {
|
|
23954
|
-
const
|
|
23955
|
-
if (
|
|
23956
|
-
|
|
24059
|
+
const argv1 = typeof process.argv[1] === "string" ? process.argv[1] : "";
|
|
24060
|
+
if (argv1) {
|
|
24061
|
+
try {
|
|
24062
|
+
const real = import_node_fs5.default.realpathSync(argv1);
|
|
24063
|
+
return import_node_path17.default.resolve(import_node_path17.default.dirname(real), "..", "prompts");
|
|
24064
|
+
} catch {
|
|
24065
|
+
}
|
|
24066
|
+
try {
|
|
24067
|
+
return import_node_path17.default.resolve(import_node_path17.default.dirname(argv1), "..", "prompts");
|
|
24068
|
+
} catch {
|
|
24069
|
+
}
|
|
23957
24070
|
}
|
|
23958
24071
|
return import_node_path17.default.resolve(process.cwd(), "prompts");
|
|
23959
24072
|
};
|
|
@@ -24475,18 +24588,18 @@ fi`
|
|
|
24475
24588
|
});
|
|
24476
24589
|
|
|
24477
24590
|
// src/devbox/commands/init/codex/plan.ts
|
|
24478
|
-
var import_node_path18,
|
|
24591
|
+
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
24592
|
var init_plan = __esm({
|
|
24480
24593
|
"src/devbox/commands/init/codex/plan.ts"() {
|
|
24481
24594
|
"use strict";
|
|
24482
24595
|
import_node_path18 = __toESM(require("node:path"), 1);
|
|
24483
|
-
|
|
24596
|
+
import_node_fs6 = __toESM(require("node:fs"), 1);
|
|
24484
24597
|
import_promises24 = __toESM(require("node:fs/promises"), 1);
|
|
24485
24598
|
resolveSchemaPath = (fileName) => {
|
|
24486
24599
|
const argv1 = typeof process.argv[1] === "string" ? process.argv[1] : "";
|
|
24487
24600
|
if (argv1) {
|
|
24488
24601
|
try {
|
|
24489
|
-
const real =
|
|
24602
|
+
const real = import_node_fs6.default.realpathSync(argv1);
|
|
24490
24603
|
return import_node_path18.default.resolve(import_node_path18.default.dirname(real), "..", "codex", fileName);
|
|
24491
24604
|
} catch {
|
|
24492
24605
|
}
|
|
@@ -24783,12 +24896,12 @@ ${bottom}
|
|
|
24783
24896
|
});
|
|
24784
24897
|
|
|
24785
24898
|
// src/devbox/commands/init/codex/local.ts
|
|
24786
|
-
var import_node_child_process9,
|
|
24899
|
+
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
24900
|
var init_local = __esm({
|
|
24788
24901
|
"src/devbox/commands/init/codex/local.ts"() {
|
|
24789
24902
|
"use strict";
|
|
24790
24903
|
import_node_child_process9 = require("node:child_process");
|
|
24791
|
-
|
|
24904
|
+
import_node_fs7 = require("node:fs");
|
|
24792
24905
|
import_promises25 = __toESM(require("node:fs/promises"), 1);
|
|
24793
24906
|
import_node_path19 = __toESM(require("node:path"), 1);
|
|
24794
24907
|
init_dist2();
|
|
@@ -24807,11 +24920,11 @@ var init_local = __esm({
|
|
|
24807
24920
|
try {
|
|
24808
24921
|
if (stdoutLogPath) {
|
|
24809
24922
|
await import_promises25.default.mkdir(import_node_path19.default.dirname(stdoutLogPath), { recursive: true });
|
|
24810
|
-
stdoutStream = (0,
|
|
24923
|
+
stdoutStream = (0, import_node_fs7.createWriteStream)(stdoutLogPath, { flags: "a" });
|
|
24811
24924
|
}
|
|
24812
24925
|
if (stderrLogPath) {
|
|
24813
24926
|
await import_promises25.default.mkdir(import_node_path19.default.dirname(stderrLogPath), { recursive: true });
|
|
24814
|
-
stderrStream = (0,
|
|
24927
|
+
stderrStream = (0, import_node_fs7.createWriteStream)(stderrLogPath, { flags: "a" });
|
|
24815
24928
|
}
|
|
24816
24929
|
} catch {
|
|
24817
24930
|
stdoutStream = null;
|
|
@@ -32254,7 +32367,7 @@ var init_cli = __esm({
|
|
|
32254
32367
|
});
|
|
32255
32368
|
|
|
32256
32369
|
// src/bin/dvb.ts
|
|
32257
|
-
var
|
|
32370
|
+
var import_node_fs8 = __toESM(require("node:fs"), 1);
|
|
32258
32371
|
var import_node_os11 = __toESM(require("node:os"), 1);
|
|
32259
32372
|
var import_node_path26 = __toESM(require("node:path"), 1);
|
|
32260
32373
|
init_src();
|
|
@@ -32312,8 +32425,8 @@ run().catch((error) => {
|
|
|
32312
32425
|
if (homeDir) {
|
|
32313
32426
|
try {
|
|
32314
32427
|
const logDir = import_node_path26.default.join(resolveDevboxDir(homeDir), "wezterm");
|
|
32315
|
-
|
|
32316
|
-
|
|
32428
|
+
import_node_fs8.default.mkdirSync(logDir, { recursive: true });
|
|
32429
|
+
import_node_fs8.default.appendFileSync(
|
|
32317
32430
|
import_node_path26.default.join(logDir, "proxy.log"),
|
|
32318
32431
|
`${(/* @__PURE__ */ new Date()).toISOString()} ${message}
|
|
32319
32432
|
`
|
package/dist/bin/dvbd.cjs
CHANGED
|
@@ -351,7 +351,7 @@ var init_repo = __esm({
|
|
|
351
351
|
});
|
|
352
352
|
|
|
353
353
|
// ../core/src/sprites.ts
|
|
354
|
-
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;
|
|
354
|
+
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;
|
|
355
355
|
var init_sprites = __esm({
|
|
356
356
|
"../core/src/sprites.ts"() {
|
|
357
357
|
"use strict";
|
|
@@ -419,39 +419,126 @@ var init_sprites = __esm({
|
|
|
419
419
|
return new URL(path6, `${protocol}//${base.host}`);
|
|
420
420
|
};
|
|
421
421
|
shellQuote = (value) => `'${value.replace(/'/g, `'\\''`)}'`;
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
422
|
+
DEFAULT_SPRITES_HTTP_TIMEOUT_MS_IDEMPOTENT = 5e3;
|
|
423
|
+
DEFAULT_SPRITES_HTTP_TIMEOUT_MS_NON_IDEMPOTENT = 2e4;
|
|
424
|
+
DEFAULT_SPRITES_HTTP_MAX_ATTEMPTS = 5;
|
|
425
|
+
SPRITES_HTTP_RETRYABLE_STATUSES = /* @__PURE__ */ new Set([408, 409, 425, 429, 500, 502, 503, 504]);
|
|
426
|
+
delay = async (ms) => new Promise((resolve) => setTimeout(resolve, ms));
|
|
427
|
+
isIdempotentMethod = (method) => {
|
|
428
|
+
const normalized = method.toUpperCase();
|
|
429
|
+
return normalized === "GET" || normalized === "HEAD" || normalized === "PUT" || normalized === "DELETE" || normalized === "OPTIONS";
|
|
430
|
+
};
|
|
431
|
+
computeRetryDelayMs = (attempt) => {
|
|
432
|
+
const base = 250;
|
|
433
|
+
const cap = 2500;
|
|
434
|
+
const exp = Math.min(cap, base * 2 ** Math.max(0, attempt - 1));
|
|
435
|
+
const jitter = Math.floor(Math.random() * 120);
|
|
436
|
+
return exp + jitter;
|
|
437
|
+
};
|
|
438
|
+
isAbortError = (error) => error instanceof Error && (error.name === "AbortError" || error.message.includes("aborted"));
|
|
439
|
+
getErrorCode = (error) => {
|
|
440
|
+
if (!error || typeof error !== "object") return void 0;
|
|
441
|
+
const record = error;
|
|
442
|
+
const code2 = record.code;
|
|
443
|
+
return typeof code2 === "string" || typeof code2 === "number" ? String(code2) : void 0;
|
|
444
|
+
};
|
|
445
|
+
isRetryableFetchError = (error) => {
|
|
446
|
+
if (isAbortError(error)) return true;
|
|
447
|
+
if (error instanceof TypeError) return true;
|
|
448
|
+
const code2 = getErrorCode(error);
|
|
449
|
+
return code2 === "ECONNRESET" || code2 === "ETIMEDOUT" || code2 === "EAI_AGAIN" || code2 === "ENOTFOUND" || code2 === "ECONNREFUSED";
|
|
450
|
+
};
|
|
451
|
+
shouldRetrySpritesRequest = (method, error) => {
|
|
452
|
+
if (!isIdempotentMethod(method)) return false;
|
|
453
|
+
if (error instanceof SpritesApiError) {
|
|
454
|
+
return SPRITES_HTTP_RETRYABLE_STATUSES.has(error.status);
|
|
431
455
|
}
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
456
|
+
return isRetryableFetchError(error);
|
|
457
|
+
};
|
|
458
|
+
withSpritesRetry = async (options) => {
|
|
459
|
+
const opId = (0, import_node_crypto.randomUUID)();
|
|
460
|
+
const timeoutMs = options.timeoutMs ?? (isIdempotentMethod(options.method) ? DEFAULT_SPRITES_HTTP_TIMEOUT_MS_IDEMPOTENT : DEFAULT_SPRITES_HTTP_TIMEOUT_MS_NON_IDEMPOTENT);
|
|
461
|
+
const maxAttemptsRaw = options.maxAttempts ?? DEFAULT_SPRITES_HTTP_MAX_ATTEMPTS;
|
|
462
|
+
const maxAttempts = isIdempotentMethod(options.method) ? Math.max(1, maxAttemptsRaw) : 1;
|
|
463
|
+
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
|
464
|
+
const requestId = (0, import_node_crypto.randomUUID)();
|
|
465
|
+
const controller = new AbortController();
|
|
466
|
+
const timeoutHandle = typeof timeoutMs === "number" && timeoutMs > 0 ? setTimeout(() => controller.abort(), timeoutMs) : null;
|
|
467
|
+
try {
|
|
468
|
+
logger.info("sprites_request", {
|
|
469
|
+
opId,
|
|
470
|
+
attempt,
|
|
471
|
+
requestId,
|
|
472
|
+
method: options.method,
|
|
473
|
+
path: options.path,
|
|
474
|
+
timeoutMs
|
|
475
|
+
});
|
|
476
|
+
return await options.run(controller.signal, requestId);
|
|
477
|
+
} catch (error) {
|
|
478
|
+
const retryable = shouldRetrySpritesRequest(options.method, error);
|
|
479
|
+
const remaining = maxAttempts - attempt;
|
|
480
|
+
if (!retryable || remaining <= 0) {
|
|
481
|
+
throw error;
|
|
482
|
+
}
|
|
483
|
+
const delayMs = computeRetryDelayMs(attempt);
|
|
484
|
+
logger.warn("sprites_http_retry", {
|
|
485
|
+
opId,
|
|
486
|
+
attempt,
|
|
487
|
+
requestId,
|
|
488
|
+
method: options.method,
|
|
489
|
+
path: options.path,
|
|
490
|
+
timeoutMs,
|
|
491
|
+
delayMs,
|
|
492
|
+
remainingAttempts: remaining,
|
|
493
|
+
errorName: error instanceof Error ? error.name : void 0,
|
|
494
|
+
errorMessage: error instanceof Error ? error.message : String(error),
|
|
495
|
+
errorCode: getErrorCode(error),
|
|
496
|
+
...error instanceof SpritesApiError ? { status: error.status } : {}
|
|
497
|
+
});
|
|
498
|
+
await delay(delayMs);
|
|
499
|
+
} finally {
|
|
500
|
+
if (timeoutHandle) clearTimeout(timeoutHandle);
|
|
501
|
+
}
|
|
435
502
|
}
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
requestId,
|
|
503
|
+
throw new Error(`Sprites request failed: ${options.method} ${options.path}`);
|
|
504
|
+
};
|
|
505
|
+
requestJson = async (apiBaseUrl, token, method, path6, body) => {
|
|
506
|
+
return await withSpritesRetry({
|
|
441
507
|
method,
|
|
442
508
|
path: path6,
|
|
443
|
-
|
|
509
|
+
run: async (signal, requestId) => {
|
|
510
|
+
const url = new URL(path6, apiBaseUrl);
|
|
511
|
+
const headers = {
|
|
512
|
+
authorization: `Bearer ${token}`,
|
|
513
|
+
"x-request-id": requestId
|
|
514
|
+
};
|
|
515
|
+
if (body) {
|
|
516
|
+
headers["content-type"] = "application/json";
|
|
517
|
+
}
|
|
518
|
+
const init = { method, headers, signal };
|
|
519
|
+
if (body) {
|
|
520
|
+
init.body = JSON.stringify(body);
|
|
521
|
+
}
|
|
522
|
+
const response = await fetch(url, init);
|
|
523
|
+
const text = await response.text();
|
|
524
|
+
logger.info("sprites_response", {
|
|
525
|
+
requestId,
|
|
526
|
+
method,
|
|
527
|
+
path: path6,
|
|
528
|
+
status: response.status
|
|
529
|
+
});
|
|
530
|
+
if (!response.ok) {
|
|
531
|
+
const snippet = text.trim().slice(0, 200);
|
|
532
|
+
throw new SpritesApiError(response.status, method, path6, snippet);
|
|
533
|
+
}
|
|
534
|
+
if (!text) return null;
|
|
535
|
+
try {
|
|
536
|
+
return JSON.parse(text);
|
|
537
|
+
} catch {
|
|
538
|
+
return text;
|
|
539
|
+
}
|
|
540
|
+
}
|
|
444
541
|
});
|
|
445
|
-
if (!response.ok) {
|
|
446
|
-
const snippet = text.trim().slice(0, 200);
|
|
447
|
-
throw new SpritesApiError(response.status, method, path6, snippet);
|
|
448
|
-
}
|
|
449
|
-
if (!text) return null;
|
|
450
|
-
try {
|
|
451
|
-
return JSON.parse(text);
|
|
452
|
-
} catch {
|
|
453
|
-
return text;
|
|
454
|
-
}
|
|
455
542
|
};
|
|
456
543
|
listSprites = async (apiBaseUrl, token, options) => {
|
|
457
544
|
const params = new URLSearchParams();
|
|
@@ -492,88 +579,99 @@ var init_sprites = __esm({
|
|
|
492
579
|
return response;
|
|
493
580
|
};
|
|
494
581
|
requestNdjson = async (apiBaseUrl, token, method, path6, body) => {
|
|
495
|
-
|
|
496
|
-
const url = new URL(path6, apiBaseUrl);
|
|
497
|
-
const headers = {
|
|
498
|
-
authorization: `Bearer ${token}`,
|
|
499
|
-
"x-request-id": requestId
|
|
500
|
-
};
|
|
501
|
-
if (body) {
|
|
502
|
-
headers["content-type"] = "application/json";
|
|
503
|
-
}
|
|
504
|
-
const init = { method, headers };
|
|
505
|
-
if (body) {
|
|
506
|
-
init.body = JSON.stringify(body);
|
|
507
|
-
}
|
|
508
|
-
logger.info("sprites_request", { requestId, method, path: path6 });
|
|
509
|
-
const response = await fetch(url, init);
|
|
510
|
-
logger.info("sprites_response", {
|
|
511
|
-
requestId,
|
|
582
|
+
return await withSpritesRetry({
|
|
512
583
|
method,
|
|
513
584
|
path: path6,
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
585
|
+
run: async (signal, requestId) => {
|
|
586
|
+
const url = new URL(path6, apiBaseUrl);
|
|
587
|
+
const headers = {
|
|
588
|
+
authorization: `Bearer ${token}`,
|
|
589
|
+
"x-request-id": requestId
|
|
590
|
+
};
|
|
591
|
+
if (body) {
|
|
592
|
+
headers["content-type"] = "application/json";
|
|
593
|
+
}
|
|
594
|
+
const init = { method, headers, signal };
|
|
595
|
+
if (body) {
|
|
596
|
+
init.body = JSON.stringify(body);
|
|
597
|
+
}
|
|
598
|
+
const response = await fetch(url, init);
|
|
599
|
+
logger.info("sprites_response", {
|
|
600
|
+
requestId,
|
|
601
|
+
method,
|
|
602
|
+
path: path6,
|
|
603
|
+
status: response.status
|
|
604
|
+
});
|
|
605
|
+
const text = await response.text();
|
|
606
|
+
if (!response.ok) {
|
|
607
|
+
const snippet = text.trim().slice(0, 200);
|
|
608
|
+
throw new SpritesApiError(response.status, method, path6, snippet);
|
|
609
|
+
}
|
|
610
|
+
const lines = text.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
611
|
+
const events = [];
|
|
612
|
+
for (const line of lines) {
|
|
613
|
+
try {
|
|
614
|
+
const parsed = JSON.parse(line);
|
|
615
|
+
if (Array.isArray(parsed)) {
|
|
616
|
+
for (const entry of parsed) {
|
|
617
|
+
if (entry && typeof entry === "object") {
|
|
618
|
+
events.push(entry);
|
|
619
|
+
} else {
|
|
620
|
+
events.push({ value: entry });
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
continue;
|
|
532
624
|
}
|
|
625
|
+
if (parsed && typeof parsed === "object") {
|
|
626
|
+
events.push(parsed);
|
|
627
|
+
continue;
|
|
628
|
+
}
|
|
629
|
+
events.push({ value: parsed });
|
|
630
|
+
} catch {
|
|
631
|
+
events.push({ raw: line });
|
|
533
632
|
}
|
|
534
|
-
continue;
|
|
535
|
-
}
|
|
536
|
-
if (parsed && typeof parsed === "object") {
|
|
537
|
-
events.push(parsed);
|
|
538
|
-
continue;
|
|
539
633
|
}
|
|
540
|
-
events
|
|
541
|
-
} catch {
|
|
542
|
-
events.push({ raw: line });
|
|
634
|
+
return events;
|
|
543
635
|
}
|
|
544
|
-
}
|
|
545
|
-
return events;
|
|
636
|
+
});
|
|
546
637
|
};
|
|
547
638
|
writeFile = async (apiBaseUrl, token, name, remotePath, data) => {
|
|
548
|
-
const requestId = (0, import_node_crypto.randomUUID)();
|
|
549
639
|
const path6 = `/v1/sprites/${name}/fs/write`;
|
|
550
640
|
const url = new URL(path6, apiBaseUrl);
|
|
551
641
|
url.searchParams.set("path", remotePath);
|
|
552
642
|
url.searchParams.set("mkdir", "true");
|
|
553
|
-
|
|
554
|
-
requestId,
|
|
555
|
-
path: path6,
|
|
556
|
-
name,
|
|
557
|
-
remotePath,
|
|
558
|
-
size: data.length
|
|
559
|
-
});
|
|
560
|
-
const response = await fetch(url, {
|
|
643
|
+
await withSpritesRetry({
|
|
561
644
|
method: "PUT",
|
|
562
|
-
headers: {
|
|
563
|
-
authorization: `Bearer ${token}`,
|
|
564
|
-
"content-type": "application/octet-stream",
|
|
565
|
-
"x-request-id": requestId
|
|
566
|
-
},
|
|
567
|
-
body: data
|
|
568
|
-
});
|
|
569
|
-
logger.info("sprites_fs_write_response", {
|
|
570
|
-
requestId,
|
|
571
645
|
path: path6,
|
|
572
|
-
|
|
646
|
+
run: async (signal, requestId) => {
|
|
647
|
+
logger.info("sprites_fs_write", {
|
|
648
|
+
requestId,
|
|
649
|
+
path: path6,
|
|
650
|
+
name,
|
|
651
|
+
remotePath,
|
|
652
|
+
size: data.length
|
|
653
|
+
});
|
|
654
|
+
const response = await fetch(url, {
|
|
655
|
+
method: "PUT",
|
|
656
|
+
headers: {
|
|
657
|
+
authorization: `Bearer ${token}`,
|
|
658
|
+
"content-type": "application/octet-stream",
|
|
659
|
+
"x-request-id": requestId
|
|
660
|
+
},
|
|
661
|
+
body: data,
|
|
662
|
+
signal
|
|
663
|
+
});
|
|
664
|
+
logger.info("sprites_fs_write_response", {
|
|
665
|
+
requestId,
|
|
666
|
+
path: path6,
|
|
667
|
+
status: response.status
|
|
668
|
+
});
|
|
669
|
+
if (!response.ok) {
|
|
670
|
+
const snippet = (await response.text()).trim().slice(0, 200);
|
|
671
|
+
throw new SpritesApiError(response.status, "PUT", path6, snippet);
|
|
672
|
+
}
|
|
673
|
+
}
|
|
573
674
|
});
|
|
574
|
-
if (!response.ok) {
|
|
575
|
-
throw new Error(`Sprites FS write failed: ${response.status}`);
|
|
576
|
-
}
|
|
577
675
|
};
|
|
578
676
|
normalizeServiceRecord = (entry) => {
|
|
579
677
|
const rawName = entry.name;
|
|
@@ -604,38 +702,44 @@ var init_sprites = __esm({
|
|
|
604
702
|
return service;
|
|
605
703
|
};
|
|
606
704
|
readFile = async (apiBaseUrl, token, name, options) => {
|
|
607
|
-
const requestId = (0, import_node_crypto.randomUUID)();
|
|
608
705
|
const path6 = `/v1/sprites/${name}/fs/read`;
|
|
609
706
|
const url = new URL(path6, apiBaseUrl);
|
|
610
707
|
url.searchParams.set("path", options.path);
|
|
611
708
|
if (options.workingDir) {
|
|
612
709
|
url.searchParams.set("workingDir", options.workingDir);
|
|
613
710
|
}
|
|
614
|
-
|
|
615
|
-
requestId,
|
|
616
|
-
path: path6,
|
|
617
|
-
name,
|
|
618
|
-
remotePath: options.path,
|
|
619
|
-
workingDir: options.workingDir
|
|
620
|
-
});
|
|
621
|
-
const response = await fetch(url, {
|
|
711
|
+
return await withSpritesRetry({
|
|
622
712
|
method: "GET",
|
|
623
|
-
headers: {
|
|
624
|
-
authorization: `Bearer ${token}`,
|
|
625
|
-
"x-request-id": requestId
|
|
626
|
-
}
|
|
627
|
-
});
|
|
628
|
-
logger.info("sprites_fs_read_response", {
|
|
629
|
-
requestId,
|
|
630
713
|
path: path6,
|
|
631
|
-
|
|
714
|
+
run: async (signal, requestId) => {
|
|
715
|
+
logger.info("sprites_fs_read", {
|
|
716
|
+
requestId,
|
|
717
|
+
path: path6,
|
|
718
|
+
name,
|
|
719
|
+
remotePath: options.path,
|
|
720
|
+
workingDir: options.workingDir
|
|
721
|
+
});
|
|
722
|
+
const response = await fetch(url, {
|
|
723
|
+
method: "GET",
|
|
724
|
+
headers: {
|
|
725
|
+
authorization: `Bearer ${token}`,
|
|
726
|
+
"x-request-id": requestId
|
|
727
|
+
},
|
|
728
|
+
signal
|
|
729
|
+
});
|
|
730
|
+
logger.info("sprites_fs_read_response", {
|
|
731
|
+
requestId,
|
|
732
|
+
path: path6,
|
|
733
|
+
status: response.status
|
|
734
|
+
});
|
|
735
|
+
if (!response.ok) {
|
|
736
|
+
const snippet = (await response.text()).trim().slice(0, 200);
|
|
737
|
+
throw new SpritesApiError(response.status, "GET", path6, snippet);
|
|
738
|
+
}
|
|
739
|
+
const buffer = await response.arrayBuffer();
|
|
740
|
+
return new Uint8Array(buffer);
|
|
741
|
+
}
|
|
632
742
|
});
|
|
633
|
-
if (!response.ok) {
|
|
634
|
-
const snippet = (await response.text()).trim().slice(0, 200);
|
|
635
|
-
throw new SpritesApiError(response.status, "GET", path6, snippet);
|
|
636
|
-
}
|
|
637
|
-
const buffer = await response.arrayBuffer();
|
|
638
|
-
return new Uint8Array(buffer);
|
|
639
743
|
};
|
|
640
744
|
openExecSocket = (apiBaseUrl, token, name, options) => {
|
|
641
745
|
const url = toWsUrl(apiBaseUrl, `/v1/sprites/${name}/exec`);
|
|
@@ -4556,27 +4660,27 @@ var init_authentication_manager = __esm({
|
|
|
4556
4660
|
);
|
|
4557
4661
|
return;
|
|
4558
4662
|
}
|
|
4559
|
-
let
|
|
4663
|
+
let delay2 = Math.min(
|
|
4560
4664
|
MAXIMUM_REFRESH_DELAY,
|
|
4561
4665
|
(tokenValiditySeconds - this.refreshTokenLeewaySeconds) * 1e3
|
|
4562
4666
|
);
|
|
4563
|
-
if (
|
|
4667
|
+
if (delay2 <= 0) {
|
|
4564
4668
|
this.logger.warn(
|
|
4565
4669
|
`Refetching auth token immediately, configured leeway ${this.refreshTokenLeewaySeconds}s is larger than the token's lifetime ${tokenValiditySeconds}s`
|
|
4566
4670
|
);
|
|
4567
|
-
|
|
4671
|
+
delay2 = 0;
|
|
4568
4672
|
}
|
|
4569
4673
|
const refetchTokenTimeoutId = setTimeout(() => {
|
|
4570
4674
|
this._logVerbose("running scheduled token refetch");
|
|
4571
4675
|
void this.refetchToken();
|
|
4572
|
-
},
|
|
4676
|
+
}, delay2);
|
|
4573
4677
|
this.setAuthState({
|
|
4574
4678
|
state: "waitingForScheduledRefetch",
|
|
4575
4679
|
refetchTokenTimeoutId,
|
|
4576
4680
|
config: this.authState.config
|
|
4577
4681
|
});
|
|
4578
4682
|
this._logVerbose(
|
|
4579
|
-
`scheduled preemptive auth token refetching in ${
|
|
4683
|
+
`scheduled preemptive auth token refetching in ${delay2}ms`
|
|
4580
4684
|
);
|
|
4581
4685
|
}
|
|
4582
4686
|
// Protects against simultaneous calls to `setConfig`
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/prompts.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/prompts.ts"],"names":[],"mappings":"AAyBA,QAAA,MAAM,kBAAkB,GAAU,MAAM,MAAM,oBAI7C,CAAC;AAOF,QAAA,MAAM,6BAA6B,uBACM,CAAC;AAC1C,QAAA,MAAM,2BAA2B,uBACK,CAAC;AACvC,QAAA,MAAM,iCAAiC,uBACM,CAAC;AAC9C,QAAA,MAAM,2BAA2B,uBACK,CAAC;AAEvC,QAAA,MAAM,qBAAqB,GACzB,WAAW,MAAM,EACjB,iBAAiB,MAAM,EACvB,mBAAmB,MAAM,EACzB,kBAAkB,MAAM,oBAOtB,CAAC;AAEL,OAAO,EACL,6BAA6B,EAC7B,2BAA2B,EAC3B,iCAAiC,EACjC,qBAAqB,EACrB,2BAA2B,EAC3B,kBAAkB,GACnB,CAAC"}
|
|
@@ -1,16 +1,31 @@
|
|
|
1
|
-
import fs from "node:fs
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import fsPromises from "node:fs/promises";
|
|
2
3
|
import path from "node:path";
|
|
3
4
|
import { renderTemplate } from "./template.js";
|
|
4
5
|
const resolvePromptsDir = () => {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
// Prefer resolving relative to the real dvb entrypoint, since `process.argv[1]`
|
|
7
|
+
// may be a bin shim (e.g. ~/.nvm/.../bin/dvb) rather than `.../dist/bin/dvb.cjs`.
|
|
8
|
+
const argv1 = typeof process.argv[1] === "string" ? process.argv[1] : "";
|
|
9
|
+
if (argv1) {
|
|
10
|
+
try {
|
|
11
|
+
const real = fs.realpathSync(argv1);
|
|
12
|
+
return path.resolve(path.dirname(real), "..", "prompts");
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
// ignore and fall back
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
return path.resolve(path.dirname(argv1), "..", "prompts");
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// ignore and fall back
|
|
22
|
+
}
|
|
8
23
|
}
|
|
9
24
|
return path.resolve(process.cwd(), "prompts");
|
|
10
25
|
};
|
|
11
26
|
const readPromptTemplate = async (name) => {
|
|
12
27
|
const promptPath = path.join(resolvePromptsDir(), name);
|
|
13
|
-
const raw = await
|
|
28
|
+
const raw = await fsPromises.readFile(promptPath, "utf8");
|
|
14
29
|
return raw;
|
|
15
30
|
};
|
|
16
31
|
const loadPrompt = async (name, vars = {}) => renderTemplate(await readPromptTemplate(name), vars).trim();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../../../src/devbox/commands/init/codex/prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,UAAU,MAAM,kBAAkB,CAAC;AAC1C,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAE/C,MAAM,iBAAiB,GAAG,GAAG,EAAE;IAC7B,gFAAgF;IAChF,kFAAkF;IAClF,MAAM,KAAK,GAAG,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACzE,IAAI,KAAK,EAAE,CAAC;QACV,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;YACpC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAC3D,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;QACD,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,IAAI,EAAE,SAAS,CAAC,CAAC;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,uBAAuB;QACzB,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,SAAS,CAAC,CAAC;AAChD,CAAC,CAAC;AAEF,MAAM,kBAAkB,GAAG,KAAK,EAAE,IAAY,EAAE,EAAE;IAChD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,EAAE,IAAI,CAAC,CAAC;IACxD,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAC1D,OAAO,GAAG,CAAC;AACb,CAAC,CAAC;AAEF,MAAM,UAAU,GAAG,KAAK,EACtB,IAAY,EACZ,OAA+B,EAAE,EACjC,EAAE,CAAC,cAAc,CAAC,MAAM,kBAAkB,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;AAEjE,MAAM,6BAA6B,GAAG,KAAK,IAAI,EAAE,CAC/C,UAAU,CAAC,2BAA2B,CAAC,CAAC;AAC1C,MAAM,2BAA2B,GAAG,KAAK,IAAI,EAAE,CAC7C,UAAU,CAAC,wBAAwB,CAAC,CAAC;AACvC,MAAM,iCAAiC,GAAG,KAAK,IAAI,EAAE,CACnD,UAAU,CAAC,+BAA+B,CAAC,CAAC;AAC9C,MAAM,2BAA2B,GAAG,KAAK,IAAI,EAAE,CAC7C,UAAU,CAAC,wBAAwB,CAAC,CAAC;AAEvC,MAAM,qBAAqB,GAAG,KAAK,EACjC,SAAiB,EACjB,eAAuB,EACvB,iBAAyB,EACzB,gBAAwB,EACxB,EAAE,CACF,UAAU,CAAC,iBAAiB,EAAE;IAC5B,UAAU,EAAE,SAAS;IACrB,gBAAgB,EAAE,eAAe;IACjC,kBAAkB,EAAE,iBAAiB;IACrC,iBAAiB,EAAE,gBAAgB;CACpC,CAAC,CAAC;AAEL,OAAO,EACL,6BAA6B,EAC7B,2BAA2B,EAC3B,iCAAiC,EACjC,qBAAqB,EACrB,2BAA2B,EAC3B,kBAAkB,GACnB,CAAC"}
|