Skip to content

feat: update POST /api/sandboxes to use command execution#195

Merged
sweetmantech merged 13 commits intotestfrom
sweetmantech/myc-4124-api-filetree-update-route-post-appapisandboxesroutets
Feb 3, 2026
Merged

feat: update POST /api/sandboxes to use command execution#195
sweetmantech merged 13 commits intotestfrom
sweetmantech/myc-4124-api-filetree-update-route-post-appapisandboxesroutets

Conversation

@sweetmantech
Copy link
Contributor

@sweetmantech sweetmantech commented Feb 3, 2026

Summary

  • Change request body from { prompt } to { command, args?, cwd? }
  • Add account snapshot support for creating sandboxes from snapshots
  • Update trigger payload to include command, args, cwd, sandboxId, accountId
  • Return runId in response from triggered task
  • Add selectAccountSnapshot function for retrieving account snapshots

Test plan

  • All sandbox tests pass (pnpm test lib/sandbox/)
  • Manual test: POST /api/sandboxes with { command: "ls", args: ["-la"] }
  • Verify response includes runId field

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Sandboxes can now be created from account snapshots when available.
    • Command execution now supports optional arguments and working directory specification.
    • Command runs now return a unique run identifier for tracking.
  • API Changes

    • Sandbox creation parameters updated to use command instead of prompt.

vercel bot and others added 2 commits February 3, 2026 09:34
Updated dependencies to fix Next.js and React CVE vulnerabilities.

The fix-react2shell-next tool automatically updated the following packages to their secure versions:
- next
- react-server-dom-webpack
- react-server-dom-parcel  
- react-server-dom-turbopack

All package.json files have been scanned and vulnerable versions have been patched to the correct fixed versions based on the official React advisory.

Co-authored-by: Vercel <vercel[bot]@users.noreply.github.com>
- Change request body from { prompt } to { command, args?, cwd? }
- Add account snapshot support for creating sandboxes from snapshots
- Update trigger payload to include command, args, cwd, sandboxId, accountId
- Return runId in response from triggered task
- Update tests to reflect new API structure

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@vercel
Copy link
Contributor

vercel bot commented Feb 3, 2026

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

Project Deployment Actions Updated (UTC)
recoup-api Ready Ready Preview Feb 3, 2026 9:31pm

@github-actions
Copy link

github-actions bot commented Feb 3, 2026

Braintrust eval report

Catalog Opportunity Analysis Evaluation (HEAD-1770154219)

Score Average Improvements Regressions
Catalog_availability 24% (+21pp) 3 🟢 1 🔴
Llm_calls 0 (+0) - -
Tool_calls 0 (+0) - -
Errors 0 (+0) - -
Llm_errors 0 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 51.52s (+5.63s) 2 🟢 3 🔴

Catalog Songs Count Evaluation (HEAD-1770154218)

Score Average Improvements Regressions
Llm_calls 4 (+0) - -
Tool_calls 0 (+0) - -
Errors 3 (+0) - -
Llm_errors 1 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 13.12s (-7.03s) 3 🟢 -

First Week Album Sales Evaluation (HEAD-1770154219)

Score Average Improvements Regressions
Llm_calls 1 (+0) - -
Tool_calls 0 (+0) - -
Errors 1 (+0) - -
Llm_errors 0 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 14.59s (-2.75s) 3 🟢 1 🔴

Memory & Storage Tools Evaluation (HEAD-1770154219)

Score Average Improvements Regressions
Tools_called 0% (+0pp) - -
Llm_calls 0 (+0) - -
Tool_calls 0 (+0) - -
Errors 0 (+0) - -
Llm_errors 0 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 18.06s (-1.26s) 1 🟢 -

Monthly Listeners Tracking Evaluation (HEAD-1770154219)

Score Average Improvements Regressions
Llm_calls 2 (+0) - -
Tool_calls 0 (+0) - -
Errors 2 (+0) - -
Llm_errors 1 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 11.02s (-4.59s) 4 🟢 1 🔴

Search Web Tool Evaluation (HEAD-1770154219)

Score Average Improvements Regressions
Llm_calls 3 (+0) - -
Tool_calls 0 (+0) - -
Errors 2 (+0) - -
Llm_errors 1 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 25.09s (-3.48s) 7 🟢 4 🔴

Social Scraping Evaluation (HEAD-1770154219)

Score Average Improvements Regressions
Tools_called 0% (+0pp) - -
Llm_calls 0 (+0) - -
Tool_calls 0 (+0) - -
Errors 0 (+0) - -
Llm_errors 0 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 26.47s (-3.47s) 3 🟢 3 🔴

Spotify Followers Evaluation (HEAD-1770154219)

