Skip to content

fix(cli): canonicalize cloud URL and rewrite agent-relay error hints#117

Merged
khaliqgant merged 1 commit into
mainfrom
fix/cli-canonicalize-cloud-url-and-error-text
May 13, 2026
Merged

fix(cli): canonicalize cloud URL and rewrite agent-relay error hints#117
khaliqgant merged 1 commit into
mainfrom
fix/cli-canonicalize-cloud-url-and-error-text

Conversation

@khaliqgant
Copy link
Copy Markdown
Member

Summary

The first customer (proactive-agents) hit two stacked deploy-time bugs:

! failed to check connection status for notion: fetch failed
x integrations.notion: connect failed: cloud integration request failed: unauthorized.
  Open https://origin.agentrelay.cloud/cloud to verify your cloud session, then run
  \`agent-relay cloud whoami\` and \`agentworkforce login\` to refresh the active workspace.

Bug A — error messages tell `agentworkforce` users to run `agent-relay` commands they don't have. Rewritten across `connect.ts` / `deploy-command.ts` (help / usage strings) so users are only ever pointed at `agentworkforce login --workspace `. `origin.agentrelay.cloud` hardcoded URL stripped from the hint.

Bug B — `ensureAuthenticated` occasionally returns `auth.apiUrl` pointing at the SST edge-bypass hostname (`origin.agentrelay.cloud`). Persisting that into `active.json` sends every subsequent API call cross-subdomain where session cookies and Bearer tokens don't validate, so every call 401s. CLI-side mitigation: `canonicalizeCloudUrl()` maps known-bypass hostnames (`origin.`, `.agentrelay.cloud`) → `https://agentrelay.com/cloud\` and is applied at every CLI write/consume site for the cloud URL.

The proper structural fix is cloud-side (handler should emit a configured public URL, never `request.url`). Tracking issue: AgentWorkforce/cloud#TBD.

