diff --git a/packages/deploy/src/cloud-url.test.ts b/packages/deploy/src/cloud-url.test.ts index 591162b0..9eaf7bfd 100644 --- a/packages/deploy/src/cloud-url.test.ts +++ b/packages/deploy/src/cloud-url.test.ts @@ -16,10 +16,32 @@ test('canonicalizeCloudUrl: origin.agentrelay.cloud/cloud → public canonical', ); }); -test('canonicalizeCloudUrl: staging.agentrelay.cloud → public canonical', () => { +test('canonicalizeCloudUrl: staging.agentrelay.cloud is preserved for staging deploys', () => { assert.equal( canonicalizeCloudUrl('https://staging.agentrelay.cloud'), - 'https://agentrelay.com/cloud' + 'https://staging.agentrelay.cloud/cloud' + ); + assert.equal( + canonicalizeCloudUrl('https://staging.agentrelay.cloud/cloud'), + 'https://staging.agentrelay.cloud/cloud' + ); + assert.equal( + canonicalizeCloudUrl('https://staging.agentrelay.cloud/cloud/'), + 'https://staging.agentrelay.cloud/cloud' + ); +}); + +test('canonicalizeCloudUrl: origin preview host → public canonical', () => { + assert.equal( + canonicalizeCloudUrl('https://origin-preview-pr-113.agentrelay.cloud/cloud'), + 'https://preview-pr-113.agentrelay.cloud/cloud' + ); +}); + +test('canonicalizeCloudUrl: preview public host gets cloud base path', () => { + assert.equal( + canonicalizeCloudUrl('https://preview-pr-113.agentrelay.cloud'), + 'https://preview-pr-113.agentrelay.cloud/cloud' ); }); diff --git a/packages/deploy/src/cloud-url.ts b/packages/deploy/src/cloud-url.ts index 93e3408b..c8a6759f 100644 --- a/packages/deploy/src/cloud-url.ts +++ b/packages/deploy/src/cloud-url.ts @@ -17,8 +17,12 @@ import type { ActiveWorkspacePointer } from './login.js'; * (the handler should emit a configured public URL, never `request.url`). * * Rules: - * - Map known-bypass hostnames (`origin.agentrelay.cloud`, - * `*.agentrelay.cloud`) → canonical `https://agentrelay.com/cloud`. + * - Map known-bypass hostnames back to their public cloud host: + * `origin.agentrelay.cloud` → `https://agentrelay.com/cloud` and + * `origin-.agentrelay.cloud` → `https://.agentrelay.cloud/cloud`. + * - Preserve stage-labeled public hosts such as `staging.agentrelay.cloud` + * so explicit staging deploys do not silently talk to production. + * - Add the `/cloud` base path for bare stage-labeled public hosts. * - Map the apex `agentrelay.com` (no `/cloud` basePath) → canonical * `https://agentrelay.com/cloud` so callers that hardcoded the apex * don't land on the Next.js marketing 404 page. @@ -40,9 +44,18 @@ export function canonicalizeCloudUrl(input: string): string { return trimmed; } const host = url.hostname.toLowerCase(); - if (host === 'agentrelay.cloud' || host.endsWith('.agentrelay.cloud')) { + if (host === 'agentrelay.cloud' || host === 'origin.agentrelay.cloud') { return 'https://agentrelay.com/cloud'; } + if (host.startsWith('origin-') && host.endsWith('.agentrelay.cloud')) { + return `https://${host.slice('origin-'.length)}/cloud`; + } + if ( + host.endsWith('.agentrelay.cloud') && + (url.pathname === '' || url.pathname === '/') + ) { + return `https://${host}/cloud`; + } if ( host === 'agentrelay.com' && (url.pathname === '' || url.pathname === '/') diff --git a/packages/deploy/test/e2e/weekly-digest.smoke.test.ts b/packages/deploy/test/e2e/weekly-digest.smoke.test.ts index ef9dc3dc..4493b1c6 100644 --- a/packages/deploy/test/e2e/weekly-digest.smoke.test.ts +++ b/packages/deploy/test/e2e/weekly-digest.smoke.test.ts @@ -5,7 +5,7 @@ import path from 'node:path'; import test from 'node:test'; import { pathToFileURL } from 'node:url'; -const DEFAULT_STAGING_URL = 'https://staging.agentrelay.com'; +const DEFAULT_STAGING_URL = 'https://staging.agentrelay.cloud/cloud'; const FIXTURE_REPO = envValue('WORKFORCE_E2E_FIXTURE_REPO') ?? 'AgentWorkforce/deploy-e2e-fixtures'; const ISSUE_TITLE_RE = /^Weekly digest\s+—\s+/u; const POLL_TIMEOUT_MS = 90_000;