Skip to content

Commit 33436ba

Browse files
khaliqgantRicky Schema Cascadeclaude
authored
fix(deploy): existing-persona lookup uses /deployments list (not phantom /agents) (#120)
* fix(deploy): existing-persona lookup uses /deployments list (not phantom /agents) `findExistingAgent` was calling `GET /workspaces/{ws}/agents?persona_slug=<slug>`. That route is a dashboard proxy to an external gateway: it requires session-cookie auth and 403s for the `cli:auth` Bearer tokens the CLI uses. The actual list of deployed personas — the `agents` table reader added in cloud#580 — lives at `GET /workspaces/{ws}/deployments`, accepts `cli:auth`, and returns `{agents:[{agentId, personaId, deployedName, status, ...}]}`. Why no `?personaId=` server-side filter: `agents.personaId` on the cloud schema is a UUID FK to `personas.id`. The CLI only knows the persona's slug (the local persona JSON's `id` field). Sending the slug as `personaId=` makes cloud's drizzle predicate throw on the UUID cast → 500. The list is workspace-scoped (dozens of rows, not thousands), so the right tradeoff is fetching unfiltered and matching client-side against `deployedName` (which cloud derives from `persona.slug || persona.name || persona.id`), `personaSlug`, or `personaId` as a fallback. Changes: * `findExistingAgent` → call `/deployments` (no query string). * `parseAgentLike` accepts both `{agentId}` (new) and `{id}` (legacy preview shape). When `expectedPersonaId` is supplied, match it against any persona-identifying field on the row (deployedName, personaSlug, personaId). Rows with NO persona info at all (legacy preview shape that pre-filtered server-side) still pass through. * Treat `status === 'destroyed'` as "not present" so a re-deploy with the same slug doesn't trip on-exists against a tombstone. * Rewrite test mocks to disambiguate the listing GET from the deploy POST via `init.method` (both now share the same URL). * Added two new tests: full /deployments shape parsing (with tombstone + wrong-persona rows skipped), and ordering guarantee (listing GET fires before deploy POST). Smoke against production cloud with the user's actual Anthropic- connected workspace: no more 403 on the existing-persona check, no more 500 on the personaId filter. Bundle upload now reaches cloud's deploy handler. (Next failure: cloud Lambda missing `@parcel/watcher-linux-x64-glibc` native binary — server packaging issue, separate PR.) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * review fixes: tighten persona-match + prefer newest active row Addressing review findings on PR #120: * Workspace-scoped list rows without persona-identifying fields are no longer treated as matches. The "no persona fields → pass through" fallback was justified by legacy `{agent: {...}}` envelopes where the URL path implied persona-scoping, but cloud's new `/deployments` list is workspace-scoped — a row missing `deployedName`/`personaSlug`/ `personaId` could belong to any persona in the workspace, and acting on it would let on-exists destroy the wrong agent. The legacy envelope keeps its back-compat via a `requirePersonaMatch: false` opt-in; every array element from the new endpoint sets `requirePersonaMatch: true`. * When multiple rows match (destroy+redeploy race window, soft-delete windows), prefer the newest `active` row instead of whichever cloud returns first. Sort by status tier (active first) then `createdAt` descending. Previously the first parsed match won, which on most SQL backends meant insertion order — the opposite of what users expect. Tests: * `workspace-scoped list rows without persona-identifying fields are NOT matched` — proves the tightened filter ignores ambiguous rows. * `multiple active rows for the same persona — newest wins` — proves the newest-active tiebreaker. * `active row wins over an older active and over inactive rows` — proves status tier outranks createdAt. * `malformed array entries (null/empty) are skipped without throwing` — defensive parser regression guard. 101/101 deploy tests pass. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(deploy): use deployments list in cancel fixture --------- Co-authored-by: Ricky Schema Cascade <ricky@agent-relay.com> Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
1 parent 97a800b commit 33436ba

3 files changed

Lines changed: 398 additions & 42 deletions

File tree

0 commit comments

Comments
 (0)