Test plan

  • `canonicalizeCloudUrl` unit table (10 cases incl. origin., staging., idempotent canonical, trailing-slash, localhost passthrough, unrelated-tenant passthrough)
  • `runLogin` test asserting `ensureAuthenticated` returning `apiUrl: 'https://origin.agentrelay.cloud'\` causes `writeActiveWorkspace` to be called with the canonical URL
  • `relayfileIntegrationResolver` 401 test using a regex assert (`/agentworkforce login/i`) and a negative assert that the message does NOT contain `agent-relay cloud` or `origin.agentrelay.cloud`
  • `corepack pnpm -r build` + `pnpm typecheck` + `pnpm lint` clean
  • `@agentworkforce/deploy test`: 72/72 pass (was 61)
  • `@agentworkforce/cli test`: 193/193 pass (was 192)

Sites where canonicalizeCloudUrl is now called

  • `packages/cli/src/deploy-command.ts` `runLogin` — once on the user-supplied / env-derived cloud URL before `ensureAuthenticated`, and once on `auth.apiUrl` before `writeActiveWorkspace`
  • `packages/deploy/src/login.ts` `writeActiveWorkspace` — write-time defensive canonicalization
  • `packages/deploy/src/login.ts` `resolveWorkspaceToken` — incoming `args.cloudUrl` so `cloudUrlMatches` compares the canonical form

Error-message rewrites

File Before After
`packages/deploy/src/connect.ts:321` 401 "Open https://origin.agentrelay.cloud/cloud … run `agent-relay cloud whoami` and `agentworkforce login`" "Your active workspace session is invalid or expired. Run `agentworkforce login --workspace ` to refresh, then retry."
`packages/deploy/src/connect.ts:326` 403 similar w/ origin.* + `agent-relay cloud whoami` "Run `agentworkforce login --workspace ` against an account with access, then retry."
`packages/cli/src/deploy-command.ts:145` no-workspaces "Create one at https://agentrelay.cloud" "Create one at https://agentrelay.com/cloud"
`packages/cli/src/deploy-command.ts:454` 403 list "check that your account has access to a workspace at https://agentrelay.cloud" "… at https://agentrelay.com/cloud"
`packages/cli/src/deploy-command.ts` LOGIN_USAGE "Reuses the shared Agent Relay Cloud login (~/.agent-relay/cloud-auth.json)…" "Opens the browser to sign in to the workforce cloud and stores a small pointer at ~/.agentworkforce/active.json …"
`packages/cli/src/deploy-command.ts` LOGOUT_USAGE "Agent Relay Cloud browser auth is shared with agent-relay and is preserved unless …" "The shared cloud browser auth is preserved unless …"

🤖 Generated with Claude Code

The customer hit two stacked CLI bugs in one deploy:

- ensureAuthenticated occasionally returns auth.apiUrl pointing at the
  SST edge-bypass hostname (origin.agentrelay.cloud). Persisting that
  into active.json sends every subsequent API call cross-subdomain,
  where session cookies and Bearer tokens don't validate, so every
  call 401s.
- The 401 hint then told `agentworkforce` users to run `agent-relay
  cloud whoami` / `agent-relay cloud login`, which they don't have.

Add canonicalizeCloudUrl() and apply it at every CLI write/consume
site for the cloud URL (login --cloud-url, ensureAuthenticated result,
writeActiveWorkspace, resolveWorkspaceToken). Known-bypass hostnames
(origin.*, *.agentrelay.cloud) remap to https://agentrelay.com/cloud;
localhost and unrelated tenants pass through untouched.

Rewrite the 401 / 403 error strings in relayfileIntegrationResolver
so they point at `agentworkforce login` instead of `agent-relay cloud
whoami`, and drop the hardcoded origin.agentrelay.cloud URL from the
hint text. Same sweep across help / usage strings.

Tests cover the canonicalization table, the login-time canonicalization
end-to-end (origin.* apiUrl -> public canonical written), and a
relayfileIntegrationResolver 401 surfacing the new agentworkforce-native
hint (regex match so future copy-edits don't break it).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 13, 2026

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e355b2e0-d894-453b-b00f-a1bf72b5bfeb

📥 Commits

Reviewing files that changed from the base of the PR and between 8d98804 and 322ffdd.

📒 Files selected for processing (8)
  • packages/cli/src/deploy-command.test.ts
  • packages/cli/src/deploy-command.ts
  • packages/deploy/src/cloud-url.test.ts
  • packages/deploy/src/cloud-url.ts
  • packages/deploy/src/connect.test.ts
  • packages/deploy/src/connect.ts
  • packages/deploy/src/index.ts
  • packages/deploy/src/login.ts

📝 Walkthrough

Walkthrough

This PR introduces cloud URL canonicalization to normalize *.agentrelay.cloud hostnames to the canonical https://agentrelay.com/cloud across the CLI login flow, workspace pointer persistence, and token resolution; updates all related error messages and help text to reference the canonical endpoint and agentworkforce login command.

Changes

Cloud URL Canonicalization

Layer / File(s) Summary
Cloud URL canonicalization function and tests
packages/deploy/src/cloud-url.ts, packages/deploy/src/cloud-url.test.ts, packages/deploy/src/index.ts
Introduces canonicalizeCloudUrl(input: string): string that remaps agentrelay.cloud family hostnames to https://agentrelay.com/cloud, strips trailing slashes for stable comparisons, and leaves other hostnames unchanged; comprehensive test coverage validates canonicalization patterns, idempotence, localhost preservation, and malformed input handling; function is exported from the public deploy module API.
CLI login flow canonicalization
packages/cli/src/deploy-command.ts, packages/cli/src/deploy-command.test.ts
Integrates canonicalizeCloudUrl into runLogin to normalize both the initial cloud URL and the apiUrl returned by ensureAuthenticated, ensuring the active workspace pointer is persisted with a canonical URL; new test verifies origin.agentrelay.cloud is canonicalized to https://agentrelay.com/cloud before active.json is written.
Active workspace pointer canonicalization
packages/deploy/src/login.ts
Applies canonicalizeCloudUrl in writeActiveWorkspace() to normalize cloudUrl at persist time and in resolveWorkspaceToken() to canonicalize the incoming cloud URL prior to credential resolution, ensuring workspace-token selection and cloudUrlMatches comparisons operate against canonical hostnames.
Error messages and help text updates
packages/deploy/src/connect.ts, packages/deploy/src/connect.test.ts, packages/cli/src/deploy-command.ts
Updates HTTP 401/403 error messages in requestJson to direct users to agentworkforce login --workspace <id-or-slug> instead of deprecated guidance; revises CLI help text for agentworkforce login and agentworkforce logout to describe workspace pointer management; updates workspace-access error messages to reference https://agentrelay.com/cloud; test expectations verify new messages exclude deprecated hostname and tool references.

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly Related PRs

  • AgentWorkforce/workforce#113: Updates the CLI login flow and writeActiveWorkspace in deploy-command.ts to change the overall active workspace pointer storage mechanism.
  • AgentWorkforce/workforce#106: Corrects CLI terminology (workforceagentworkforce) in the same help text and user-facing message areas modified here.
  • AgentWorkforce/workforce#115: Updates HTTP 401/403 authentication error handling in packages/deploy/src/connect.ts and connect.test.ts with revised user guidance.

Poem

🐰 A rabbit hops through tangled URLs,
Canonicalizing each wayward swirl—
From origin.cloud to the standard form,
Workspace pointers now perfectly warm.
Credentials resolved on the straightest path,
No more confusion in the auth-check wrath! 🌙

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the two main changes: canonicalizing cloud URLs and rewriting error messages to remove agent-relay references.
Description check ✅ Passed The description is comprehensive and directly related to the changeset, detailing both bugs fixed, the solution approach, test coverage, and specific file/site modifications.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/cli-canonicalize-cloud-url-and-error-text

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown
Contributor

@devin-ai-integration devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no potential bugs to report.

View in Devin Review to see 4 additional findings.

Open in Devin Review

@khaliqgant khaliqgant merged commit a0610cc into main May 13, 2026
3 checks passed
@khaliqgant khaliqgant deleted the fix/cli-canonicalize-cloud-url-and-error-text branch May 13, 2026 17:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant