Skip to content

promote: test → main (GET /api/ai/models)#498

Merged
sweetmantech merged 3 commits into
mainfrom
test
Apr 30, 2026
Merged

promote: test → main (GET /api/ai/models)#498
sweetmantech merged 3 commits into
mainfrom
test

Conversation

@sweetmantech
Copy link
Copy Markdown
Contributor

Promotes #491 (GET /api/ai/models migration) from `test` to `main`.

New content vs main

(The other commits showing on the diff — `7d4611c` and `d74037b` — are the already-promoted #493 and the test-from-main sync merge; their tree content is already on main via squash commit `bea4d3e5`.)

Verification

PR #491 was manually verified end-to-end on its preview deployment — see #491 (comment) for the full test results: 6/6 cases pass, 194 model ids identical to chat prod, response shape matches the documented contract at developers.recoupable.com/api-reference/ai/models exactly.

Notes

The api uses `@ai-sdk/gateway 2.0.83`; chat uses `^3.0.96`. The newer 3.x adds a `tags` field per model that api doesn't return. Not consumed by any chat code path (verified). Optional follow-up to bump api's gateway if exact byte-parity is desired.

ahmednahima0-beep and others added 3 commits April 30, 2026 14:15
* chore: update Prettier configuration and add new dependencies

- Added "endOfLine": "lf" to the Prettier configuration for consistent line endings.
- Introduced "stripe" and "uuid" packages in package.json for enhanced functionality.
- Updated pnpm-lock.yaml to reflect the addition of new dependencies.

* refactor(stripe): rename mapToSubscriptionSessionErrorResponse to mapToSubscriptionSessionError

- Updated the function name from `mapToSubscriptionSessionErrorResponse` to `mapToSubscriptionSessionError` for consistency and clarity.
- Adjusted import statements and references in related files to reflect the new function name.

* fix(tests): update ACCOUNT UUID in route.test.ts for consistency

- Changed the ACCOUNT constant in route.test.ts from "123e4567-e89b-12d3-a456-426614174000" to "123e4567-e89b-12d3-a456-426614174001" to ensure consistency in test cases.

* feat(stripe): add STRIPE_SK environment variable and improve error handling

- Introduced the STRIPE_SK environment variable in .env.example to ensure proper configuration for Stripe integration.
- Updated the Stripe client initialization to throw an error if STRIPE_SK is not set, enhancing robustness.
- Modified error handling in createSubscriptionSessionHandler to return a 500 status with a generic error message for internal server errors.
- Adjusted validation logic in validateCreateSubscriptionSessionRequest to remove the optional accountId field, simplifying the request structure.
- Enhanced mapToSubscriptionSessionError to mask upstream error messages for 5xx responses, improving security.
- Updated tests to reflect changes in error handling and validation logic.

* fix(connectors): unify action catalog and execution paths for consistent access

- Merged shared and artist toolkits into the actions catalog to ensure all executable actions are listed, reflecting the full access available to the chat agent.
- Updated the executeConnectorAction function to also utilize the merged toolkit, ensuring that all actions listed in the catalog are executable.
- Extracted ConnectorActionNotFoundError into a separate file for cleaner error handling and improved test organization.
- Rewritten tests to mock the new toolkit structure, ensuring comprehensive coverage of the updated functionality.

* feat(stripe): refactor createStripeSession to use configuration constants

- Updated createStripeSession to utilize STRIPE_SUBSCRIPTION_PRICE_ID and STRIPE_SUBSCRIPTION_TRIAL_PERIOD_DAYS constants for better maintainability and configuration management.
- Enhanced tests for createStripeSession to reflect these changes, ensuring consistency in the subscription parameters.
- Improved error handling in client tests by refining the management of the STRIPE_SK environment variable.

* chore: remove .gitattributes and update Prettier configuration

- Deleted the .gitattributes file to simplify project configuration.
- Updated .prettierrc by removing the "endOfLine" setting for cleaner formatting consistency.

* chore(stripe): drop uuid dep, use accountId as client_reference_id

YAGNI: client_reference_id is a soft-convenience pointer string with no
readers in either api or chat — never round-trips, never queried via the
sessions.list API (it isn't a filterable param). The migration was
generating a throwaway random uuid that mapped to nothing internally.

Setting it to accountId instead:
- removes the uuid dep entirely (only callsite in this repo)
- makes the Stripe dashboard's "Client reference" column actually
  useful for support/debugging
- matches metadata.accountId so reconciliation is consistent

Drop the uuid mock from createStripeSession.test.ts and flip the
not.toBe("acc-1") assertion to toBe("acc-1") — encoding the new
contract instead of the old "value must be a random UUID" stance.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Sweets Sweetman <sweetmantech@gmail.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* feat(api): migrate misc-reads endpoints (email, ai/models, youtube/channel-info)

Adds api parity for chat's /api/email, /api/ai/models, /api/youtube/channel-info
ahead of the chat-side cutover.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(api): address AI review on misc-reads PR

- updateContact: switch to loops v6 object-arg signature (fixes Vercel build)
- handlers: stop leaking raw exception text in 500 responses
- loopsClient: convert singleton to factory function matching filename
- youtubeErrors: align export name with filename
- getYouTubeChannelHandler: explicit boolean discriminator narrowing for build

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(api): change /api/email from GET to POST

Email tracking upserts a Loops contact — a write — so it should not be
exposed as GET with email in query params (PII in URLs, cacheable
responses). Switches to POST with `{ email }` JSON body.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* revert(api): drop /api/email endpoint

Loops is no longer used; the email tracking endpoint is removed
from this migration entirely.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(api): simplify youtube channel-info flow

- Fold token validation into validateYouTubeChannelInfoRequest so the
  handler is a thin fetch+respond orchestrator
- Rename validateYouTubeChannelQuery → validateYouTubeChannelInfoRequest
  (matches validateArtistRequest / validateChatRequest convention)
- Drop buildYouTubeUtilityError + error code catalog: every token-level
  failure collapses to the same {success:false, tokenStatus:"invalid"}
  response, so the typed codes carried no information out

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(api): throw from youtube libs, single catch at validator

- refreshStoredYouTubeToken now throws on every failure (no more
  catch-log-return-null); the deep invalid_grant type guard is gone
  since the general console.error already logs the full error
- validateYouTubeTokens lets errors propagate; null is reserved for
  the legitimate "no tokens row / no refresh_token" cases
- validateYouTubeChannelInfoRequest is the single catch boundary;
  thrown errors and null both collapse to the same tokenStatus:invalid
  response, matching chat parity

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(api): drop redundant explicit return types from misc-reads libs

TS inference already produces the same types for these helpers; explicit
annotations were noise. Kept annotations on discriminated-union returns
(validators, route handlers) and anywhere inference would widen.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(api): drop more redundant return types from misc-reads libs

Continues 7f64027 — TS inference produces the same types for these
helpers; explicit annotations were noise. Kept the discriminated-union
annotation on validateYouTubeChannelInfoRequest where it documents an
intentional contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(api): slim youtube channel-info response and validator

- drop response fields that no chat consumer reads
- validateYouTubeTokens throws on every unusable case; the request
  validator's catch is the single failure boundary (no more let/null)
- drop now-unnecessary explicit return types

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(api): trim youtube tests, jsdocs, type duplication, response

- Drop `success` from /api/youtube/channel-info; conform to the
  `{ status: "success", channels }` envelope used across the rest of
  the api (lib/networking/successResponse.ts, songs, posts, accounts,
  chats, artists). Clients infer "needs re-auth" from
  `channels === null`.
- Keep only validator + handler tests; cover no-token, expired-no-refresh,
  refresh-failure, and db-update-failure cases at the validator boundary
  via it.each on the thrown-error contract.
- Trim jsdocs to information-bearing lines only; drop stale
  "mirrors chat" notes and self-evident @param/@returns lines on lib
  helpers.
- Dedupe YouTubeTokensRow: keep the export in validateYouTubeTokens.ts
  (the contract owner) and import it in refreshStoredYouTubeToken.ts.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(api): return proper status codes for youtube channel-info errors

- 401 + {status:"error",message} when stored YouTube tokens can't be
  validated/refreshed (re-auth needed)
- 502 + {status:"error",message} for upstream YouTube API failures
- Drops the inconsistent "200 status:success channels:null" shape

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(api): drop YouTubeTokensRow alias and return type

validateYouTubeTokens lets TS infer the return type; the alias is gone
(only refreshStoredYouTubeToken used it, now inlined as Tables<>).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(api): bypass @ai-sdk/gateway SDK for model catalog

The SDK's getAvailableModels() rejects valid responses with a Zod error
("expected error.object"), which silenced 194 models behind an empty
array. Match chat's direct fetch to /v1/ai/config — same approach,
same payload, same parity.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* fix(api): pin @ai-sdk/gateway to 2.x for catalog reads

The 3.x SDK requires specificationVersion:"v3" via a strict Zod literal,
but the live /v1/ai/config endpoint still emits "v2" descriptors. Pin
to 2.0.83 (latest 2.x, expects "v2") so gateway.getAvailableModels()
works as designed. This is a catalog-read-only consumer; api never uses
gateway() as a model factory, so 2.x's LanguageModelV2 surface doesn't
collide with the rest of the codebase on @ai-sdk/provider@3.

Restore the SDK call site (no more direct fetch hack); a comment
flags when to bump back to 3.x.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(api): drop redundant jsdoc on getAvailableModels

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* refactor(api): restore original jsdoc on getAvailableModels

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* feat(api): gate /api/youtube/channel-info behind auth + artist access

Layers in validateAuthContext + checkAccountArtistAccess so anonymous
callers can no longer probe stored YouTube tokens by guessing UUIDs.
Returns 401 on missing/invalid auth, 403 when the authed caller has no
access to the requested artist.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

* revert(api): drop /api/youtube/channel-info from this migration

YouTube channel-info will migrate via Composio in a separate PR.
Reduces Group 1 scope to just /api/ai/models.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-authored-by: Sweets Sweetman <sweetmantech@gmail.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 30, 2026

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

Project Deployment Actions Updated (UTC)
api Ready Ready Preview Apr 30, 2026 7:40pm

Request Review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 30, 2026

Warning

Rate limit exceeded

@sweetmantech has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 22 minutes and 26 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: c7ae0857-c375-46cd-ba13-884b418c80b6

📥 Commits

Reviewing files that changed from the base of the PR and between bea4d3e and 8774759.

⛔ Files ignored due to path filters (4)
  • lib/ai/__tests__/getAvailableModels.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • lib/ai/__tests__/getAvailableModelsHandler.test.ts is excluded by !**/*.test.*, !**/__tests__/** and included by lib/**
  • package.json is excluded by none and included by none
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml and included by none
📒 Files selected for processing (3)
  • app/api/ai/models/route.ts
  • lib/ai/getAvailableModels.ts
  • lib/ai/getAvailableModelsHandler.ts
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share
Review rate limit: 0/1 reviews remaining, refill in 22 minutes and 26 seconds.

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

@sweetmantech sweetmantech merged commit d3e049d into main Apr 30, 2026
7 checks passed
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.

3 participants