Score Average Improvements Regressions
Llm_calls 3 (+0) - -
Tool_calls 0 (+0) - -
Errors 3 (+0) - -
Llm_errors 2 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 11.74s (-7.05s) 4 🟢 1 🔴

Spotify Tools Evaluation (HEAD-1770154219)

Score Average Improvements Regressions
Tools_called 0% (+0pp) - -
Llm_calls 0 (+0) - -
Tool_calls 0 (+0) - -
Errors 0 (+0) - -
Llm_errors 0 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 36.33s (-1.39s) 2 🟢 -

TikTok Analytics Questions Evaluation (HEAD-1770154218)

Score Average Improvements Regressions
Question_answered 10% (+0pp) 1 🟢 1 🔴
Llm_calls 0 (+0) - -
Tool_calls 0 (+0) - -
Errors 0 (+0) - -
Llm_errors 0 (+0) - -
Tool_errors 0 (+0) - -
Prompt_tokens 0tok (+0tok) - -
Prompt_cached_tokens 0tok (+0tok) - -
Prompt_cache_creation_tokens 0tok (+0tok) - -
Completion_tokens 0tok (+0tok) - -
Completion_reasoning_tokens 0tok (+0tok) - -
Total_tokens 0tok (+0tok) - -
Duration 20.12s (+3.75s) - 2 🔴

The Vercel Sandbox SDK requires snapshotId to be passed via the source
parameter with type: 'snapshot', not as a direct property.

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

coderabbitai bot commented Feb 3, 2026

Warning

Rate limit exceeded

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

⌛ 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.

📝 Walkthrough

Walkthrough

The changes transition sandbox creation from prompt-based to command-based execution, introducing account-level snapshot detection. The workflow now fetches snapshots when available and conditionally applies defaults based on the presence of a snapshot source during sandbox creation.

Changes

Cohort / File(s) Summary
Sandbox Creation Logic
lib/sandbox/createSandbox.ts, lib/sandbox/createSandboxPostHandler.ts
Refactored createSandbox to accept typed params object with defaults (timeout, vcpus, runtime). Added snapshot source detection: if snapshot present, uses snapshot ID; otherwise applies resource defaults. Handler now fetches account snapshots and passes snapshotId to sandbox creation. Added error handling for trigger operations.
Request/Response Schema Updates
lib/sandbox/validateSandboxBody.ts, lib/trigger/triggerRunSandboxCommand.ts, app/api/sandboxes/route.ts
Replaced prompt field with command and added optional args and cwd fields. RunSandboxCommandPayload now requires accountId. API documentation updated to reflect command execution instead of prompt. Response now includes runId from trigger handle.
Account Snapshot Functionality
lib/supabase/account_snapshots/selectAccountSnapshots.ts
New module that exports selectAccountSnapshot() function to fetch the most recent snapshot for an account from the account_snapshots table. Returns AccountSnapshot record or null on error.

Sequence Diagram

sequenceDiagram
    participant Client
    participant Handler as POST /api/sandboxes
    participant DB as Supabase
    participant SandboxSDK as Sandbox.create
    participant Trigger as triggerRunSandboxCommand

    Client->>Handler: POST {command, args, cwd}
    Handler->>DB: selectAccountSnapshot(accountId)
    alt Snapshot Exists
        DB-->>Handler: AccountSnapshot
        Handler->>SandboxSDK: create({source: {type: "snapshot", snapshotId}})
    else No Snapshot
        DB-->>Handler: null
        Handler->>SandboxSDK: create({vcpus: DEFAULT_VCPUS, runtime: DEFAULT_RUNTIME})
    end
    SandboxSDK-->>Handler: SandboxCreatedResponse {sandboxId}
    Handler->>DB: Save to account_sandboxes
    Handler->>Trigger: triggerRunSandboxCommand({command, args, cwd, sandboxId, accountId})
    Trigger-->>Handler: {handle with runId}
    Handler-->>Client: {sandboxes: [...], runId}
Loading

Estimated Code Review Effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🏗️ From prompts to commands, the sandbox evolves,
Snapshots now guide where fresh creation resolves,
Args and cwd dance alongside the way,
Architecture refines—cleaner by the day! ✨

