Skip to content
2 changes: 2 additions & 0 deletions app/components/TerminalPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { useEffect, useState, ReactNode } from "react";
import { usePrivy } from "@privy-io/react-auth";
import TerminalComponent from "./Terminal";
import { TerminalData } from "./TerminalData";
import { useSetupSandbox } from "../hooks/useSetupSandbox";

export default function TerminalPage({
agentEndpoint,
Expand All @@ -14,6 +15,7 @@ export default function TerminalPage({
}) {
const [mounted, setMounted] = useState(false);
const { ready, authenticated, login, getAccessToken } = usePrivy();
useSetupSandbox();

useEffect(() => {
setMounted(true);
Expand Down
29 changes: 29 additions & 0 deletions app/hooks/useSetupSandbox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { useEffect, useRef } from "react";
import { usePrivy } from "@privy-io/react-auth";
import { getSandboxes } from "@/lib/recoup-api/getSandboxes";
import { setupSandbox } from "@/lib/recoup-api/setupSandbox";

export function useSetupSandbox() {
const { authenticated, getAccessToken } = usePrivy();
const hasRun = useRef(false);

useEffect(() => {
if (!authenticated || hasRun.current) return;
hasRun.current = true;

(async () => {
try {
const token = await getAccessToken();
if (!token) return;

const data = await getSandboxes(token);
if (!data) return;
if (data.snapshot_id && data.github_repo) return;

setupSandbox(token);
} catch {
// Silent — background provisioning only
}
})();
}, [authenticated, getAccessToken]);
}
5 changes: 5 additions & 0 deletions lib/consts.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
const IS_PROD = process.env.NEXT_PUBLIC_VERCEL_ENV === "production";

export const RECOUP_API_URL = IS_PROD
? "https://recoup-api.vercel.app"
: "https://test-recoup-api.vercel.app";
5 changes: 1 addition & 4 deletions lib/recoup-api/createSandbox.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
const IS_PROD = process.env.NEXT_PUBLIC_VERCEL_ENV === "production";
const RECOUP_API_URL = IS_PROD
? "https://recoup-api.vercel.app"
: "https://test-recoup-api.vercel.app";
import { RECOUP_API_URL } from "@/lib/consts";

export async function createSandbox(
bearerToken: string,
Expand Down
11 changes: 11 additions & 0 deletions lib/recoup-api/getSandboxes.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { RECOUP_API_URL } from "@/lib/consts";

export async function getSandboxes(bearerToken: string) {
const response = await fetch(`${RECOUP_API_URL}/api/sandboxes`, {
headers: { Authorization: `Bearer ${bearerToken}` },
});

if (!response.ok) return null;

return response.json();
}
8 changes: 8 additions & 0 deletions lib/recoup-api/setupSandbox.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import { RECOUP_API_URL } from "@/lib/consts";

export function setupSandbox(bearerToken: string) {
fetch(`${RECOUP_API_URL}/api/sandboxes/setup`, {
method: "POST",
headers: { Authorization: `Bearer ${bearerToken}` },
});
}
5 changes: 1 addition & 4 deletions lib/recoup-api/updateAccountSnapshot.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
const IS_PROD = process.env.NEXT_PUBLIC_VERCEL_ENV === "production";
const RECOUP_API_URL = IS_PROD
? "https://recoup-api.vercel.app"
: "https://test-recoup-api.vercel.app";
import { RECOUP_API_URL } from "@/lib/consts";

export async function updateAccountSnapshot(
bearerToken: string,
Expand Down