76 lines · 3.4 KB
import { z } from "zod";
import { badRequest, conflict, forbidden, notFoundError } from "../../errors";
import { requireHeadPush } from "../../pull-merge";
import { loadPull } from "../../pulls";
import { hasPermission } from "../../repos";
import { scopedRepoPermission } from "../../token-scope";
import { limitWrite } from "../../limits";
import { loadStack, restackTree, stackParent } from "../../stacks";
import { defineTool, repoArgs, scopedRepo } from "./base";

const number = z.number().int().positive();

const getStackTool = defineTool({
  name: "get_pull_stack",
  title: "Get pull request stack",
  description:
    "The stack a pull request belongs to, bottom first. A pull request is stacked when its base is another open pull request's head branch; open one with open_pull using the parent's head branch as base.",
  input: z.object({ ...repoArgs, number }),
  write: false,
  async run({ caller }, args) {
    const { repo } = await scopedRepo(caller, args.owner, args.repo, "pulls", "read");
    const pull = await loadPull(repo.id, args.number);
    if (!pull) throw notFoundError("Pull request not found");
    const [stack, parent] = await Promise.all([loadStack(pull), stackParent(pull)]);
    return {
      structured: {
        stacked_on: parent ? parent.number : null,
        stack: stack.map((entry) => ({
          number: entry.number,
          title: entry.title,
          state: entry.merged ? "merged" : entry.state,
          draft: entry.draft,
          head: entry.headRef,
          base: entry.baseRef,
          depth: entry.depth,
          current: entry.current,
        })),
      },
      repoId: repo.id,
    };