🚥 Pre-merge checks | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Solid & Clean Code ⚠️ Warning The pull request violates Single Responsibility Principle by combining snapshot retrieval, sandbox creation, persistence, and task triggering in one function, with inconsistent error handling and unexported public types. Extract snapshot retrieval and trigger invocation into separate functions, export RunSandboxCommandPayload type, and establish consistent error handling with clear documentation of graceful degradation behavior.

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

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch sweetmantech/myc-4124-api-filetree-update-route-post-appapisandboxesroutets

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.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@lib/supabase/account_snapshots/selectAccountSnapshot.ts`:
- Around line 1-31: The file is misnamed: it targets the account_snapshots table
but is named selectAccountSnapshot.ts; rename the file to
selectAccountSnapshots.ts to follow the select[TableName].ts convention, keep
the exported function selectAccountSnapshot unchanged, and then update all
imports that reference the old filename to the new path (including any
barrels/indices). Search the repo for imports of "selectAccountSnapshot" and
occurrences of the old filename and replace them with the new filename so builds
and type imports resolve correctly.
- Around line 1-31: The file defines a local AccountSnapshot interface and uses
it as the return type for selectAccountSnapshot; replace that with the generated
DB types: import Tables from '@/types/database.types' (or the correct named
export) and change the function signature to return
Promise<Tables<"account_snapshots"> | null>, removing the local AccountSnapshot
interface so the function (selectAccountSnapshot) uses the canonical
Tables<"account_snapshots"> type used elsewhere (e.g., selectSocials.ts) to keep
typings in sync with the DB schema.
🧹 Nitpick comments (2)
lib/sandbox/createSandbox.ts (1)

25-39: Extract the shared timeout value to avoid drift between branches.

Both branches use the same timeout literal; hoisting it reduces duplication and future divergence risk.

♻️ Suggested refactor
 export async function createSandbox(
   options: CreateSandboxOptions = {},
 ): Promise<SandboxCreatedResponse> {
   const { snapshotId } = options;
+  const timeout = ms("10m");

   const sandbox = snapshotId
     ? await Sandbox.create({
         source: { type: "snapshot", snapshotId },
-        timeout: ms("10m"),
+        timeout,
       })
     : await Sandbox.create({
         resources: { vcpus: 4 },
-        timeout: ms("10m"),
+        timeout,
         runtime: "node22",
       });

As per coding guidelines, DRY: Consolidate similar logic into shared utilities.

lib/sandbox/validateSandboxBody.ts (1)

8-12: Harden validation for whitespace-only command/cwd and empty args entries.

min(1) allows strings of spaces. Consider trimming and enforcing non-empty entries for args items.

♻️ Suggested validation tightening
 export const sandboxBodySchema = z.object({
-  command: z.string({ message: "command is required" }).min(1, "command cannot be empty"),
-  args: z.array(z.string()).optional(),
-  cwd: z.string().optional(),
+  command: z
+    .string({ message: "command is required" })
+    .trim()
+    .min(1, "command cannot be empty"),
+  args: z.array(z.string().min(1)).optional(),
+  cwd: z.string().trim().min(1).optional(),
 });

Update test payloads to match new API: command, args, cwd, sandboxId, accountId

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Export CreateSandboxParams type extracted from Sandbox.create signature
- Accept full SDK params instead of custom snapshotId option
- Apply sensible defaults for timeout, resources, and runtime
- Update handler to pass source object for snapshots
- Add tests for new parameter combinations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use 'in' operator to check for runtime/resources properties since
they don't exist on the snapshot variant of the union type.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Spread defaults first, then override with params. This avoids
type conflicts between snapshot and base param variants.

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

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@lib/sandbox/createSandbox.ts`:
- Around line 28-44: createSandbox currently spreads ...params which can
overwrite the default resources object and drop DEFAULT_VCPUS when callers pass
a partial params.resources; update the non-snapshot branch that calls
Sandbox.create so resources are merged with defaults instead of overwritten
(e.g., set resources to an object that starts with vcpus: DEFAULT_VCPUS and then
spreads params.resources), ensuring you still spread ...params for other fields
and preserve timeout/default runtime handling; refer to createSandbox,
Sandbox.create, params, resources, and DEFAULT_VCPUS when making this change.

