Skip to content

feat: add optional topic param to /api/chat and /api/chat/generate - #192

Merged
sweetmantech merged 2 commits into
testfrom
sweetmantech/myc-4108-api-apichat-and-apigenerate-add-optional-topic-param
Feb 3, 2026
Merged

feat: add optional topic param to /api/chat and /api/chat/generate#192
sweetmantech merged 2 commits into
testfrom
sweetmantech/myc-4108-api-apichat-and-apigenerate-add-optional-topic-param

Conversation

@sweetmantech

@sweetmantechsweetmantech commented Feb 3, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Add optional topic parameter to /api/chat and /api/chat/generate endpoints
  • When provided, uses the given topic for new chat rooms instead of auto-generating from message content
  • Topic is ignored if room already exists (matches docs specification)

Changes

  • lib/chat/validateChatRequest.ts: Add topic to request schema
  • lib/chat/setupConversation.ts: Pass topic through to room creation
  • lib/chat/createNewRoom.ts: Use provided topic or fall back to generated title
  • Route files: Updated JSDoc comments

Test plan

  • Send chat request without topic - should auto-generate title as before
  • Send chat request with topic - should use provided topic
  • Send chat request with topic and existing roomId - topic should be ignored

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Users can now optionally provide a topic when creating new chat rooms. When specified, the topic will be used as the conversation title instead of auto-generating it from the message content.
  • Documentation

    • Updated API documentation across chat endpoints to describe the new optional topic parameter and its behavior.

Add topic parameter to chat request schema. When provided, uses the
given topic for new chat rooms instead of auto-generating one from
the message content. Topic is ignored if room already exists.
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@vercel

vercelBot commented Feb 3, 2026

Copy link
Copy Markdown
Contributor

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

ProjectDeploymentActionsUpdated (UTC)
recoup-apiReadyReadyPreviewFeb 3, 2026 1:45am

@coderabbitai

coderabbitaiBot commented Feb 3, 2026

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

📝 Walkthrough

Walkthrough

An optional topic parameter is added to the chat API, threading through validation and conversation setup layers. When creating a new chat room, the provided topic becomes the conversation title if no message-derived title exists. Documentation is updated in route files.

Changes

Cohort / File(s)Summary
API Documentation
app/api/chat/generate/route.ts, app/api/chat/route.ts
Documentation-only updates describing the optional topic parameter in request body comments.
Chat Infrastructure
lib/chat/validateChatRequest.ts, lib/chat/setupConversation.ts, lib/chat/createNewRoom.ts
Topic parameter threaded through validation schema, conversation setup, and room creation. Title resolution now prefers provided topic over message-derived titles.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

Poem

A topic blooms in chat's design,
Through validation, setup, fine,
Threading softly layer by layer,
Each room now wears a custom prayer,
Where words become the conversation's name. 🎭✨

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sweetmantech/myc-4108-api-apichat-and-apigenerate-add-optional-topic-param

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

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

@github-actions

github-actionsBot commented Feb 3, 2026

Copy link
Copy Markdown

Braintrust eval report

Catalog Opportunity Analysis Evaluation (HEAD-1770083091)

ScoreAverageImprovementsRegressions
Catalog_availability47.6% (+46pp)4 🟢-
Llm_calls0 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration41.08s (+1.57s)3 🟢2 🔴

Catalog Songs Count Evaluation (HEAD-1770083091)

ScoreAverageImprovementsRegressions
Llm_calls4 (+0)--
Tool_calls0 (+0)--
Errors2.67 (+2.67)-3 🔴
Llm_errors0.67 (+0.67)-2 🔴
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration12.85s (-3.29s)3 🟢-

First Week Album Sales Evaluation (HEAD-1770083091)

ScoreAverageImprovementsRegressions
Llm_calls1 (+0)--
Tool_calls0 (+0)--
Errors1 (+1)-4 🔴
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration16.79s (+1.67s)2 🟢2 🔴

Memory & Storage Tools Evaluation (HEAD-1770083091)

ScoreAverageImprovementsRegressions
Tools_called0% (+0pp)--
Llm_calls0 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration16.45s (-1.61s)1 🟢-

Monthly Listeners Tracking Evaluation (HEAD-1770083091)

ScoreAverageImprovementsRegressions
AnswerSimilarity79.1% (+1pp)1 🟢2 🔴
Llm_calls2 (+0)--
Tool_calls0 (+0)--
Errors0.8 (+0.8)-2 🔴
Llm_errors0.4 (+0.4)-2 🔴
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration14.98s (+2.68s)1 🟢4 🔴

