90 lines · 3.5 KB
import { z } from "zod";
import { limitAccountWrite, limitWrite } from "../../limits";
import { createScratchFromFiles, createScratchRepo, deploySiteRef } from "../../sites/api";
import type { ScratchResult } from "../../sites/api";
import { defineTool, repoArgs, scopedRepo } from "./base";

const MAX_FILES = 500;
const MAX_FILE_CHARS = 1024 * 1024;

function scratchText(result: ScratchResult): string {
  return `Live at ${result.url ?? "(sites disabled)"} until ${new Date(result.expiresAt).toISOString()}. Claim it at ${result.claimUrl} (keep the claim token secret).`;
}

const deploySiteTool = defineTool({
  name: "deploy_site",
  title: "Deploy site",
  description:
    "Deploy a repository's site from a branch: its production branch goes live, any other branch deploys a preview on its own host. Requires contents:write.",
  input: z.object({
    ...repoArgs,
    ref: z.string().max(250).optional().describe("Branch; defaults to the site's production branch"),
  }),
  write: true,
  async run({ caller }, args) {
    const { repo } = await scopedRepo(caller, args.owner, args.repo, "contents", "write");
    await limitWrite(caller.viewer);
    const result = await deploySiteRef(repo, { ref: args.ref, actorId: caller.viewer.id });
    return {
      structured: { deployment_id: result.deploymentId, environment: result.environment, url: result.url },
      text: `Queued ${result.environment} deploy ${result.deploymentId}; it will be served at ${result.url ?? "(sites disabled)"}.`,
      repoId: repo.id,
    };
  },
});

const scratchSiteTool = defineTool({
  name: "create_scratch_site",
  title: "Create scratch site",
  description:
    "Publish files as a temporary site (24 h, up to 500 files and 10 MiB) with a one-time claim token; include _worker.js for a dynamic Worker. Anyone signed in can claim it to keep it.",