Skip to content

feat(eve): search team-scoped Vercel projects#110

Merged
ruiconti merged 6 commits into
mainfrom
rui/vercel-project-selection
Jun 22, 2026
Merged

feat(eve): search team-scoped Vercel projects#110
ruiconti merged 6 commits into
mainfrom
rui/vercel-project-selection

Conversation

@ruiconti

@ruiconti ruiconti commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

Description

The existing-project picker only saw the first page of vercel project ls, so any project past the first page was unreachable, and nothing recorded which team owned the result. Linking then hand-wrote .vercel/project.json, which could drift from the project the user picked.

This makes discovery team-scoped and fully paginated, and links through vercel link so the on-disk link is whatever Vercel wrote — then verifies it's the project that was selected. Builds on the credential work in #109.

What

  • List and paginate the teams for the current user, and pick the scope (auto when there's only one).
  • Load recent projects in that team, and search the whole team from the picker.
  • Link via vercel link --project, read the link back, and fail if the id doesn't match the selection.
  • Classify Vercel API failures (not-found / conflict / forbidden + SSO) at the setup boundary.
  • Drop a CI link workaround that's no longer needed.

Team scope and search

vercel-project-api.ts wraps teams ls and project ls and drains every page through the --next cursor, bailing if Vercel ever returns a cursor it already gave us. The picker lists recent projects; typing filters them locally and always offers a Search for '<query>' row that runs project ls --filter <query> across the whole team — so a project outside the recent set is reachable even when the local list already has near-matches.

In the dev TUI that search runs in place: the picker stays open with a spinner and swaps in the results, and a slow response from an earlier query can't paint over a newer one. Plain CLI reopens the picker with the new results folded into the list.

Linking

linkProject runs vercel link --project <id> --scope <team> --yes instead of writing .vercel/project.json by hand. The link box reads the link metadata back and throws if the resolved id isn't the one that was picked, so a stale or mismatched .vercel can't win. Re-linking the same identity is a no-op, so the box always re-links to the planned project.

It forces non-interactive on purpose: eve strips the coding-agent env markers, and without them the CLI starts prompting (the plugin/MCP setup question) and reads stdin, which wedges the dev TUI.

API failures

vercel api --raw can exit zero with an error body. vercel-api-failure.ts reads that structured error and classifies it — 404, 409, and 403/SSO each map to the right outcome, so a scoped denial sends you to re-auth instead of surfacing as a generic failure.

Also in here

  • Folded the project-picker module into pickProject — it was a thin wrapper.
  • CI: removed the env -u VERCEL_ORG_ID -u VERCEL_PROJECT_ID wrapper around vc link (a stopgap to force link materialization); plain vc link --project matches the documented e2e flow.
  • Two readability cleanups: searchFilter's nested ternary became an if/else, and the .now rejection in assertNoLegacyProjectLinkDirectory no longer throws through its own catch.

Scope

Discovery, selection, and linking. No startup auth recovery and no Trusted Sources work — those come later in the stack.

Stack

  1. fix(eve): verify remote Vercel credentials #109 — verified remote credentials
  2. feat(eve): search team-scoped Vercel projects #110 — team-scoped project selection (this PR)
  3. feat(eve): add remote client authentication foundation #191 — remote client authentication foundation
  4. feat(eve): add Trusted Sources policy primitives #190 — Trusted Sources policy primitives
  5. feat(eve): recover remote TUI authentication #111 — remote TUI authentication exposure

How did you test your changes?

Unit and integration tests cover pagination and the repeated-cursor guard, team filtering, API-failure classification, project resolution, the read-back identity check, and the picker search in both CLI and TUI. Workspace typecheck, lint, build, and the unit/integration suites pass.

PR Checklist

  • I ran the relevant checks from CONTRIBUTING.md
  • I added tests and documentation where relevant
  • I added a changeset
  • DCO sign-off passes for every commit

@vercel

vercel Bot commented Jun 19, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
eve-docs Ready Ready Preview, Comment, Open in v0 Jun 22, 2026 8:05pm

@github-actions

github-actions Bot commented Jun 22, 2026

Copy link
Copy Markdown
Contributor

Bundle + Package Summary: apps/fixtures/weather-agent

Key takeaways

  • No notable deltas vs main (2057b43).

Delta vs main (2057b43)

Area Metric Baseline Current Delta
Package Packed tarball 3.28 MB 3.29 MB +3.8 kB ⚠️
Package Unpacked publish size 11.84 MB 11.84 MB +8.3 kB ⚠️
Package Installed footprint 52.04 MB 52.05 MB +8.3 kB ⚠️
Package Published files 2231 2235 +4
Package Installed files 5436 5440 +4
Runtime Unique function payloads 2 2 0
Runtime Total function bytes 9.35 MB 9.35 MB -176 B ✅
Runtime Public routes 9 9 0
Changed function payloads vs main (2057b43) (2)
Function Status Baseline Current Delta Route changes
functions/__server.func changed 3.87 MB 3.87 MB -144 B ✅ none
functions/.well-known/workflow/v1/flow.func changed 5.48 MB 5.48 MB -32 B ✅ none
Build Metadata
  • Preset: vercel
  • Nitro: nitro@3.0.260610-beta
  • Output directory: apps/fixtures/weather-agent/.vercel/output
  • Build metadata timestamp: 2026-06-22T20:06:17.969Z
  • Route aliases: 9 public, 1 internal (10 total aliases)
  • Vercel routes in config: 10
  • Severity legend: 🔴 dominant/large, 🟠 notable, 🟡 watch, ⚪ small
Package Drill-Down

Package Details

  • Package: eve@0.12.3
  • Package directory: packages/eve
  • Tarball: 3.29 MB (eve-0.12.3.tgz)
  • Unpacked payload: 11.84 MB across 2235 published files
  • Installed footprint: 52.05 MB across 5440 installed files
  • Installed root package: 10.73 MB
  • Installed dependencies: 41.32 MB
  • Runtime dependencies: 1
  • Peer dependencies: 12 (11 optional)

Installed footprint is measured from an isolated temporary npm install of the packed tarball.

Heavy installed dependencies

  • @rolldown/binding-linux-x64-gnu: 20.61 MB (39.6%)
  • eve: 10.73 MB (20.6%)
  • ai: 6.20 MB (11.9%)
  • zod: 4.97 MB (9.5%)
  • nitro: 2.41 MB (4.6%)
Publish payload breakdown
Published file size
🟠 dist/src/compiled/experimental-ai-sdk-code-mo... [####....................] 1.51 MB 12.7%
🟡 dist/src/compiled/@workflow/core/runtime.js      [##......................] 775.4 kB 6.5%
🟡 dist/src/compiled/@vercel/sandbox/index.js       [##......................] 632.0 kB 5.3%
🟡 dist/src/compiled/@chat-adapter/slack/index.js   [#.......................] 436.9 kB 3.7%
🟡 dist/src/compiled/_chunks/workflow/attribute-... [#.......................] 370.9 kB 3.1%
🔴 Other published files                            [########################] 8.12 MB 68.6%
Installed footprint breakdown
Installed package size
🔴 @rolldown/binding-linux-x64-gnu [########################] 20.61 MB 39.6%
🔴 eve                             [############............] 10.73 MB 20.6%
🔴 ai                              [#######.................] 6.20 MB 11.9%
🟠 zod                             [######..................] 4.97 MB 9.5%
🟠 nitro                           [###.....................] 2.41 MB 4.6%
🟡 rolldown                        [#.......................] 771.0 kB 1.5%
🔴 Other installed packages        [#######.................] 6.37 MB 12.2%
Runtime dependencies (1)
Package Range Notes
nitro 3.0.260610-beta
Peer dependencies (12)
Package Range Notes
@opentelemetry/api ^1.0.0 optional peer
@sveltejs/kit ^2.0.0 optional peer
ai catalog:
braintrust ^3.0.0 optional peer
just-bash ^3.0.0 optional peer
microsandbox ^0.5.0 optional peer
next ^16.0.0 optional peer
nuxt ^4.0.0 optional peer
react ^19.0.0 optional peer
svelte ^5.0.0 optional peer
vite ^8.0.0 optional peer
vue ^3.5.0 optional peer
Function Drill-Down

Payload Size Graph

Unique function payload size and share of total
🔴 functions/.well-known/workflow/v1/flow.func     [########################] 5.48 MB 58.6%
🔴 functions/__server.func                         [#################.......] 3.87 MB 41.4%

Top Function Payloads

🟠 functions/.well-known/workflow/v1/flow.func • 1 public route • 5.48 MB
Metric Value
Public routes /.well-known/workflow/v1/flow
Runtime nodejs24.x
Handler index.mjs
Payload 5.48 MB
Function files 5.48 MB across 27 files
Traced dependencies 0 B
Signal 🟠 Bundled file __eve_nitro_handler__.mjs is 1.51 MB (27.6%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 __eve_nitro_handler__.mjs              [########################] 1.51 MB 27.6%
🟠 _chunks/runtime.mjs                    [###############.........] 958.4 kB 17.5%
🟡 _chunks/sandbox.mjs                    [############............] 766.0 kB 14.0%
🟡 _chunks/attribute-changes-Bi5DLT8S.mjs [########................] 472.2 kB 8.6%
🟡 _chunks/dist-DTchiX0N.mjs              [#######.................] 460.6 kB 8.4%
🟠 Other bundled files                    [#####################...] 1.31 MB 23.9%

🧾 Vercel Config

{
  "handler": "index.mjs",
  "launcherType": "Nodejs",
  "shouldAddHelpers": false,
  "supportsResponseStreaming": true,
  "runtime": "nodejs24.x",
  "environment": {
    "NODE_OPTIONS": "--experimental-require-module",
    "WORKFLOW_QUEUE_NAMESPACE": "eve"
  },
  "maxDuration": "max",
  "experimentalTriggers": [
    {
      "type": "queue/v2beta",
      "topic": "__eve_wkf_workflow_*",
      "consumer": "default",
      "retryAfterSeconds": 5,
      "initialDelaySeconds": 0
    }
  ]
}

🟠 functions/__server.func • 8 public routes, 1 internal alias • 3.87 MB
Metric Value
Public routes /
/eve/v1/callback/[token]
/eve/v1/connections/[name]/callback/[token]
/eve/v1/health
/eve/v1/info
/eve/v1/session
/eve/v1/session/[sessionId]
/eve/v1/session/[sessionId]/stream
Internal aliases /__server
Runtime nodejs24.x
Handler index.mjs
Payload 3.87 MB
Function files 3.87 MB across 21 files
Traced dependencies 0 B
Signal 🟠 Bundled file index.mjs is 1.40 MB (36.3%)

🟠 🔎 Dependency Analysis

📦 Bundled files:

Bundled file size
🟠 index.mjs                              [########################] 1.40 MB 36.3%
🟠 _chunks/runtime.mjs                    [###############.........] 875.8 kB 22.6%
🟠 _chunks/sandbox.mjs                    [#############...........] 766.0 kB 19.8%
🟡 _chunks/attribute-changes-Bi5DLT8S.mjs [########................] 448.5 kB 11.6%
⚪ _libs/zod.mjs                          [##......................] 114.2 kB 3.0%
🟡 Other bundled files                    [####....................] 258.8 kB 6.7%

🧾 Vercel Config

{
  "handler": "index.mjs",
  "launcherType": "Nodejs",
  "shouldAddHelpers": false,
  "supportsResponseStreaming": true,
  "runtime": "nodejs24.x"
}

ruiconti and others added 2 commits June 22, 2026 15:23
…ntity

Search every Vercel project in the selected team from the picker —
paginated and team-scoped — instead of only the ~20 most recent, and
let the user trigger a full-team search when the local filter has no
match.

Link via `vercel link` rather than hand-writing .vercel/project.json,
carry the selected project identity through linking, and assert the
read-back link metadata matches the chosen project so a stale or
mismatched link can't silently win. Materialize Vercel project links in
CI e2e.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Rui Conti <ruiconti@gmail.com>
Inline pickExistingVercelProject into pickProject and drop the
vercel-project-picker module; move its tests into vercel-project.test.ts.
Adapted onto the modular rebase: VercelProjectListEntry is exported from
vercel-project-api, and the test capture helper accepts objects.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Rui Conti <ruiconti@gmail.com>
ruiconti added 2 commits June 22, 2026 15:55
Move the unsupported-`.now` rejection out of the try so it is no longer
thrown into and rethrown out of the catch. Behavior is unchanged: a
missing `.now` (ENOENT) and a non-directory `.now` still pass; a `.now`
directory still throws.

Signed-off-by: Rui Conti <ruiconti@gmail.com>
Same rendered output (filter text plus caret, or the dim placeholder, plus
an optional loading frame); the explicit branches read more clearly than
the nested conditional.

Signed-off-by: Rui Conti <ruiconti@gmail.com>
Reverts the `env -u VERCEL_ORG_ID -u VERCEL_PROJECT_ID` wrapper around
`vc link` in the Vercel e2e job (added in 3e008e2), restoring the plain
`vc link --project` invocation that matches the documented e2e flow in
AGENTS.md. The unset was a stopgap to force link materialization and is
not needed.

Signed-off-by: Rui Conti <ruiconti@gmail.com>
@ruiconti ruiconti marked this pull request as ready for review June 22, 2026 20:04
@ruiconti ruiconti requested a review from AndrewBarba June 22, 2026 20:10
@ruiconti ruiconti enabled auto-merge (squash) June 22, 2026 20:17
@ruiconti ruiconti merged commit f00ca73 into main Jun 22, 2026
57 of 59 checks passed
@ruiconti ruiconti deleted the rui/vercel-project-selection branch June 22, 2026 20:54
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.

2 participants