Search Web Tool Evaluation (HEAD-1770083091)

ScoreAverageImprovementsRegressions
Llm_calls3 (+0)--
Tool_calls0 (+0)--
Errors1.64 (+1.64)-11 🔴
Llm_errors0.64 (+0.64)-7 🔴
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration24.51s (-0.1s)6 🟢5 🔴

Social Scraping Evaluation (HEAD-1770083091)

ScoreAverageImprovementsRegressions
Tools_called0% (+0pp)--
Llm_calls0 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration25.81s (+0.92s)2 🟢4 🔴

Spotify Followers Evaluation (HEAD-1770083091)

ScoreAverageImprovementsRegressions
Llm_calls3 (+0)--
Tool_calls0 (+0)--
Errors1.8 (+1.8)-5 🔴
Llm_errors0.8 (+0.8)-4 🔴
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration16.52s (+0.59s)3 🟢2 🔴

Spotify Tools Evaluation (HEAD-1770083091)

ScoreAverageImprovementsRegressions
Tools_called0% (+0pp)--
Llm_calls0 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration36.75s (+3.84s)-2 🔴

TikTok Analytics Questions Evaluation (HEAD-1770083091)

ScoreAverageImprovementsRegressions
Question_answered0% (+0pp)--
Llm_calls0 (+0)--
Tool_calls0 (+0)--
Errors0 (+0)--
Llm_errors0 (+0)--
Tool_errors0 (+0)--
Prompt_tokens0tok (+0tok)--
Prompt_cached_tokens0tok (+0tok)--
Prompt_cache_creation_tokens0tok (+0tok)--
Completion_tokens0tok (+0tok)--
Completion_reasoning_tokens0tok (+0tok)--
Total_tokens0tok (+0tok)--
Duration18.01s (+3.71s)-2 🔴

