gencow 0.1.220 → 0.1.222

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.
@@ -81,6 +81,10 @@ export function formatMemoryExceededDetails(appRow) {
81
81
  }
82
82
 
83
83
  export function formatRecoveryDispositionDetails(appRow) {
84
+ // A delete receipt owns the user-visible lifecycle. Runtime recovery
85
+ // diagnostics are internal while the platform is fencing and removing the
86
+ // app; showing them would incorrectly ask the customer to contact support.
87
+ if (appRow?.status === "deleting") return "";
84
88
  const disposition = appRow?.recoveryDisposition;
85
89
  if (disposition?.kind === "deploy_required") {
86
90
  return " Recovery: no deployment is available. Run `gencow deploy` from this project.\n Retryable: no";
@@ -13,13 +13,12 @@ const APP_DELETE_ACTIVE_STATES = new Set([
13
13
  "blocked_ownership_ambiguous",
14
14
  "blocked_active_work",
15
15
  "blocked_runtime_outcome_unknown",
16
+ "blocked_catalog_outcome_unknown",
16
17
  "failed_tenant_db_cleanup",
17
18
  "failed_catalog_cleanup",
18
- ]);
19
- const APP_DELETE_TERMINAL_FAILURE_STATES = new Set([
20
- "blocked_catalog_outcome_unknown",
21
19
  "failed_delete_recovery_required",
22
20
  ]);
21
+ const APP_DELETE_TERMINAL_FAILURE_STATES = new Set();
23
22
  const APP_DELETE_RESPONSE_STATES = new Set([
24
23
  ...APP_DELETE_ACTIVE_STATES,
25
24
  ...APP_DELETE_TERMINAL_FAILURE_STATES,
@@ -21,8 +21,38 @@ import { pollAcceptedDeploymentOperation } from "./deployment-operation-poll.mjs
21
21
  import { writeProjectMetadata } from "./deploy-project-metadata.mjs";
22
22
 
23
23
  function shouldPreserveFinalizeAttempt(error) {
24
- return error?.retryable === true ||
25
- error?.message === "APP_SERVING_ROUTE_COMMIT_PENDING";
24
+ return error?.retryable === true || error?.message === "APP_SERVING_ROUTE_COMMIT_PENDING";
25
+ }
26
+
27
+ const TRANSIENT_STATIC_DEPLOY_PROXY_STATUSES = new Set([502, 503, 504]);
28
+
29
+ async function isBodylessTransientStaticDeployResponse(response) {
30
+ if (
31
+ !TRANSIENT_STATIC_DEPLOY_PROXY_STATUSES.has(response?.status) ||
32
+ typeof response?.clone !== "function"
33
+ ) {
34
+ return false;
35
+ }
36
+ try {
37
+ return (await readJsonObjectResponse(response.clone())) === null;
38
+ } catch {
39
+ return false;
40
+ }
41
+ }
42
+
43
+ export async function postStaticDeployWithTransientProxyRetry({
44
+ send,
45
+ retryDelaysMs = [250, 500, 1_000],
46
+ delayImpl = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
47
+ }) {
48
+ let response;
49
+ for (let attempt = 0; ; attempt += 1) {
50
+ response = await send();
51
+ if (!(await isBodylessTransientStaticDeployResponse(response)) || attempt >= retryDelaysMs.length) {
52
+ return response;
53
+ }
54
+ await delayImpl(retryDelaysMs[attempt]);
55
+ }
26
56
  }
27
57
 
28
58
  export function resolveStaticDeployDir({
@@ -178,6 +208,8 @@ export function createStaticDeployRuntime({
178
208
  resolvePathImpl = resolve,
179
209
  setTimeoutImpl = setTimeout,
180
210
  statSyncImpl = statSync,
211
+ staticDeployRetryDelayImpl = (ms) => new Promise((resolve) => setTimeout(resolve, ms)),
212
+ staticDeployRetryDelaysMs,
181
213
  successImpl = success,
182
214
  tarCreateImpl,
183
215
  unlinkSyncImpl = unlinkSync,
@@ -383,22 +415,27 @@ export function createStaticDeployRuntime({
383
415
  infoImpl("Deploying static files...");
384
416
  let deployRes;
385
417
  try {
386
- deployRes = await platformFetchImpl(creds, `/platform/apps/${appId}/deploy-static`, {
387
- method: "POST",
388
- headers: {
389
- "Content-Type": "application/octet-stream",
390
- "X-Deploy-Local-Dir": cwd,
391
- "X-Gencow-Deploy-Claim": deployClaim.header,
392
- "X-Gencow-Deploy-Protocol": "1",
393
- "X-Gencow-CLI-Version": deployClaim.claim.generatedBy.version,
394
- ...(releaseAttemptId
395
- ? {
396
- "X-Gencow-Release-Attempt-Id": releaseAttemptId,
397
- "X-Gencow-Release-Environment": opts.envTarget || "dev",
398
- }
399
- : {}),
400
- },
401
- body: bundleBuffer,
418
+ deployRes = await postStaticDeployWithTransientProxyRetry({
419
+ send: () =>
420
+ platformFetchImpl(creds, `/platform/apps/${appId}/deploy-static`, {
421
+ method: "POST",
422
+ headers: {
423
+ "Content-Type": "application/octet-stream",
424
+ "X-Deploy-Local-Dir": cwd,
425
+ "X-Gencow-Deploy-Claim": deployClaim.header,
426
+ "X-Gencow-Deploy-Protocol": "1",
427
+ "X-Gencow-CLI-Version": deployClaim.claim.generatedBy.version,
428
+ ...(releaseAttemptId
429
+ ? {
430
+ "X-Gencow-Release-Attempt-Id": releaseAttemptId,
431
+ "X-Gencow-Release-Environment": opts.envTarget || "dev",
432
+ }
433
+ : {}),
434
+ },
435
+ body: bundleBuffer,
436
+ }),
437
+ retryDelaysMs: staticDeployRetryDelaysMs,
438
+ delayImpl: staticDeployRetryDelayImpl,
402
439
  });
403
440
  if (deployRes.status === 202) {
404
441
  deployRes = await pollAcceptedDeploymentOperation({
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gencow",
3
- "version": "0.1.220",
3
+ "version": "0.1.222",
4
4
  "description": "Gencow — AI Backend Engine",
5
5
  "type": "module",
6
6
  "bin": {
@@ -34,8 +34,8 @@
34
34
  "@types/node": "^25.9.5",
35
35
  "better-auth": "^1.6.23",
36
36
  "@gencow/client": "0.2.7",
37
- "@gencow/core": "0.1.43",
38
- "@gencow/react": "0.2.7"
37
+ "@gencow/react": "0.2.7",
38
+ "@gencow/core": "0.1.43"
39
39
  },
40
40
  "scripts": {
41
41
  "prebuild": "pnpm --filter @gencow/migration-contract run build && pnpm --filter @gencow/server run build",