Comment on lines +28 to +44
export async function createSandbox(params: CreateSandboxParams = {}): Promise<SandboxCreatedResponse> {
const hasSnapshotSource = params.source && "type" in params.source && params.source.type === "snapshot";

// Pass params directly to SDK - it handles all the type variants
const sandbox = await Sandbox.create(
hasSnapshotSource
? {
...params,
timeout: params.timeout ?? DEFAULT_TIMEOUT,
}
: {
resources: { vcpus: DEFAULT_VCPUS },
timeout: params.timeout ?? DEFAULT_TIMEOUT,
runtime: DEFAULT_RUNTIME,
...params,
},
);
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Preserve default vCPU when partial resources are provided.

In the non-snapshot branch, ...params overwrites resources entirely. If a caller passes a partial resources (e.g., only memoryMB), the default vcpus is dropped, which can lead to missing/invalid resource settings. Consider merging defaults after spreading params.

✅ Suggested fix (merge resources after spreading params)
       : {
-          resources: { vcpus: DEFAULT_VCPUS },
           timeout: params.timeout ?? DEFAULT_TIMEOUT,
           runtime: DEFAULT_RUNTIME,
           ...params,
+          resources: { vcpus: DEFAULT_VCPUS, ...(params.resources ?? {}) },
         },
🤖 Prompt for AI Agents
In `@lib/sandbox/createSandbox.ts` around lines 28 - 44, createSandbox currently
spreads ...params which can overwrite the default resources object and drop
DEFAULT_VCPUS when callers pass a partial params.resources; update the
non-snapshot branch that calls Sandbox.create so resources are merged with
defaults instead of overwritten (e.g., set resources to an object that starts
with vcpus: DEFAULT_VCPUS and then spreads params.resources), ensuring you still
spread ...params for other fields and preserve timeout/default runtime handling;
refer to createSandbox, Sandbox.create, params, resources, and DEFAULT_VCPUS
when making this change.

- Wrap triggerRunSandboxCommand in try-catch to prevent hanging
- Return 200 with sandbox info even if trigger fails (runId omitted)
- Update JSDoc to document new command/args/cwd request format
- Update tests to reflect new graceful failure behavior

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Add console.log at each step to identify where the request is hanging:
- Request received
- Validation
- Snapshot lookup
- Sandbox creation
- DB insert
- Task trigger
- Response building

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Follow the select[TableName].ts naming convention where the table name
is account_snapshots (plural). Function name unchanged.

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

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@app/api/sandboxes/route.ts`:
- Around line 29-36: Update the response documentation to indicate that runId
may be absent/null: modify the Response schema comment in the file to show runId
as optional (e.g., runId?: string | null) for the sandboxes array returned by
createSandboxPostHandler, since createSandboxPostHandler can omit runId when the
trigger fails; mention it may be null or undefined to reflect trigger failure
behavior.
🧹 Nitpick comments (2)
lib/sandbox/createSandboxPostHandler.ts (2)

27-55: Consider extracting snapshot lookup + trigger orchestration into helpers.

This handler now does validation, snapshot selection, sandbox creation, DB insert, trigger, and response shaping. Splitting into small helpers would improve single responsibility and keep this under 50 lines.

As per coding guidelines, lib/**/*.ts: For domain functions, ensure: Single responsibility per function ... Keep functions under 50 lines ... Avoid side effects.


58-65: Keep response shape consistent when trigger fails.

Right now runId is omitted on failure, forcing clients to branch on missing fields. Consider returning a stable shape (e.g., runId: null and runStatus) to make parsing predictable.

Suggested response shape update
-    return NextResponse.json(
-      {
-        status: "success",
-        sandboxes: [
-          {
-            ...result,
-            ...(runId && { runId }),
-          },
-        ],
-      },
+    const runStatus = runId ? "triggered" : "failed";
+    return NextResponse.json(
+      {
+        status: "success",
+        sandboxes: [
+          {
+            ...result,
+            runId: runId ?? null,
+            runStatus,
+          },
+        ],
+      },
       { status: 200, headers: getCorsHeaders() },
     );
As per coding guidelines, `app/api/**/*.ts: Return consistent response formats`.

Comment on lines 29 to +36
* Request body:
* - prompt: string (required, min length 1) - The prompt to send to Claude Code
* - command: string (required) - The command to execute in the sandbox
* - args: string[] (optional) - Arguments to pass to the command
* - cwd: string (optional) - Working directory for command execution
*
* Response (200):
* - status: "success"
* - sandboxes: [{ sandboxId, sandboxStatus, timeout, createdAt }]
* - sandboxes: [{ sandboxId, sandboxStatus, timeout, createdAt, runId }]
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Document runId as optional.

createSandboxPostHandler omits runId when the trigger fails, but the docs imply it’s always present. Please update the response docs to clarify it’s optional (or may be null) on trigger failure.

Doc tweak
- * - sandboxes: [{ sandboxId, sandboxStatus, timeout, createdAt, runId }]
+ * - sandboxes: [{ sandboxId, sandboxStatus, timeout, createdAt, runId? }]
🤖 Prompt for AI Agents
In `@app/api/sandboxes/route.ts` around lines 29 - 36, Update the response
documentation to indicate that runId may be absent/null: modify the Response
schema comment in the file to show runId as optional (e.g., runId?: string |
null) for the sandboxes array returned by createSandboxPostHandler, since
createSandboxPostHandler can omit runId when the trigger fails; mention it may
be null or undefined to reflect trigger failure behavior.

- Rename function from selectAccountSnapshot to selectAccountSnapshots
- Remove .limit(1).single() to return full array
- Update handler to get first element from array
- Update tests with new function name and array return values

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Regenerate types with supabase gen types to include account_snapshots table
- Replace local AccountSnapshot interface with Tables<"account_snapshots">
- DRY: single source of truth for type definitions

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
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

Comments