- Test topic is passed through schema validation
- Test topic is passed to setupConversation
- Test topic is passed to createNewRoom when creating new room
- Test topic is ignored when room already exists
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@sweetmantech
sweetmantech merged commit c1eeb0f into testFeb 3, 2026
3 of 5 checks passed
sweetmantech added a commit that referenced this pull request May 7, 2026
Addresses review feedback on PR #522 and the "missing from open-agents"
audit:
User-flagged review comments:
- SRP: extract `buildSource` to lib/sandbox/buildSource.ts
- YAGNI: drop `isNewBranch` from POST /api/sandbox — chat never sets it
(note: docs PR #192 still documents it; will open follow-up docs PR
to drop from sandbox.json)
- SRP: extract `isoToEpochMs` to lib/sandbox/isoToEpochMs.ts
- SRP: extract `buildLifecycle` to lib/sandbox/buildLifecycle.ts
- SRP: extract `isSandboxActive` to lib/sandbox/isSandboxActive.ts
- KISS: rename lib/supabase/sessions/updateSessionSandboxState.ts ->
updateSession.ts, generalize signature to (id, TablesUpdate<"sessions">)
Tier 1 correctness gaps from the open-agents comparison:
1. GitHub URL validation via parseGitHubRepoUrl in
validateCreateSandboxBody — bad URLs now return a clean 400 instead
of falling through to a confusing 502 from the sandbox provider
2. Service GitHub token plumbed into connectSandbox options via new
lib/github/getServiceGithubToken.ts — private repos can now clone
3. snapshot_url + snapshot_created_at cleared on fresh provision so
GET /api/sandbox/status no longer surfaces stale snapshot URLs from
prior runs
TDD red -> green:
- 5 new unit-test files for the extracted helpers (buildSource,
isoToEpochMs, buildLifecycle, isSandboxActive, getServiceGithubToken)
- updateSession.test.ts replaces updateSessionSandboxState.test.ts
- Updated validator + handler tests for the contract changes
(drop isNewBranch, add bad-URL 400 cases, assert githubToken plumbing,
assert snapshot_url/snapshot_created_at: null in update payload)
- Confirmed RED before each implementation
- Suite: 2499 -> 2516 (+17 net new tests), pnpm lint:check clean
Files net delta: -241 / +70 lines (extractions + handler shrinks)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
sweetmantech added a commit that referenced this pull request May 7, 2026
…open-agents (#522)
* feat(sandbox): port POST /api/sandbox + GET /api/sandbox/status from open-agents
Implements the two session-scoped sandbox endpoints required to drive
the chat "loading sandbox..." UX on session entry — matching the
contract documented in recoupable/docs#192 (now merged on main).
POST /api/sandbox provisions or resumes a Sandbox via the abstraction
inlined in #507. When sessionId is supplied, the deterministic
sandboxName ensures resume idempotency and the resolved sandbox state
is persisted onto the session row (sandbox_state, lifecycle_state =
"active", lifecycle_version bumped, sandbox_expires_at,
last_activity_at) so subsequent GET /api/sandbox/status calls report
the sandbox as active.
GET /api/sandbox/status is DB-only — reads the session row, computes
status as "active" when sandbox_state is set and not expired (10s
buffer to match open-agents), otherwise "no_sandbox". hasSnapshot is
true when snapshot_url is set. Mirrors the lifecycle envelope shape
from open-agents so the frontend cutover is byte-identical.
Files follow existing api conventions:
- Route shells in app/api/sandbox/ delegate to handlers in lib/sandbox/
- Auth via validateAuthContext (Privy Bearer or x-api-key)
- Validation via Zod (validateCreateSandboxBody)
- Supabase ops in lib/supabase/sessions/ (one fn per file)
- Error envelope { status: "error", error } matches sessions PRs
TDD red → green:
- 7 new test files added covering validator, helper, Supabase wrapper,
both handlers, and the two route shells
- 30 new tests, all passing (was 2461, now 2491)
- pnpm lint:check clean
Out of scope (deferred to follow-up PRs):
- Org-snapshot lookup / kickBuildOrgSnapshotWorkflow (cold-start opt)
- Skill installation (installSessionGlobalSkills)
- Lifecycle workflow kick (no workflow infra in api yet)
- DELETE /api/sandbox + PUT /api/sandbox/snapshot (no UI callers
identified during the open-agents grep audit)
- /api/sandbox/{extend,activity,reconnect,snapshot} sub-routes — to
follow once these two land and the chat UX is validated
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(sandbox): treat type-stub sandbox_state as no_sandbox in /status
Smoke test against the preview deployment caught a regression that
defeated the entire loading-state UX this PR exists to enable: GET
/api/sandbox/status reported `"active"` immediately after POST
/api/sessions, before any sandbox had been provisioned.
Root cause: POST /api/sessions (PR #515) inserts `sandbox_state` as
the type stub `{ type: "vercel" }`. The previous `isSandboxActive`
check `if (!row.sandbox_state) return false` saw a truthy object and
fell through; with `sandbox_expires_at = null` (no expiry yet), the
function returned true.
Fix: introduce `hasRuntimeSandboxState(state)` that distinguishes the
type stub from real runtime metadata by requiring a non-empty
`sandboxName` (set by `getSessionSandboxName(sessionId)` in POST
/api/sandbox and preserved by the abstraction's `getState()`).
Mirrors open-agents' equivalent helper.
TDD red → green:
- Regression test pinned to the exact production scenario
(sandbox_state = {type:"vercel"}, sandbox_expires_at = null,
lifecycle_state = "provisioning") asserting status=no_sandbox
- Companion test asserting status=active once sandboxName is set
- 6 unit tests for the new helper covering null/undefined, scalars,
type stub, populated state, and empty-string sandboxName edge case
- Confirmed RED before implementing, GREEN after
- Suite: 2491 → 2499 (+8 new tests), pnpm lint:check clean
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(sandbox): SRP/KISS extractions + Tier 1 correctness fixes
Addresses review feedback on PR #522 and the "missing from open-agents"
audit:
User-flagged review comments:
- SRP: extract `buildSource` to lib/sandbox/buildSource.ts
- YAGNI: drop `isNewBranch` from POST /api/sandbox — chat never sets it
(note: docs PR #192 still documents it; will open follow-up docs PR
to drop from sandbox.json)
- SRP: extract `isoToEpochMs` to lib/sandbox/isoToEpochMs.ts
- SRP: extract `buildLifecycle` to lib/sandbox/buildLifecycle.ts
- SRP: extract `isSandboxActive` to lib/sandbox/isSandboxActive.ts
- KISS: rename lib/supabase/sessions/updateSessionSandboxState.ts ->
updateSession.ts, generalize signature to (id, TablesUpdate<"sessions">)
Tier 1 correctness gaps from the open-agents comparison:
1. GitHub URL validation via parseGitHubRepoUrl in
validateCreateSandboxBody — bad URLs now return a clean 400 instead
of falling through to a confusing 502 from the sandbox provider
2. Service GitHub token plumbed into connectSandbox options via new
lib/github/getServiceGithubToken.ts — private repos can now clone
3. snapshot_url + snapshot_created_at cleared on fresh provision so
GET /api/sandbox/status no longer surfaces stale snapshot URLs from
prior runs
TDD red -> green:
- 5 new unit-test files for the extracted helpers (buildSource,
isoToEpochMs, buildLifecycle, isSandboxActive, getServiceGithubToken)
- updateSession.test.ts replaces updateSessionSandboxState.test.ts
- Updated validator + handler tests for the contract changes
(drop isNewBranch, add bad-URL 400 cases, assert githubToken plumbing,
assert snapshot_url/snapshot_created_at: null in update payload)
- Confirmed RED before each implementation
- Suite: 2499 -> 2516 (+17 net new tests), pnpm lint:check clean
Files net delta: -241 / +70 lines (extractions + handler shrinks)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* refactor(sandbox): drop branch from POST /api/sandbox contract
YAGNI/KISS per review feedback — chat always works off the repo's
default branch, so the explicit `branch` input adds no value.
- Drop `branch` from createSandboxBodySchema
- Inline the now-trivial source object in createSandboxHandler
(`{ repo: body.repoUrl }`) and delete `lib/sandbox/buildSource.ts`
+ its test
- Read `currentBranch` for the response from the sandbox handle's
own `currentBranch` property (whatever the SDK actually checked
out), falling back to "main" — no longer derives from a request
field that no longer exists
Tests: TDD red -> green.
- Validator test asserts `branch` is stripped from the body even
if a client still sends it
- Handler test asserts `currentBranch` in the response comes from
`sandbox.currentBranch` (mocked to "release/v2") not from input
- Suite stays at 2516 (-1 from buildSource.test deletion +1 new
currentBranch test)
Pairs with docs PR recoupable/docs#194 (merged) which already
removed `branch` and `isNewBranch` from the published OpenAPI spec.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
sweetmantech added a commit that referenced this pull request May 7, 2026
…open-agents (#522) (#524)
* feat(sandbox): port POST /api/sandbox + GET /api/sandbox/status from open-agents
Implements the two session-scoped sandbox endpoints required to drive
the chat "loading sandbox..." UX on session entry — matching the
contract documented in recoupable/docs#192 (now merged on main).
POST /api/sandbox provisions or resumes a Sandbox via the abstraction
inlined in #507. When sessionId is supplied, the deterministic
sandboxName ensures resume idempotency and the resolved sandbox state
is persisted onto the session row (sandbox_state, lifecycle_state =
"active", lifecycle_version bumped, sandbox_expires_at,
last_activity_at) so subsequent GET /api/sandbox/status calls report
the sandbox as active.
GET /api/sandbox/status is DB-only — reads the session row, computes
status as "active" when sandbox_state is set and not expired (10s
buffer to match open-agents), otherwise "no_sandbox". hasSnapshot is
true when snapshot_url is set. Mirrors the lifecycle envelope shape
from open-agents so the frontend cutover is byte-identical.
Files follow existing api conventions:
- Route shells in app/api/sandbox/ delegate to handlers in lib/sandbox/
- Auth via validateAuthContext (Privy Bearer or x-api-key)
- Validation via Zod (validateCreateSandboxBody)
- Supabase ops in lib/supabase/sessions/ (one fn per file)
- Error envelope { status: "error", error } matches sessions PRs
TDD red → green:
- 7 new test files added covering validator, helper, Supabase wrapper,
both handlers, and the two route shells
- 30 new tests, all passing (was 2461, now 2491)
- pnpm lint:check clean
Out of scope (deferred to follow-up PRs):
- Org-snapshot lookup / kickBuildOrgSnapshotWorkflow (cold-start opt)
- Skill installation (installSessionGlobalSkills)
- Lifecycle workflow kick (no workflow infra in api yet)
- DELETE /api/sandbox + PUT /api/sandbox/snapshot (no UI callers
identified during the open-agents grep audit)
- /api/sandbox/{extend,activity,reconnect,snapshot} sub-routes — to
follow once these two land and the chat UX is validated
* fix(sandbox): treat type-stub sandbox_state as no_sandbox in /status
Smoke test against the preview deployment caught a regression that
defeated the entire loading-state UX this PR exists to enable: GET
/api/sandbox/status reported `"active"` immediately after POST
/api/sessions, before any sandbox had been provisioned.
Root cause: POST /api/sessions (PR #515) inserts `sandbox_state` as
the type stub `{ type: "vercel" }`. The previous `isSandboxActive`
check `if (!row.sandbox_state) return false` saw a truthy object and
fell through; with `sandbox_expires_at = null` (no expiry yet), the
function returned true.
Fix: introduce `hasRuntimeSandboxState(state)` that distinguishes the
type stub from real runtime metadata by requiring a non-empty
`sandboxName` (set by `getSessionSandboxName(sessionId)` in POST
/api/sandbox and preserved by the abstraction's `getState()`).
Mirrors open-agents' equivalent helper.
TDD red → green:
- Regression test pinned to the exact production scenario
(sandbox_state = {type:"vercel"}, sandbox_expires_at = null,
lifecycle_state = "provisioning") asserting status=no_sandbox
- Companion test asserting status=active once sandboxName is set
- 6 unit tests for the new helper covering null/undefined, scalars,
type stub, populated state, and empty-string sandboxName edge case
- Confirmed RED before implementing, GREEN after
- Suite: 2491 → 2499 (+8 new tests), pnpm lint:check clean
* refactor(sandbox): SRP/KISS extractions + Tier 1 correctness fixes
Addresses review feedback on PR #522 and the "missing from open-agents"
audit:
User-flagged review comments:
- SRP: extract `buildSource` to lib/sandbox/buildSource.ts
- YAGNI: drop `isNewBranch` from POST /api/sandbox — chat never sets it
(note: docs PR #192 still documents it; will open follow-up docs PR
to drop from sandbox.json)
- SRP: extract `isoToEpochMs` to lib/sandbox/isoToEpochMs.ts
- SRP: extract `buildLifecycle` to lib/sandbox/buildLifecycle.ts
- SRP: extract `isSandboxActive` to lib/sandbox/isSandboxActive.ts
- KISS: rename lib/supabase/sessions/updateSessionSandboxState.ts ->
updateSession.ts, generalize signature to (id, TablesUpdate<"sessions">)
Tier 1 correctness gaps from the open-agents comparison:
1. GitHub URL validation via parseGitHubRepoUrl in
validateCreateSandboxBody — bad URLs now return a clean 400 instead
of falling through to a confusing 502 from the sandbox provider
2. Service GitHub token plumbed into connectSandbox options via new
lib/github/getServiceGithubToken.ts — private repos can now clone
3. snapshot_url + snapshot_created_at cleared on fresh provision so
GET /api/sandbox/status no longer surfaces stale snapshot URLs from
prior runs
TDD red -> green:
- 5 new unit-test files for the extracted helpers (buildSource,
isoToEpochMs, buildLifecycle, isSandboxActive, getServiceGithubToken)
- updateSession.test.ts replaces updateSessionSandboxState.test.ts
- Updated validator + handler tests for the contract changes
(drop isNewBranch, add bad-URL 400 cases, assert githubToken plumbing,
assert snapshot_url/snapshot_created_at: null in update payload)
- Confirmed RED before each implementation
- Suite: 2499 -> 2516 (+17 net new tests), pnpm lint:check clean
Files net delta: -241 / +70 lines (extractions + handler shrinks)
* refactor(sandbox): drop branch from POST /api/sandbox contract
YAGNI/KISS per review feedback — chat always works off the repo's
default branch, so the explicit `branch` input adds no value.
- Drop `branch` from createSandboxBodySchema
- Inline the now-trivial source object in createSandboxHandler
(`{ repo: body.repoUrl }`) and delete `lib/sandbox/buildSource.ts`
+ its test
- Read `currentBranch` for the response from the sandbox handle's
own `currentBranch` property (whatever the SDK actually checked
out), falling back to "main" — no longer derives from a request
field that no longer exists
Tests: TDD red -> green.
- Validator test asserts `branch` is stripped from the body even
if a client still sends it
- Handler test asserts `currentBranch` in the response comes from
`sandbox.currentBranch` (mocked to "release/v2") not from input
- Suite stays at 2516 (-1 from buildSource.test deletion +1 new
currentBranch test)
Pairs with docs PR recoupable/docs#194 (merged) which already
removed `branch` and `isNewBranch` from the published OpenAPI spec.
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for freeto 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

@sweetmantech