run402 4.109.0 → 4.110.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/lib/deploy-v2.mjs +46 -5
- package/lib/sdk-errors.mjs +8 -1
- package/package.json +1 -1
- package/sdk/dist/errors.d.ts +1 -1
- package/sdk/dist/errors.d.ts.map +1 -1
- package/sdk/dist/errors.js.map +1 -1
- package/sdk/dist/index.d.ts +1 -0
- package/sdk/dist/index.d.ts.map +1 -1
- package/sdk/dist/index.js.map +1 -1
- package/sdk/dist/namespaces/deploy.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.js +112 -26
- package/sdk/dist/namespaces/deploy.js.map +1 -1
- package/sdk/dist/namespaces/deploy.types.d.ts +30 -0
- package/sdk/dist/namespaces/deploy.types.d.ts.map +1 -1
- package/sdk/dist/namespaces/deploy.types.js.map +1 -1
- package/sdk/dist/namespaces/site-removal-summary.d.ts +48 -0
- package/sdk/dist/namespaces/site-removal-summary.d.ts.map +1 -0
- package/sdk/dist/namespaces/site-removal-summary.js +107 -0
- package/sdk/dist/namespaces/site-removal-summary.js.map +1 -0
- package/sdk/dist/node/deploy-manifest.d.ts +12 -0
- package/sdk/dist/node/deploy-manifest.d.ts.map +1 -1
- package/sdk/dist/node/deploy-manifest.js +16 -3
- package/sdk/dist/node/deploy-manifest.js.map +1 -1
- package/sdk/dist/type-contract.d.ts.map +1 -1
- package/sdk/dist/type-contract.js +7 -0
- package/sdk/dist/type-contract.js.map +1 -1
- package/vault-surface.json +1 -1
|
@@ -26,6 +26,7 @@ import { assertCiDeployableSpec } from "./ci.js";
|
|
|
26
26
|
import { ROUTE_PRICING_NETWORKS, ROUTE_HTTP_METHODS, isModernPlanMigrationDiff, normalizeDeployResolveRequest, } from "./deploy.types.js";
|
|
27
27
|
import { ApiError, LocalError, NetworkError, PaymentRequired, Run402DeployError, Unauthorized, isRun402Error, isTransferFreezeError, } from "../errors.js";
|
|
28
28
|
import { assertAssetMetadata, assertExifPolicy, } from "./assets-validation.js";
|
|
29
|
+
import { withSiteRemovalSummaries } from "./site-removal-summary.js";
|
|
29
30
|
// ─── Constants ───────────────────────────────────────────────────────────────
|
|
30
31
|
const PLAN_BODY_LIMIT_BYTES = 5 * 1024 * 1024;
|
|
31
32
|
const COMMIT_POLL_INITIAL_MS = 1_000;
|
|
@@ -45,6 +46,25 @@ const SECRET_KEY_RE = /^[A-Z_][A-Z0-9_]{0,127}$/;
|
|
|
45
46
|
const APPLY_SAFE_RETRY_CODES = new Set([
|
|
46
47
|
"BASE_RELEASE_CONFLICT",
|
|
47
48
|
]);
|
|
49
|
+
/**
|
|
50
|
+
* Transient platform conditions the gateway marks `safe_to_retry: true`: the
|
|
51
|
+
* task running the deploy was replaced mid-commit, an image encode ran out of
|
|
52
|
+
* wall clock or queue under load, or an archive export briefly paused writes.
|
|
53
|
+
* Nothing was activated, so the whole apply re-plans and runs again — content
|
|
54
|
+
* is addressed by hash, so already-uploaded bytes are not sent twice
|
|
55
|
+
* (kychee-com/run402#628, #616). These wait longer than a release-race replan.
|
|
56
|
+
*/
|
|
57
|
+
const APPLY_TRANSIENT_RETRY_CODES = new Set([
|
|
58
|
+
"OPERATION_INTERRUPTED",
|
|
59
|
+
"IMAGE_ENCODE_TIMEOUT",
|
|
60
|
+
"TOO_MANY_ENCODES_QUEUED",
|
|
61
|
+
"EXPORT_CONSISTENCY_UNAVAILABLE",
|
|
62
|
+
]);
|
|
63
|
+
const APPLY_TRANSIENT_RETRY_BASE_DELAY_MS = 2_000;
|
|
64
|
+
const APPLY_TRANSIENT_RETRY_MAX_DELAY_MS = 15_000;
|
|
65
|
+
/** A read or an idempotent request lost to a 502/503/504 or a dropped connection. */
|
|
66
|
+
const TRANSIENT_REQUEST_MAX_ATTEMPTS = 3;
|
|
67
|
+
const TRANSIENT_REQUEST_RETRY_BASE_DELAY_MS = 500;
|
|
48
68
|
const EMAIL_TRIGGER_EVENTS = new Set(["reply_received", "delivery", "bounced", "complained", "mailbox_suspended"]);
|
|
49
69
|
const STATIC_ACTIVATION_FAILURE_CODES = new Set([
|
|
50
70
|
"BAD_FIELD",
|
|
@@ -111,29 +131,31 @@ export class Deploy {
|
|
|
111
131
|
return await applyOnce(this.client, spec, opts, emit);
|
|
112
132
|
}
|
|
113
133
|
catch (err) {
|
|
114
|
-
if (!(err
|
|
134
|
+
if (!isRun402Error(err))
|
|
115
135
|
throw err;
|
|
116
136
|
const safeToRetry = isSafeDeployApplyRetry(err, spec);
|
|
117
137
|
if (!safeToRetry)
|
|
118
138
|
throw err;
|
|
119
139
|
if (attempt === maxAttempts) {
|
|
120
|
-
if (maxRetries > 0) {
|
|
140
|
+
if (maxRetries > 0 && err instanceof Run402DeployError) {
|
|
121
141
|
throw withDeployRetryMetadata(err, attempt, maxRetries, err.code);
|
|
122
142
|
}
|
|
123
143
|
throw err;
|
|
124
144
|
}
|
|
125
|
-
const
|
|
145
|
+
const code = err.code ?? "UNKNOWN";
|
|
146
|
+
const delayMs = deployApplyRetryDelayMs(attempt, code);
|
|
147
|
+
const deployErr = err instanceof Run402DeployError ? err : null;
|
|
126
148
|
emit({
|
|
127
149
|
type: "deploy.retry",
|
|
128
150
|
attempt,
|
|
129
151
|
nextAttempt: attempt + 1,
|
|
130
152
|
maxAttempts,
|
|
131
153
|
delayMs,
|
|
132
|
-
code
|
|
133
|
-
phase:
|
|
134
|
-
resource:
|
|
135
|
-
operationId:
|
|
136
|
-
planId:
|
|
154
|
+
code,
|
|
155
|
+
phase: deployErr?.phase ?? null,
|
|
156
|
+
resource: deployErr?.resource ?? null,
|
|
157
|
+
operationId: deployErr?.operationId ?? null,
|
|
158
|
+
planId: deployErr?.planId ?? null,
|
|
137
159
|
message: err.message,
|
|
138
160
|
});
|
|
139
161
|
await sleep(delayMs);
|
|
@@ -842,7 +864,14 @@ function normalizeApplyMaxRetries(value) {
|
|
|
842
864
|
return value;
|
|
843
865
|
}
|
|
844
866
|
function isSafeDeployApplyRetry(err, spec) {
|
|
845
|
-
|
|
867
|
+
if (err.safeToRetry !== true || typeof err.code !== "string")
|
|
868
|
+
return false;
|
|
869
|
+
// Transient codes reach here from the deploy state machine (a failed
|
|
870
|
+
// operation) or as a plain API error from an upload-phase request. Nothing
|
|
871
|
+
// was activated either way, so the spec's base still holds.
|
|
872
|
+
if (APPLY_TRANSIENT_RETRY_CODES.has(err.code))
|
|
873
|
+
return true;
|
|
874
|
+
return (err instanceof Run402DeployError &&
|
|
846
875
|
APPLY_SAFE_RETRY_CODES.has(err.code) &&
|
|
847
876
|
isAutoRebasableSpec(spec));
|
|
848
877
|
}
|
|
@@ -851,9 +880,11 @@ function isAutoRebasableSpec(spec) {
|
|
|
851
880
|
return true;
|
|
852
881
|
return "release" in spec.base && spec.base.release === "current";
|
|
853
882
|
}
|
|
854
|
-
function deployApplyRetryDelayMs(attempt) {
|
|
855
|
-
const
|
|
856
|
-
const
|
|
883
|
+
function deployApplyRetryDelayMs(attempt, code) {
|
|
884
|
+
const transient = APPLY_TRANSIENT_RETRY_CODES.has(code);
|
|
885
|
+
const base = transient ? APPLY_TRANSIENT_RETRY_BASE_DELAY_MS : APPLY_RETRY_BASE_DELAY_MS;
|
|
886
|
+
const max = transient ? APPLY_TRANSIENT_RETRY_MAX_DELAY_MS : APPLY_RETRY_MAX_DELAY_MS;
|
|
887
|
+
const capped = Math.min(base * 2 ** (attempt - 1), max);
|
|
857
888
|
return capped + Math.floor(Math.random() * (APPLY_RETRY_JITTER_MS + 1));
|
|
858
889
|
}
|
|
859
890
|
function withDeployRetryMetadata(err, attempts, maxRetries, lastRetryCode) {
|
|
@@ -1072,22 +1103,26 @@ function siteToCoreSpec(site) {
|
|
|
1072
1103
|
...(site.public_paths ? { public_paths: site.public_paths } : {}),
|
|
1073
1104
|
};
|
|
1074
1105
|
}
|
|
1075
|
-
// tenant-site-embedding and site.
|
|
1076
|
-
// gateway-owned and core validates site keys against
|
|
1106
|
+
// tenant-site-embedding, site.sign_in_path, and site.noindex never reach
|
|
1107
|
+
// core: all three are gateway-owned and core validates site keys against
|
|
1108
|
+
// its own list.
|
|
1077
1109
|
return site.public_paths ? { public_paths: site.public_paths } : {};
|
|
1078
1110
|
}
|
|
1079
1111
|
function siteToWire(site) {
|
|
1080
1112
|
// tenant-site-embedding: `null` is a meaningful value on the wire (clear), so
|
|
1081
1113
|
// it is carried whenever the key is present, unlike public_paths.
|
|
1082
|
-
// site.sign_in_path follows the same rule (`null` clears back to the hosted page)
|
|
1114
|
+
// site.sign_in_path follows the same rule (`null` clears back to the hosted page),
|
|
1115
|
+
// and so does site.noindex (`false` or `null` clears back to indexable).
|
|
1083
1116
|
const embedding = "embedding" in site && site.embedding !== undefined ? { embedding: site.embedding } : {};
|
|
1084
1117
|
const signInPath = "sign_in_path" in site && site.sign_in_path !== undefined ? { sign_in_path: site.sign_in_path } : {};
|
|
1118
|
+
const noindex = "noindex" in site && site.noindex !== undefined ? { noindex: site.noindex } : {};
|
|
1085
1119
|
if ("replace" in site && site.replace) {
|
|
1086
1120
|
return {
|
|
1087
1121
|
replace: fileSetToWire(site.replace),
|
|
1088
1122
|
...(site.public_paths ? { public_paths: site.public_paths } : {}),
|
|
1089
1123
|
...embedding,
|
|
1090
1124
|
...signInPath,
|
|
1125
|
+
...noindex,
|
|
1091
1126
|
};
|
|
1092
1127
|
}
|
|
1093
1128
|
if ("patch" in site && site.patch) {
|
|
@@ -1099,12 +1134,14 @@ function siteToWire(site) {
|
|
|
1099
1134
|
...(site.public_paths ? { public_paths: site.public_paths } : {}),
|
|
1100
1135
|
...embedding,
|
|
1101
1136
|
...signInPath,
|
|
1137
|
+
...noindex,
|
|
1102
1138
|
};
|
|
1103
1139
|
}
|
|
1104
1140
|
return {
|
|
1105
1141
|
...(site.public_paths ? { public_paths: site.public_paths } : {}),
|
|
1106
1142
|
...embedding,
|
|
1107
1143
|
...signInPath,
|
|
1144
|
+
...noindex,
|
|
1108
1145
|
};
|
|
1109
1146
|
}
|
|
1110
1147
|
function i18nToWire(i18n) {
|
|
@@ -1599,6 +1636,7 @@ function expandCronNumberPart(part, min, max) {
|
|
|
1599
1636
|
return values;
|
|
1600
1637
|
}
|
|
1601
1638
|
async function commitInternal(client, planId, idempotencyKey, project, requiredPlan, vault, operationId) {
|
|
1639
|
+
const tries = { attempts: 0 };
|
|
1602
1640
|
try {
|
|
1603
1641
|
const body = {};
|
|
1604
1642
|
if (idempotencyKey)
|
|
@@ -1622,10 +1660,16 @@ async function commitInternal(client, planId, idempotencyKey, project, requiredP
|
|
|
1622
1660
|
: {}),
|
|
1623
1661
|
context: "committing deploy",
|
|
1624
1662
|
});
|
|
1625
|
-
return await sendCommitRecoveringLostResponse(client, send, operationId, project);
|
|
1663
|
+
return await sendCommitRecoveringLostResponse(client, send, operationId, project, tries);
|
|
1626
1664
|
}
|
|
1627
1665
|
catch (err) {
|
|
1628
|
-
|
|
1666
|
+
const translated = translateDeployError(err, "commit", planId, operationId ?? null);
|
|
1667
|
+
// Retries were spent on a lost response: say how many and on what, so a
|
|
1668
|
+
// caller can tell "the SDK already tried" from "the first attempt failed".
|
|
1669
|
+
if (tries.attempts > 1) {
|
|
1670
|
+
throw withDeployRetryMetadata(translated, tries.attempts, DEPLOY_COMMIT_MAX_ATTEMPTS - 1, translated.code);
|
|
1671
|
+
}
|
|
1672
|
+
throw translated;
|
|
1629
1673
|
}
|
|
1630
1674
|
}
|
|
1631
1675
|
/**
|
|
@@ -1636,9 +1680,11 @@ async function commitInternal(client, planId, idempotencyKey, project, requiredP
|
|
|
1636
1680
|
* operation first: once it has left `planning`/`uploading` the commit landed,
|
|
1637
1681
|
* and the caller follows the operation; otherwise the commit never arrived and
|
|
1638
1682
|
* is sent again. Without an operation id to read, the failure surfaces as is.
|
|
1683
|
+
* `tries.attempts` counts the commits sent, for the error's retry metadata.
|
|
1639
1684
|
*/
|
|
1640
|
-
async function sendCommitRecoveringLostResponse(client, send, operationId, projectId) {
|
|
1685
|
+
async function sendCommitRecoveringLostResponse(client, send, operationId, projectId, tries) {
|
|
1641
1686
|
for (let attempt = 1;; attempt++) {
|
|
1687
|
+
tries.attempts = attempt;
|
|
1642
1688
|
try {
|
|
1643
1689
|
return await send();
|
|
1644
1690
|
}
|
|
@@ -1692,14 +1738,16 @@ async function uploadMissing(client, projectId, presence, byteReaders, emit) {
|
|
|
1692
1738
|
content_type: reader?.contentType,
|
|
1693
1739
|
};
|
|
1694
1740
|
});
|
|
1695
|
-
|
|
1741
|
+
// A lost content plan is safe to repeat: it only opens upload sessions, and
|
|
1742
|
+
// an abandoned one expires unused.
|
|
1743
|
+
const planRes = await requestWithTransientRetry(() => client.request("/content/v1/plans", {
|
|
1696
1744
|
method: "POST",
|
|
1697
1745
|
headers,
|
|
1698
1746
|
body: ciCredentials
|
|
1699
1747
|
? { project_id: projectId, content: contentRequest }
|
|
1700
1748
|
: { content: contentRequest },
|
|
1701
1749
|
context: "planning content upload",
|
|
1702
|
-
});
|
|
1750
|
+
}));
|
|
1703
1751
|
const total = planRes.missing.length;
|
|
1704
1752
|
let done = 0;
|
|
1705
1753
|
for (const session of planRes.missing) {
|
|
@@ -1782,6 +1830,19 @@ async function commitContentPlanWithRetry(client, planId, headers) {
|
|
|
1782
1830
|
}
|
|
1783
1831
|
}
|
|
1784
1832
|
}
|
|
1833
|
+
/** Repeat a read or an idempotent request lost to a 502/503/504 or a dropped connection. */
|
|
1834
|
+
async function requestWithTransientRetry(send) {
|
|
1835
|
+
for (let attempt = 1;; attempt++) {
|
|
1836
|
+
try {
|
|
1837
|
+
return await send();
|
|
1838
|
+
}
|
|
1839
|
+
catch (err) {
|
|
1840
|
+
if (!isTransientGatewayFailure(err) || attempt >= TRANSIENT_REQUEST_MAX_ATTEMPTS)
|
|
1841
|
+
throw err;
|
|
1842
|
+
await sleep(TRANSIENT_REQUEST_RETRY_BASE_DELAY_MS * 2 ** (attempt - 1));
|
|
1843
|
+
}
|
|
1844
|
+
}
|
|
1845
|
+
}
|
|
1785
1846
|
function isTransientGatewayFailure(err) {
|
|
1786
1847
|
if (!isRun402Error(err))
|
|
1787
1848
|
return false;
|
|
@@ -2068,7 +2129,10 @@ async function pollSnapshotUntilReady(client, initial, diff, warnings, emit, pro
|
|
|
2068
2129
|
if (Date.now() - start > COMMIT_POLL_BACKOFF_AFTER_MS) {
|
|
2069
2130
|
interval = Math.min(Math.floor(interval * 1.5), COMMIT_POLL_MAX_MS);
|
|
2070
2131
|
}
|
|
2071
|
-
|
|
2132
|
+
// A poll lost to a 502/503/504 (a gateway rollout) says nothing about the
|
|
2133
|
+
// operation; read it again rather than abandon a deploy that is running.
|
|
2134
|
+
const operationId = snapshot.operation_id;
|
|
2135
|
+
snapshot = await requestWithTransientRetry(() => client.request(`/apply/v1/operations/${encodeURIComponent(operationId)}`, { headers: opHeaders, context: "polling deploy operation" }));
|
|
2072
2136
|
}
|
|
2073
2137
|
}
|
|
2074
2138
|
async function drainRecordedOperationEvents(client, operationId, headers, cursor, emit) {
|
|
@@ -2313,7 +2377,7 @@ const FUNCTION_SPEC_FIELDS = new Set([
|
|
|
2313
2377
|
const FUNCTION_CONFIG_FIELDS = new Set(["timeoutSeconds", "memoryMb"]);
|
|
2314
2378
|
const FUNCTION_TRIGGER_FIELDS = new Set(["id", "type", "cron", "timezone", "misfire_policy", "overlap_policy", "mailbox", "events", "run"]);
|
|
2315
2379
|
const FUNCTION_TRIGGER_RUN_FIELDS = new Set(["event_type", "payload", "retry", "expires_after_seconds"]);
|
|
2316
|
-
const SITE_SPEC_FIELDS = new Set(["replace", "patch", "public_paths", "embedding", "sign_in_path"]);
|
|
2380
|
+
const SITE_SPEC_FIELDS = new Set(["replace", "patch", "public_paths", "embedding", "sign_in_path", "noindex"]);
|
|
2317
2381
|
const SITE_PATCH_FIELDS = new Set(["put", "delete"]);
|
|
2318
2382
|
const SITE_PUBLIC_PATHS_FIELDS = new Set(["mode", "replace"]);
|
|
2319
2383
|
const PUBLIC_STATIC_PATH_FIELDS = new Set(["asset", "cache_class"]);
|
|
@@ -2652,6 +2716,17 @@ function validateSiteSpec(site) {
|
|
|
2652
2716
|
if (obj.sign_in_path !== undefined) {
|
|
2653
2717
|
validateSiteSignInPath(obj.sign_in_path, "site.sign_in_path");
|
|
2654
2718
|
}
|
|
2719
|
+
if (obj.noindex !== undefined) {
|
|
2720
|
+
validateSiteNoindex(obj.noindex, "site.noindex");
|
|
2721
|
+
}
|
|
2722
|
+
}
|
|
2723
|
+
/** site.noindex. `true` = every response of the host carries
|
|
2724
|
+
* `X-Robots-Tag: noindex, nofollow, nosnippet`; `false` or `null` clears back
|
|
2725
|
+
* to indexable; omitted carries forward. */
|
|
2726
|
+
function validateSiteNoindex(value, resource) {
|
|
2727
|
+
if (value === null || typeof value === "boolean")
|
|
2728
|
+
return;
|
|
2729
|
+
throw invalidSpec(`ReleaseSpec.${resource} must be true, false, or null; send true to add X-Robots-Tag: noindex, nofollow, nosnippet to every response of the host, false or null to make it indexable again, or omit ${resource} to carry the previous value forward`, resource);
|
|
2655
2730
|
}
|
|
2656
2731
|
/** site.sign_in_path. Structural check only (the gateway is authoritative on
|
|
2657
2732
|
* the reserved prefixes and the full rule set): a same-origin absolute path
|
|
@@ -3031,6 +3106,10 @@ function hasSiteContent(site) {
|
|
|
3031
3106
|
if (site && typeof site === "object" && "sign_in_path" in site && site.sign_in_path !== undefined) {
|
|
3032
3107
|
return true;
|
|
3033
3108
|
}
|
|
3109
|
+
// site.noindex: same rule, true/false/null is content.
|
|
3110
|
+
if (site && typeof site === "object" && "noindex" in site && site.noindex !== undefined) {
|
|
3111
|
+
return true;
|
|
3112
|
+
}
|
|
3034
3113
|
if (!isRecord(site))
|
|
3035
3114
|
return false;
|
|
3036
3115
|
if (hasRecordEntries(site.replace))
|
|
@@ -3113,7 +3192,7 @@ function invalidRouteSpec(message, resource) {
|
|
|
3113
3192
|
}
|
|
3114
3193
|
function normalizePlanResponse(plan) {
|
|
3115
3194
|
const raw = plan;
|
|
3116
|
-
const warnings = Array.isArray(raw.warnings) ? raw.warnings : [];
|
|
3195
|
+
const warnings = withSiteRemovalSummaries(Array.isArray(raw.warnings) ? raw.warnings : []);
|
|
3117
3196
|
const missingContent = Array.isArray(raw.missing_content) ? raw.missing_content : [];
|
|
3118
3197
|
if (raw.kind === "plan_response") {
|
|
3119
3198
|
const diff = {
|
|
@@ -3487,6 +3566,10 @@ async function normalizeReleaseSpec(client, spec, opts = {}) {
|
|
|
3487
3566
|
const signInPath = "sign_in_path" in spec.site && spec.site.sign_in_path !== undefined
|
|
3488
3567
|
? { sign_in_path: spec.site.sign_in_path }
|
|
3489
3568
|
: {};
|
|
3569
|
+
// site.noindex: present (boolean or null) travels as-is.
|
|
3570
|
+
const noindex = "noindex" in spec.site && spec.site.noindex !== undefined
|
|
3571
|
+
? { noindex: spec.site.noindex }
|
|
3572
|
+
: {};
|
|
3490
3573
|
if ("replace" in spec.site && spec.site.replace) {
|
|
3491
3574
|
const map = await normalizeFileSet(spec.site.replace, rememberRelease);
|
|
3492
3575
|
// Re-check post-expansion so `dir("dist")` (a LocalDirRef whose keys are
|
|
@@ -3497,6 +3580,7 @@ async function normalizeReleaseSpec(client, spec, opts = {}) {
|
|
|
3497
3580
|
...(publicPaths ? { public_paths: publicPaths } : {}),
|
|
3498
3581
|
...embedding,
|
|
3499
3582
|
...signInPath,
|
|
3583
|
+
...noindex,
|
|
3500
3584
|
};
|
|
3501
3585
|
}
|
|
3502
3586
|
else if ("patch" in spec.site && spec.site.patch) {
|
|
@@ -3512,13 +3596,15 @@ async function normalizeReleaseSpec(client, spec, opts = {}) {
|
|
|
3512
3596
|
...(publicPaths ? { public_paths: publicPaths } : {}),
|
|
3513
3597
|
...embedding,
|
|
3514
3598
|
...signInPath,
|
|
3599
|
+
...noindex,
|
|
3515
3600
|
};
|
|
3516
3601
|
}
|
|
3517
|
-
else if (publicPaths || "embedding" in embedding || "sign_in_path" in signInPath) {
|
|
3602
|
+
else if (publicPaths || "embedding" in embedding || "sign_in_path" in signInPath || "noindex" in noindex) {
|
|
3518
3603
|
normalized.site = {
|
|
3519
3604
|
...(publicPaths ? { public_paths: publicPaths } : {}),
|
|
3520
3605
|
...embedding,
|
|
3521
3606
|
...signInPath,
|
|
3607
|
+
...noindex,
|
|
3522
3608
|
};
|
|
3523
3609
|
}
|
|
3524
3610
|
}
|
|
@@ -4106,14 +4192,14 @@ function makeUnreadableReader(sha256, label) {
|
|
|
4106
4192
|
async function uploadInlineCas(client, projectId, bytes, contentType) {
|
|
4107
4193
|
const sha256 = await sha256Hex(bytes);
|
|
4108
4194
|
const headers = await apikeyHeaders(client, projectId);
|
|
4109
|
-
const planRes = await client.request("/content/v1/plans", {
|
|
4195
|
+
const planRes = await requestWithTransientRetry(() => client.request("/content/v1/plans", {
|
|
4110
4196
|
method: "POST",
|
|
4111
4197
|
headers,
|
|
4112
4198
|
body: {
|
|
4113
4199
|
content: [{ sha256, size: bytes.byteLength, content_type: contentType }],
|
|
4114
4200
|
},
|
|
4115
4201
|
context: "planning content upload",
|
|
4116
|
-
});
|
|
4202
|
+
}));
|
|
4117
4203
|
if (planRes.missing.length > 0) {
|
|
4118
4204
|
const session = planRes.missing[0];
|
|
4119
4205
|
await uploadOne(client.fetch, session, bytes);
|