mirror of
https://github.com/sourcebot-dev/sourcebot.git
synced 2025-12-12 12:25:22 +00:00
Review Agent (#298)
* push review agent implementation * feedback * wip integrating review agent into monorepo * move review agent to web * feedback * feedback * add rate limit throttling to octokit * configure agent ui in app * docs * add review command logic and add logging for review agent to data cache dir * fix bug with llm returning multiple reviews in single invocation * fix doc link bug * feedback and improved docs for review agent * review agent doc nits * mcp doc nit
This commit is contained in:
parent
f385ee2f7b
commit
e64f37178a
29 changed files with 1168 additions and 52 deletions
|
|
@ -23,6 +23,8 @@ AUTH_URL="http://localhost:3000"
|
||||||
# AUTH_GOOGLE_CLIENT_ID=""
|
# AUTH_GOOGLE_CLIENT_ID=""
|
||||||
# AUTH_GOOGLE_CLIENT_SECRET=""
|
# AUTH_GOOGLE_CLIENT_SECRET=""
|
||||||
|
|
||||||
|
#DATA_CACHE_DIR="" # Path to the sourcebot cache dir (ex. ~/sourcebot/.sourcebot)
|
||||||
|
|
||||||
# Email
|
# Email
|
||||||
# EMAIL_FROM_ADDRESS="" # The from address for transactional emails.
|
# EMAIL_FROM_ADDRESS="" # The from address for transactional emails.
|
||||||
# SMTP_CONNECTION_URL="" # The SMTP connection URL for transactional emails.
|
# SMTP_CONNECTION_URL="" # The SMTP connection URL for transactional emails.
|
||||||
|
|
@ -51,6 +53,16 @@ REDIS_URL="redis://localhost:6379"
|
||||||
# STRIPE_WEBHOOK_SECRET: z.string().optional(),
|
# STRIPE_WEBHOOK_SECRET: z.string().optional(),
|
||||||
# STRIPE_ENABLE_TEST_CLOCKS=false
|
# STRIPE_ENABLE_TEST_CLOCKS=false
|
||||||
|
|
||||||
|
# Agents
|
||||||
|
|
||||||
|
# GITHUB_APP_ID=
|
||||||
|
# GITHUB_APP_PRIVATE_KEY_PATH=
|
||||||
|
# GITHUB_APP_WEBHOOK_SECRET=
|
||||||
|
# OPENAI_API_KEY=
|
||||||
|
REVIEW_AGENT_LOGGING_ENABLED=true
|
||||||
|
REVIEW_AGENT_AUTO_REVIEW_ENABLED=false
|
||||||
|
REVIEW_AGENT_REVIEW_COMMAND=review
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
|
|
||||||
# Generated using:
|
# Generated using:
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,13 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"group": "Agents",
|
||||||
|
"pages": [
|
||||||
|
"docs/agents/overview",
|
||||||
|
"docs/agents/review-agent"
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"group": "More",
|
"group": "More",
|
||||||
"pages": [
|
"pages": [
|
||||||
|
|
|
||||||
17
docs/docs/agents/overview.mdx
Normal file
17
docs/docs/agents/overview.mdx
Normal file
|
|
@ -0,0 +1,17 @@
|
||||||
|
---
|
||||||
|
title: "Agents Overview"
|
||||||
|
sidebarTitle: "Overview"
|
||||||
|
---
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
Have an idea for an agent that we haven't built? Submit a [feature request](https://github.com/sourcebot-dev/sourcebot/discussions/categories/feature-requests) on our GitHub
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
Agents are automations that leverage the code indexed on Sourcebot to perform a specific task. Once you've setup Sourcebot, check out the
|
||||||
|
guides below to configure additional agents.
|
||||||
|
|
||||||
|
<CardGroup cols={2}>
|
||||||
|
<Card horizontal title="Review Agent" icon="gear" href="/docs/agents/review-agent">
|
||||||
|
An AI agent that reviews your PRs to identify issues
|
||||||
|
</Card>
|
||||||
|
</CardGroup>
|
||||||
93
docs/docs/agents/review-agent.mdx
Normal file
93
docs/docs/agents/review-agent.mdx
Normal file
|
|
@ -0,0 +1,93 @@
|
||||||
|
---
|
||||||
|
title: AI Code Review Agent
|
||||||
|
sidebarTitle: AI Code Review Agent
|
||||||
|
---
|
||||||
|
|
||||||
|
<Note>
|
||||||
|
This agent sends data to OpenAI (through an API key you supply) to perform code reviews. This data includes code from the PR being reviewed, as well as additional relevant context from your
|
||||||
|
codebase that the agent may fetch to perform the review.
|
||||||
|
</Note>
|
||||||
|
|
||||||
|
This agent provides codebase-aware reviews for your PRs. For each diff, this agent fetches relevant context from Sourcebot and feeds it into an LLM for a detailed review of your changes.
|
||||||
|
|
||||||
|
The AI Code Review Agent is open source and packaged in [Sourcebot](https://github.com/sourcebot-dev/sourcebot). To get started using this agent, [deploy Sourcebot](/self-hosting/overview)
|
||||||
|
and then follow the configuration instructions below.
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
# Configure
|
||||||
|
|
||||||
|
This agent currently only supports reviewing GitHub PRs. You configure the agent by creating a GitHub app, installing it into your GitHub organization, and then giving your app info to Sourcebot.
|
||||||
|
|
||||||
|
Before you get started, make sure you have an OpenAPI account that you can create an OpenAPI key with.
|
||||||
|
|
||||||
|
<Steps>
|
||||||
|
<Step title="Register a GitHub app">
|
||||||
|
Follow the official GitHub guide for [registering a GitHub app](https://docs.github.com/en/apps/creating-github-apps/registering-a-github-app/registering-a-github-app)
|
||||||
|
|
||||||
|
- GitHub App name: You can make this whatever you want (ex. Sourcebot Review Agent)
|
||||||
|
- Homepage URL: You can make this whatever you want (ex. https://www.sourcebot.dev/)
|
||||||
|
- Webhook URL (**IMPORTANT**): You must set this to point to your Sourcebot deployment at /api/webhook (ex. https://sourcebot.aperture.com/api/webhook). Your Sourcebot deployment must be able to accept requests from GitHub
|
||||||
|
(either github.com or your self-hosted enterprise server) for this to work. If you're running Sourcebot locally, you can [use smee](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#step-2-get-a-webhook-proxy-url) to [forward webhooks](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#step-6-start-your-server) to your local deployment.
|
||||||
|
- Permissions
|
||||||
|
- Pull requests: Read & Write
|
||||||
|
- Issues: Read & Write
|
||||||
|
- Contents: Read
|
||||||
|
- Events:
|
||||||
|
- Pull request
|
||||||
|
- Issue comment
|
||||||
|
</Step>
|
||||||
|
<Step title="Install the GitHub app in your organization">
|
||||||
|
Navigate to your new [GitHub app's page](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#navigate-to-your-app-settings) and press `Install`
|
||||||
|
</Step>
|
||||||
|
<Step title="Configure the environment variables in Sourcebot">
|
||||||
|
Sourcebot requires the following environment variables to begin reviewing PRs through your new GitHub app:
|
||||||
|
|
||||||
|
- `GITHUB_APP_ID`: The client ID of your GitHub app. Can be found in your [app settings](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#navigate-to-your-app-settings)
|
||||||
|
- `GITHUB_APP_WEBHOOK_SECRET`: A random webhook secret that you've set in your [app settings](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#navigate-to-your-app-settings). This can be anything (ex. `python -c "import secrets; print(secrets.token_hex(10))"` to generate a random secret)
|
||||||
|
- `GITHUB_APP_PRIVATE_KEY_PATH`: The path to your app's private key. If you're running Sourcebot from a container, this is the path to this file from within your container
|
||||||
|
(ex `/data/review-agent-key.pem`). You must copy the private key file into the directory you mount to Sourcebot (similar to the config file).
|
||||||
|
|
||||||
|
You can generate a private key file for your app in the [app settings](https://docs.github.com/en/apps/creating-github-apps/writing-code-for-a-github-app/quickstart#navigate-to-your-app-settings). You must copy this private key file into the
|
||||||
|
directory that you mount to Sourcebot
|
||||||
|

|
||||||
|
- `OPENAI_API_KEY`: Your OpenAI API key
|
||||||
|
- `REVIEW_AGENT_AUTO_REVIEW_ENABLED` (default: `false`): If enabled, the review agent will automatically review any new or updated PR. If disabled, you must invoke it using the command defined by `REVIEW_AGENT_REVIEW_COMMAND`
|
||||||
|
- `REVIEW_AGENT_REVIEW_COMMAND` (default: `review`): The command that invokes the review agent (ex. `/review`) when a user comments on the PR. Don't include the slash character in this value.
|
||||||
|
|
||||||
|
You can find an example docker compose file below.
|
||||||
|
- This docker compose file is placed in `~/sourcebot_review_agent_workspace`, and I'm mounting that directory to Sourcebot
|
||||||
|
- The config and the app private key files are placed in this directory
|
||||||
|
- The paths to these files are given to Sourcebot relative to `/data` since that's the directory in Sourcebot that I'm mounting to
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
sourcebot:
|
||||||
|
image: ghcr.io/sourcebot-dev/sourcebot:latest
|
||||||
|
pull_policy: always
|
||||||
|
container_name: sourcebot
|
||||||
|
ports:
|
||||||
|
- "3000:3000"
|
||||||
|
volumes:
|
||||||
|
- "/Users/michael/sourcebot_review_agent_workspace:/data"
|
||||||
|
environment:
|
||||||
|
CONFIG_PATH: "/data/config.json"
|
||||||
|
GITHUB_APP_ID: "my-github-app-id"
|
||||||
|
GITHUB_APP_WEBHOOK_SECRET: "my-github-app-webhook-secret"
|
||||||
|
GITHUB_APP_PRIVATE_KEY_PATH: "/data/review-agent-key.pem"
|
||||||
|
OPENAI_API_KEY: "sk-proj-my-open-api-key"
|
||||||
|
```
|
||||||
|
</Step>
|
||||||
|
<Step title="Verify configuration">
|
||||||
|
Navigate to the agents page by pressing `Agents` in the Sourcebot nav menu. If you've configured your environment variables correctly you'll see the following:
|
||||||
|
|
||||||
|

|
||||||
|
</Step>
|
||||||
|
</Steps>
|
||||||
|
|
||||||
|
# Using the agent
|
||||||
|
|
||||||
|
The review agent will not automatically review your PRs by default. To enable this feature, set the `REVIEW_AGENT_AUTO_REVIEW_ENABLED` environment variable to true.
|
||||||
|
|
||||||
|
You can invoke the review agent manually by commenting `/review` on the PR you'd like it to review. You can configure the command that triggers the agent by changing
|
||||||
|
the `REVIEW_AGENT_REVIEW_COMMAND` environment variable.
|
||||||
|
|
@ -7,7 +7,7 @@ sidebarTitle: Sourcebot MCP server
|
||||||
This feature is only available when [self-hosting](/self-hosting) with [authentication](/self-hosting/more/authentication) disabled.
|
This feature is only available when [self-hosting](/self-hosting) with [authentication](/self-hosting/more/authentication) disabled.
|
||||||
</Note>
|
</Note>
|
||||||
|
|
||||||
The [Model Context Protocol](https://modelcontextprotocol.io/introduction) (MCP) is a open standard for providing context to LLMs. The [@sourcebot/mcp](https://www.npmjs.com/package/@sourcebot/mcp) package is a MCP server that enables LLMs to interface with your Sourcebot instance, enabling MCP clients like Cursor, Vscode, and others to have context over your entire codebase.
|
The [Model Context Protocol](https://modelcontextprotocol.io/introduction) (MCP) is an open standard for providing context to LLMs. The [@sourcebot/mcp](https://www.npmjs.com/package/@sourcebot/mcp) package is a MCP server that enables LLMs to interface with your Sourcebot instance, enabling MCP clients like Cursor, Vscode, and others to have context over your entire codebase.
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
|
|
|
||||||
BIN
docs/images/github_app_private_key.png
Normal file
BIN
docs/images/github_app_private_key.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 22 KiB |
BIN
docs/images/review_agent_configured.png
Normal file
BIN
docs/images/review_agent_configured.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
BIN
docs/images/review_agent_example.png
Normal file
BIN
docs/images/review_agent_example.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 211 KiB |
|
|
@ -1,7 +1,8 @@
|
||||||
{
|
{
|
||||||
"private": true,
|
"private": true,
|
||||||
"workspaces": [
|
"workspaces": [
|
||||||
"packages/*"
|
"packages/*",
|
||||||
|
"packages/agents/*"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cross-env SKIP_ENV_VALIDATION=1 yarn workspaces foreach -A run build",
|
"build": "cross-env SKIP_ENV_VALIDATION=1 yarn workspaces foreach -A run build",
|
||||||
|
|
@ -11,6 +12,7 @@
|
||||||
"dev:zoekt": "yarn with-env zoekt-webserver -index .sourcebot/index -rpc",
|
"dev:zoekt": "yarn with-env zoekt-webserver -index .sourcebot/index -rpc",
|
||||||
"dev:backend": "yarn with-env yarn workspace @sourcebot/backend dev:watch",
|
"dev:backend": "yarn with-env yarn workspace @sourcebot/backend dev:watch",
|
||||||
"dev:web": "yarn with-env yarn workspace @sourcebot/web dev",
|
"dev:web": "yarn with-env yarn workspace @sourcebot/web dev",
|
||||||
|
"dev:review-agent": "yarn with-env yarn workspace @sourcebot/review-agent dev",
|
||||||
"watch:mcp": "yarn workspace @sourcebot/mcp build:watch",
|
"watch:mcp": "yarn workspace @sourcebot/mcp build:watch",
|
||||||
"watch:schemas": "yarn workspace @sourcebot/schemas watch",
|
"watch:schemas": "yarn workspace @sourcebot/schemas watch",
|
||||||
"dev:prisma:migrate:dev": "yarn with-env yarn workspace @sourcebot/db prisma:migrate:dev",
|
"dev:prisma:migrate:dev": "yarn with-env yarn workspace @sourcebot/db prisma:migrate:dev",
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,8 @@ export const env = createEnv({
|
||||||
SOURCEBOT_INSTALL_ID: z.string().default("unknown"),
|
SOURCEBOT_INSTALL_ID: z.string().default("unknown"),
|
||||||
NEXT_PUBLIC_SOURCEBOT_VERSION: z.string().default("unknown"),
|
NEXT_PUBLIC_SOURCEBOT_VERSION: z.string().default("unknown"),
|
||||||
|
|
||||||
|
DATA_CACHE_DIR: z.string(),
|
||||||
|
|
||||||
NEXT_PUBLIC_POSTHOG_PAPIK: z.string().optional(),
|
NEXT_PUBLIC_POSTHOG_PAPIK: z.string().optional(),
|
||||||
|
|
||||||
FALLBACK_GITHUB_CLOUD_TOKEN: z.string().optional(),
|
FALLBACK_GITHUB_CLOUD_TOKEN: z.string().optional(),
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import path from 'path';
|
||||||
import { AppContext } from "./types.js";
|
import { AppContext } from "./types.js";
|
||||||
import { main } from "./main.js"
|
import { main } from "./main.js"
|
||||||
import { PrismaClient } from "@sourcebot/db";
|
import { PrismaClient } from "@sourcebot/db";
|
||||||
|
import { env } from "./env.js";
|
||||||
|
|
||||||
// Register handler for normal exit
|
// Register handler for normal exit
|
||||||
process.on('exit', (code) => {
|
process.on('exit', (code) => {
|
||||||
|
|
@ -36,22 +37,9 @@ process.on('unhandledRejection', (reason, promise) => {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log(process.cwd());
|
||||||
|
|
||||||
const parser = new ArgumentParser({
|
const cacheDir = env.DATA_CACHE_DIR;
|
||||||
description: "Sourcebot backend tool",
|
|
||||||
});
|
|
||||||
|
|
||||||
type Arguments = {
|
|
||||||
cacheDir: string;
|
|
||||||
}
|
|
||||||
|
|
||||||
parser.add_argument("--cacheDir", {
|
|
||||||
help: "Path to .sourcebot cache directory",
|
|
||||||
required: true,
|
|
||||||
});
|
|
||||||
const args = parser.parse_args() as Arguments;
|
|
||||||
|
|
||||||
const cacheDir = args.cacheDir;
|
|
||||||
const reposPath = path.join(cacheDir, 'repos');
|
const reposPath = path.join(cacheDir, 'repos');
|
||||||
const indexPath = path.join(cacheDir, 'index');
|
const indexPath = path.join(cacheDir, 'index');
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -118,6 +118,9 @@
|
||||||
"next-auth": "^5.0.0-beta.25",
|
"next-auth": "^5.0.0-beta.25",
|
||||||
"next-themes": "^0.3.0",
|
"next-themes": "^0.3.0",
|
||||||
"nodemailer": "^6.10.0",
|
"nodemailer": "^6.10.0",
|
||||||
|
"octokit": "^4.1.3",
|
||||||
|
"openai": "^4.98.0",
|
||||||
|
"parse-diff": "^0.11.1",
|
||||||
"posthog-js": "^1.161.5",
|
"posthog-js": "^1.161.5",
|
||||||
"pretty-bytes": "^6.1.1",
|
"pretty-bytes": "^6.1.1",
|
||||||
"psl": "^1.15.0",
|
"psl": "^1.15.0",
|
||||||
|
|
@ -135,7 +138,8 @@
|
||||||
"tailwind-merge": "^2.5.2",
|
"tailwind-merge": "^2.5.2",
|
||||||
"tailwindcss-animate": "^1.0.7",
|
"tailwindcss-animate": "^1.0.7",
|
||||||
"usehooks-ts": "^3.1.0",
|
"usehooks-ts": "^3.1.0",
|
||||||
"zod": "^3.24.3"
|
"zod": "^3.24.3",
|
||||||
|
"zod-to-json-schema": "^3.24.5"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/micromatch": "^4.0.9",
|
"@types/micromatch": "^4.0.9",
|
||||||
|
|
|
||||||
69
packages/web/src/app/[domain]/agents/page.tsx
Normal file
69
packages/web/src/app/[domain]/agents/page.tsx
Normal file
|
|
@ -0,0 +1,69 @@
|
||||||
|
import Link from "next/link";
|
||||||
|
import { NavigationMenu } from "../components/navigationMenu";
|
||||||
|
import { FaCogs } from "react-icons/fa";
|
||||||
|
import { env } from "@/env.mjs";
|
||||||
|
|
||||||
|
const agents = [
|
||||||
|
{
|
||||||
|
id: "review-agent",
|
||||||
|
name: "Review Agent",
|
||||||
|
description: "An AI code review agent that reviews your PRs. Uses the code indexed on Sourcebot to provide codebase-wide context.",
|
||||||
|
requiredEnvVars: ["GITHUB_APP_ID", "GITHUB_APP_WEBHOOK_SECRET", "GITHUB_APP_PRIVATE_KEY_PATH", "OPENAI_API_KEY"],
|
||||||
|
configureUrl: "https://docs.sourcebot.dev/docs/agents/review-agent"
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
export default function AgentsPage({ params: { domain } }: { params: { domain: string } }) {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col items-center overflow-hidden min-h-screen">
|
||||||
|
<NavigationMenu domain={domain} />
|
||||||
|
<div className="w-full max-w-6xl px-4 mt-12 mb-24">
|
||||||
|
<div
|
||||||
|
className={
|
||||||
|
agents.length === 1
|
||||||
|
? "flex justify-center items-center min-h-[60vh]"
|
||||||
|
: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-10"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{agents.map((agent) => (
|
||||||
|
<div
|
||||||
|
key={agent.id}
|
||||||
|
className={
|
||||||
|
agents.length === 1
|
||||||
|
? "relative flex flex-col items-center border border-border rounded-2xl p-8 bg-card shadow-xl w-full max-w-xl"
|
||||||
|
: "relative flex flex-col items-center border border-border rounded-2xl p-8 bg-card shadow-xl"
|
||||||
|
}
|
||||||
|
>
|
||||||
|
{/* Name and description */}
|
||||||
|
<div className="flex flex-col items-center w-full">
|
||||||
|
<h2 className="font-bold text-2xl mb-4 mt-2 text-center text-foreground drop-shadow-sm">
|
||||||
|
{agent.name}
|
||||||
|
</h2>
|
||||||
|
<p className="text-base text-muted-foreground text-center mb-4 min-h-[56px]">
|
||||||
|
{agent.description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{/* Actions */}
|
||||||
|
<div className="flex flex-col items-center w-full mt-2">
|
||||||
|
{agent.requiredEnvVars.every(envVar => envVar in env && env[envVar as keyof typeof env] !== undefined) ? (
|
||||||
|
<div className="text-green-500 font-semibold">
|
||||||
|
Agent is configured and accepting requests on /api/webhook
|
||||||
|
</div>
|
||||||
|
) : (
|
||||||
|
<Link
|
||||||
|
href={agent.configureUrl}
|
||||||
|
target="_blank"
|
||||||
|
rel="noopener noreferrer"
|
||||||
|
className="flex items-center justify-center gap-2 px-5 py-2.5 rounded-md bg-primary text-primary-foreground font-mono font-semibold text-base border border-primary shadow-sm hover:bg-primary/80 focus:outline-none focus:ring-2 focus:ring-primary/60 transition w-1/2"
|
||||||
|
>
|
||||||
|
<FaCogs className="text-lg" /> Configure
|
||||||
|
</Link>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
@ -3,7 +3,8 @@ import { TopBar } from "@/app/[domain]/components/topBar";
|
||||||
import { Separator } from '@/components/ui/separator';
|
import { Separator } from '@/components/ui/separator';
|
||||||
import { getFileSource } from '@/features/search/fileSourceApi';
|
import { getFileSource } from '@/features/search/fileSourceApi';
|
||||||
import { listRepositories } from '@/features/search/listReposApi';
|
import { listRepositories } from '@/features/search/listReposApi';
|
||||||
import { base64Decode, isServiceError } from "@/lib/utils";
|
import { isServiceError } from "@/lib/utils";
|
||||||
|
import { base64Decode } from "@/lib/utils";
|
||||||
import { CodePreview } from "./codePreview";
|
import { CodePreview } from "./codePreview";
|
||||||
import { ErrorCode } from "@/lib/errorCodes";
|
import { ErrorCode } from "@/lib/errorCodes";
|
||||||
import { LuFileX2, LuBookX } from "react-icons/lu";
|
import { LuFileX2, LuBookX } from "react-icons/lu";
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,13 @@ export const NavigationMenu = async ({
|
||||||
</NavigationMenuLink>
|
</NavigationMenuLink>
|
||||||
</Link>
|
</Link>
|
||||||
</NavigationMenuItem>
|
</NavigationMenuItem>
|
||||||
|
<NavigationMenuItem>
|
||||||
|
<Link href={`/${domain}/agents`} legacyBehavior passHref>
|
||||||
|
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
|
||||||
|
Agents
|
||||||
|
</NavigationMenuLink>
|
||||||
|
</Link>
|
||||||
|
</NavigationMenuItem>
|
||||||
<NavigationMenuItem>
|
<NavigationMenuItem>
|
||||||
<Link href={`/${domain}/repos`} legacyBehavior passHref>
|
<Link href={`/${domain}/repos`} legacyBehavior passHref>
|
||||||
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
|
<NavigationMenuLink className={navigationMenuTriggerStyle()}>
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ export const POST = async (request: NextRequest) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const postSource = (request: FileSourceRequest, domain: string) => sew(() =>
|
export const postSource = (request: FileSourceRequest, domain: string) => sew(() =>
|
||||||
withAuth(async (session) =>
|
withAuth(async (session) =>
|
||||||
withOrgMembership(session, domain, async ({ orgId }) => {
|
withOrgMembership(session, domain, async ({ orgId }) => {
|
||||||
const response = await getFileSource(request, orgId);
|
const response = await getFileSource(request, orgId);
|
||||||
|
|
|
||||||
113
packages/web/src/app/api/(server)/webhook/route.ts
Normal file
113
packages/web/src/app/api/(server)/webhook/route.ts
Normal file
|
|
@ -0,0 +1,113 @@
|
||||||
|
'use server';
|
||||||
|
|
||||||
|
import { NextRequest } from "next/server";
|
||||||
|
import { App, Octokit } from "octokit";
|
||||||
|
import { WebhookEventDefinition} from "@octokit/webhooks/types";
|
||||||
|
import { EndpointDefaults } from "@octokit/types";
|
||||||
|
import { env } from "@/env.mjs";
|
||||||
|
import { processGitHubPullRequest } from "@/features/agents/review-agent/app";
|
||||||
|
import { throttling } from "@octokit/plugin-throttling";
|
||||||
|
import fs from "fs";
|
||||||
|
import { GitHubPullRequest } from "@/features/agents/review-agent/types";
|
||||||
|
|
||||||
|
let githubApp: App | undefined;
|
||||||
|
if (env.GITHUB_APP_ID && env.GITHUB_APP_WEBHOOK_SECRET && env.GITHUB_APP_PRIVATE_KEY_PATH) {
|
||||||
|
try {
|
||||||
|
const privateKey = fs.readFileSync(env.GITHUB_APP_PRIVATE_KEY_PATH, "utf8");
|
||||||
|
|
||||||
|
const throttledOctokit = Octokit.plugin(throttling);
|
||||||
|
githubApp = new App({
|
||||||
|
appId: env.GITHUB_APP_ID,
|
||||||
|
privateKey: privateKey,
|
||||||
|
webhooks: {
|
||||||
|
secret: env.GITHUB_APP_WEBHOOK_SECRET,
|
||||||
|
},
|
||||||
|
Octokit: throttledOctokit,
|
||||||
|
throttle: {
|
||||||
|
onRateLimit: (retryAfter: number, options: Required<EndpointDefaults>, octokit: Octokit, retryCount: number) => {
|
||||||
|
if (retryCount > 3) {
|
||||||
|
console.log(`Rate limit exceeded: ${retryAfter} seconds`);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error initializing GitHub app: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function isPullRequestEvent(eventHeader: string, payload: unknown): payload is WebhookEventDefinition<"pull-request-opened"> | WebhookEventDefinition<"pull-request-synchronize"> {
|
||||||
|
return eventHeader === "pull_request" && typeof payload === "object" && payload !== null && "action" in payload && typeof payload.action === "string" && (payload.action === "opened" || payload.action === "synchronize");
|
||||||
|
}
|
||||||
|
|
||||||
|
function isIssueCommentEvent(eventHeader: string, payload: unknown): payload is WebhookEventDefinition<"issue-comment-created"> {
|
||||||
|
return eventHeader === "issue_comment" && typeof payload === "object" && payload !== null && "action" in payload && typeof payload.action === "string" && payload.action === "created";
|
||||||
|
}
|
||||||
|
|
||||||
|
export const POST = async (request: NextRequest) => {
|
||||||
|
const body = await request.json();
|
||||||
|
const headers = Object.fromEntries(request.headers.entries());
|
||||||
|
|
||||||
|
const githubEvent = headers['x-github-event'] || headers['X-GitHub-Event'];
|
||||||
|
if (githubEvent) {
|
||||||
|
console.log('GitHub event received:', githubEvent);
|
||||||
|
|
||||||
|
if (!githubApp) {
|
||||||
|
console.warn('Received GitHub webhook event but GitHub app env vars are not set');
|
||||||
|
return Response.json({ status: 'ok' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPullRequestEvent(githubEvent, body)) {
|
||||||
|
if (env.REVIEW_AGENT_AUTO_REVIEW_ENABLED === "false") {
|
||||||
|
console.log('Review agent auto review (REVIEW_AGENT_AUTO_REVIEW_ENABLED) is disabled, skipping');
|
||||||
|
return Response.json({ status: 'ok' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!body.installation) {
|
||||||
|
console.error('Received github pull request event but installation is not present');
|
||||||
|
return Response.json({ status: 'ok' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const installationId = body.installation.id;
|
||||||
|
const octokit = await githubApp.getInstallationOctokit(installationId);
|
||||||
|
|
||||||
|
const pullRequest = body.pull_request as GitHubPullRequest;
|
||||||
|
await processGitHubPullRequest(octokit, pullRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isIssueCommentEvent(githubEvent, body)) {
|
||||||
|
const comment = body.comment.body;
|
||||||
|
if (!comment) {
|
||||||
|
console.warn('Received issue comment event but comment body is empty');
|
||||||
|
return Response.json({ status: 'ok' });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (comment === `/${env.REVIEW_AGENT_REVIEW_COMMAND}`) {
|
||||||
|
console.log('Review agent review command received, processing');
|
||||||
|
|
||||||
|
if (!body.installation) {
|
||||||
|
console.error('Received github issue comment event but installation is not present');
|
||||||
|
return Response.json({ status: 'ok' });
|
||||||
|
}
|
||||||
|
|
||||||
|
const pullRequestNumber = body.issue.number;
|
||||||
|
const repositoryName = body.repository.name;
|
||||||
|
const owner = body.repository.owner.login;
|
||||||
|
|
||||||
|
const octokit = await githubApp.getInstallationOctokit(body.installation.id);
|
||||||
|
const { data: pullRequest } = await octokit.rest.pulls.get({
|
||||||
|
owner,
|
||||||
|
repo: repositoryName,
|
||||||
|
pull_number: pullRequestNumber,
|
||||||
|
});
|
||||||
|
|
||||||
|
await processGitHubPullRequest(octokit, pullRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Response.json({ status: 'ok' });
|
||||||
|
}
|
||||||
|
|
@ -27,6 +27,8 @@ export const env = createEnv({
|
||||||
AUTH_URL: z.string().url(),
|
AUTH_URL: z.string().url(),
|
||||||
AUTH_CREDENTIALS_LOGIN_ENABLED: booleanSchema.default('true'),
|
AUTH_CREDENTIALS_LOGIN_ENABLED: booleanSchema.default('true'),
|
||||||
|
|
||||||
|
DATA_CACHE_DIR: z.string(),
|
||||||
|
|
||||||
// Email
|
// Email
|
||||||
SMTP_CONNECTION_URL: z.string().url().optional(),
|
SMTP_CONNECTION_URL: z.string().url().optional(),
|
||||||
EMAIL_FROM_ADDRESS: z.string().email().optional(),
|
EMAIL_FROM_ADDRESS: z.string().email().optional(),
|
||||||
|
|
@ -52,6 +54,15 @@ export const env = createEnv({
|
||||||
|
|
||||||
// EE License
|
// EE License
|
||||||
SOURCEBOT_EE_LICENSE_KEY: z.string().optional(),
|
SOURCEBOT_EE_LICENSE_KEY: z.string().optional(),
|
||||||
|
|
||||||
|
// GitHub app for review agent
|
||||||
|
GITHUB_APP_ID: z.string().optional(),
|
||||||
|
GITHUB_APP_WEBHOOK_SECRET: z.string().optional(),
|
||||||
|
GITHUB_APP_PRIVATE_KEY_PATH: z.string().optional(),
|
||||||
|
OPENAI_API_KEY: z.string().optional(),
|
||||||
|
REVIEW_AGENT_LOGGING_ENABLED: booleanSchema.default('true'),
|
||||||
|
REVIEW_AGENT_AUTO_REVIEW_ENABLED: booleanSchema.default('false'),
|
||||||
|
REVIEW_AGENT_REVIEW_COMMAND: z.string().default('review'),
|
||||||
},
|
},
|
||||||
// @NOTE: Please make sure of the following:
|
// @NOTE: Please make sure of the following:
|
||||||
// - Make sure you destructure all client variables in
|
// - Make sure you destructure all client variables in
|
||||||
|
|
|
||||||
51
packages/web/src/features/agents/review-agent/app.ts
Normal file
51
packages/web/src/features/agents/review-agent/app.ts
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
import { Octokit } from "octokit";
|
||||||
|
import { generatePrReviews } from "@/features/agents/review-agent/nodes/generatePrReview";
|
||||||
|
import { githubPushPrReviews } from "@/features/agents/review-agent/nodes/githubPushPrReviews";
|
||||||
|
import { githubPrParser } from "@/features/agents/review-agent/nodes/githubPrParser";
|
||||||
|
import { env } from "@/env.mjs";
|
||||||
|
import { GitHubPullRequest } from "@/features/agents/review-agent/types";
|
||||||
|
import path from "path";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
const rules = [
|
||||||
|
"Do NOT provide general feedback, summaries, explanations of changes, or praises for making good additions.",
|
||||||
|
"Do NOT provide any advice that is not actionable or directly related to the changes.",
|
||||||
|
"Do NOT provide any comments or reviews on code that you believe is good, correct, or a good addition. Your job is only to identify issues and provide feedback on how to fix them.",
|
||||||
|
"If a review for a chunk contains different reviews at different line ranges, return a seperate review object for each line range.",
|
||||||
|
"Focus solely on offering specific, objective insights based on the given context and refrain from making broad comments about potential impacts on the system or question intentions behind the changes.",
|
||||||
|
"Keep comments concise and to the point. Every comment must highlight a specific issue and provide a clear and actionable solution to the developer.",
|
||||||
|
"If there are no issues found on a line range, do NOT respond with any comments. This includes comments such as \"No issues found\" or \"LGTM\"."
|
||||||
|
]
|
||||||
|
|
||||||
|
export async function processGitHubPullRequest(octokit: Octokit, pullRequest: GitHubPullRequest) {
|
||||||
|
console.log(`Received a pull request event for #${pullRequest.number}`);
|
||||||
|
|
||||||
|
if (!env.OPENAI_API_KEY) {
|
||||||
|
console.error("OPENAI_API_KEY is not set, skipping review agent");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
let reviewAgentLogPath: string | undefined;
|
||||||
|
if (env.REVIEW_AGENT_LOGGING_ENABLED) {
|
||||||
|
const reviewAgentLogDir = path.join(env.DATA_CACHE_DIR, "review-agent");
|
||||||
|
if (!fs.existsSync(reviewAgentLogDir)) {
|
||||||
|
fs.mkdirSync(reviewAgentLogDir, { recursive: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
const timestamp = new Date().toLocaleString('en-US', {
|
||||||
|
year: 'numeric',
|
||||||
|
month: '2-digit',
|
||||||
|
day: '2-digit',
|
||||||
|
hour: '2-digit',
|
||||||
|
minute: '2-digit',
|
||||||
|
second: '2-digit',
|
||||||
|
hour12: false
|
||||||
|
}).replace(/(\d+)\/(\d+)\/(\d+), (\d+):(\d+):(\d+)/, '$3_$1_$2_$4_$5_$6');
|
||||||
|
reviewAgentLogPath = path.join(reviewAgentLogDir, `review-agent-${pullRequest.number}-${timestamp}.log`);
|
||||||
|
console.log(`Review agent logging to ${reviewAgentLogPath}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const prPayload = await githubPrParser(octokit, pullRequest);
|
||||||
|
const fileDiffReviews = await generatePrReviews(reviewAgentLogPath, prPayload, rules);
|
||||||
|
await githubPushPrReviews(octokit, prPayload, fileDiffReviews);
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,33 @@
|
||||||
|
import { sourcebot_context, sourcebot_pr_payload } from "@/features/agents/review-agent/types";
|
||||||
|
import { fileSourceResponseSchema } from "@/features/search/schemas";
|
||||||
|
import { base64Decode } from "@/lib/utils";
|
||||||
|
import { postSource } from "@/app/api/(server)/source/route";
|
||||||
|
import { isServiceError } from "@/lib/utils";
|
||||||
|
|
||||||
|
export const fetchFileContent = async (pr_payload: sourcebot_pr_payload, filename: string): Promise<sourcebot_context> => {
|
||||||
|
console.log("Executing fetch_file_content");
|
||||||
|
|
||||||
|
const repoPath = pr_payload.hostDomain + "/" + pr_payload.owner + "/" + pr_payload.repo;
|
||||||
|
const fileSourceRequest = {
|
||||||
|
fileName: filename,
|
||||||
|
repository: repoPath,
|
||||||
|
}
|
||||||
|
console.log(JSON.stringify(fileSourceRequest, null, 2));
|
||||||
|
|
||||||
|
const response = await postSource(fileSourceRequest, "~");
|
||||||
|
if (isServiceError(response)) {
|
||||||
|
throw new Error(`Failed to fetch file content for ${filename} from ${repoPath}: ${response.message}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const fileSourceResponse = fileSourceResponseSchema.parse(response);
|
||||||
|
const fileContent = base64Decode(fileSourceResponse.source);
|
||||||
|
|
||||||
|
const fileContentContext: sourcebot_context = {
|
||||||
|
type: "file_content",
|
||||||
|
description: `The content of the file ${filename}`,
|
||||||
|
context: fileContent,
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Completed fetch_file_content");
|
||||||
|
return fileContentContext;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
import { sourcebot_diff, sourcebot_context, sourcebot_file_diff_review_schema } from "@/features/agents/review-agent/types";
|
||||||
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
||||||
|
|
||||||
|
export const generateDiffReviewPrompt = async (diff: sourcebot_diff, context: sourcebot_context[], rules: string[]) => {
|
||||||
|
console.log("Executing generate_diff_review_prompt");
|
||||||
|
|
||||||
|
const prompt = `
|
||||||
|
You are an expert software engineer that excells at reviewing code changes. Given the input, additional context, and rules defined below, review the code changes and provide a detailed review. The review you provide
|
||||||
|
must conform to all of the rules defined below. The output format of your review must conform to the output format defined below.
|
||||||
|
|
||||||
|
# Input
|
||||||
|
|
||||||
|
The input is the old and new code snippets, which represent a single hunk from a git diff. The old code snippet is the code before the changes were made, and the new code snippet is the code after the changes were made. Each code snippet
|
||||||
|
is a sequence of lines each with a line number.
|
||||||
|
|
||||||
|
## Old Code Snippet
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
${diff.oldSnippet}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
## New Code Snippet
|
||||||
|
|
||||||
|
\`\`\`
|
||||||
|
${diff.newSnippet}
|
||||||
|
\`\`\`
|
||||||
|
|
||||||
|
# Additional Context
|
||||||
|
|
||||||
|
${context.map(c => `${c.type}: ${c.description}\n\n${c.context}`).join("\n\n----------------------\n\n")}
|
||||||
|
|
||||||
|
# Rules
|
||||||
|
|
||||||
|
- ${rules.join("\n- ")}
|
||||||
|
|
||||||
|
# Output Format (JSON Schema)
|
||||||
|
The output must be a valid JSON object that conforms to the following JSON schema. Do NOT respond with anything other than the JSON object. Do NOT respond with
|
||||||
|
the JSON object in a markdown code block.
|
||||||
|
${JSON.stringify(zodToJsonSchema(sourcebot_file_diff_review_schema), null, 2)}
|
||||||
|
`;
|
||||||
|
|
||||||
|
console.log("Completed generate_diff_review_prompt");
|
||||||
|
return prompt;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,49 @@
|
||||||
|
import { sourcebot_pr_payload, sourcebot_diff_review, sourcebot_file_diff_review, sourcebot_context } from "@/features/agents/review-agent/types";
|
||||||
|
import { generateDiffReviewPrompt } from "@/features/agents/review-agent/nodes/generateDiffReviewPrompt";
|
||||||
|
import { invokeDiffReviewLlm } from "@/features/agents/review-agent/nodes/invokeDiffReviewLlm";
|
||||||
|
import { fetchFileContent } from "@/features/agents/review-agent/nodes/fetchFileContent";
|
||||||
|
|
||||||
|
export const generatePrReviews = async (reviewAgentLogPath: string | undefined, pr_payload: sourcebot_pr_payload, rules: string[]): Promise<sourcebot_file_diff_review[]> => {
|
||||||
|
console.log("Executing generate_pr_reviews");
|
||||||
|
|
||||||
|
const file_diff_reviews: sourcebot_file_diff_review[] = [];
|
||||||
|
for (const file_diff of pr_payload.file_diffs) {
|
||||||
|
const reviews: sourcebot_diff_review[] = [];
|
||||||
|
|
||||||
|
for (const diff of file_diff.diffs) {
|
||||||
|
try {
|
||||||
|
const fileContentContext = await fetchFileContent(pr_payload, file_diff.to);
|
||||||
|
const context: sourcebot_context[] = [
|
||||||
|
{
|
||||||
|
type: "pr_title",
|
||||||
|
description: "The title of the pull request",
|
||||||
|
context: pr_payload.title,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
type: "pr_description",
|
||||||
|
description: "The description of the pull request",
|
||||||
|
context: pr_payload.description,
|
||||||
|
},
|
||||||
|
fileContentContext,
|
||||||
|
];
|
||||||
|
|
||||||
|
const prompt = await generateDiffReviewPrompt(diff, context, rules);
|
||||||
|
|
||||||
|
const diffReview = await invokeDiffReviewLlm(reviewAgentLogPath, prompt);
|
||||||
|
reviews.push(...diffReview.reviews);
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error generating review for ${file_diff.to}: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (reviews.length > 0) {
|
||||||
|
file_diff_reviews.push({
|
||||||
|
filename: file_diff.to,
|
||||||
|
reviews: reviews,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Completed generate_pr_reviews");
|
||||||
|
return file_diff_reviews;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
||||||
|
import { sourcebot_pr_payload, sourcebot_file_diff, sourcebot_diff } from "@/features/agents/review-agent/types";
|
||||||
|
import parse from "parse-diff";
|
||||||
|
import { Octokit } from "octokit";
|
||||||
|
import { GitHubPullRequest } from "@/features/agents/review-agent/types";
|
||||||
|
|
||||||
|
export const githubPrParser = async (octokit: Octokit, pullRequest: GitHubPullRequest): Promise<sourcebot_pr_payload> => {
|
||||||
|
console.log("Executing github_pr_parser");
|
||||||
|
|
||||||
|
let parsedDiff: parse.File[] = [];
|
||||||
|
try {
|
||||||
|
const diff = await octokit.request(pullRequest.diff_url);
|
||||||
|
parsedDiff = parse(diff.data);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Error fetching diff: ", error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
const sourcebotFileDiffs: (sourcebot_file_diff | null)[] = parsedDiff.map((file) => {
|
||||||
|
if (!file.from || !file.to) {
|
||||||
|
console.log(`Skipping file due to missing from (${file.from}) or to (${file.to})`)
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
const diffs: sourcebot_diff[] = file.chunks.map((chunk) => {
|
||||||
|
let oldSnippet = `@@ -${chunk.oldStart},${chunk.oldLines} +${chunk.newStart},${chunk.newLines} @@\n`;
|
||||||
|
let newSnippet = `@@ -${chunk.oldStart},${chunk.oldLines} +${chunk.newStart},${chunk.newLines} @@\n`;
|
||||||
|
|
||||||
|
for (const change of chunk.changes) {
|
||||||
|
if (change.type === "normal") {
|
||||||
|
oldSnippet += change.ln1 + ":" + change.content + "\n";
|
||||||
|
newSnippet += change.ln2 + ":" + change.content + "\n";
|
||||||
|
} else if (change.type === "add") {
|
||||||
|
newSnippet += change.ln + ":" + change.content + "\n";
|
||||||
|
} else if (change.type === "del") {
|
||||||
|
oldSnippet += change.ln + ":" + change.content + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
oldSnippet: oldSnippet,
|
||||||
|
newSnippet: newSnippet,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return {
|
||||||
|
from: file.from,
|
||||||
|
to: file.to,
|
||||||
|
diffs: diffs,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
const filteredSourcebotFileDiffs: sourcebot_file_diff[] = sourcebotFileDiffs.filter((file) => file !== null) as sourcebot_file_diff[];
|
||||||
|
|
||||||
|
console.log("Completed github_pr_parser");
|
||||||
|
return {
|
||||||
|
title: pullRequest.title,
|
||||||
|
description: pullRequest.body ?? "",
|
||||||
|
hostDomain: "github.com",
|
||||||
|
owner: pullRequest.base.repo.owner.login,
|
||||||
|
repo: pullRequest.base.repo.name,
|
||||||
|
file_diffs: filteredSourcebotFileDiffs,
|
||||||
|
number: pullRequest.number,
|
||||||
|
head_sha: pullRequest.head.sha
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,37 @@
|
||||||
|
import { Octokit } from "octokit";
|
||||||
|
import { sourcebot_pr_payload, sourcebot_file_diff_review } from "@/features/agents/review-agent/types";
|
||||||
|
|
||||||
|
export const githubPushPrReviews = async (octokit: Octokit, pr_payload: sourcebot_pr_payload, file_diff_reviews: sourcebot_file_diff_review[]) => {
|
||||||
|
console.log("Executing github_push_pr_reviews");
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (const file_diff_review of file_diff_reviews) {
|
||||||
|
for (const review of file_diff_review.reviews) {
|
||||||
|
try {
|
||||||
|
await octokit.rest.pulls.createReviewComment({
|
||||||
|
owner: pr_payload.owner,
|
||||||
|
repo: pr_payload.repo,
|
||||||
|
pull_number: pr_payload.number,
|
||||||
|
body: review.review,
|
||||||
|
path: file_diff_review.filename,
|
||||||
|
commit_id: pr_payload.head_sha,
|
||||||
|
side: "RIGHT",
|
||||||
|
...(review.line_start === review.line_end
|
||||||
|
? { line: review.line_start }
|
||||||
|
: {
|
||||||
|
start_line: review.line_start,
|
||||||
|
line: review.line_end,
|
||||||
|
start_side: "RIGHT",
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error pushing pr reviews for ${file_diff_review.filename}: ${error}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(`Error pushing pr reviews: ${error}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Completed github_push_pr_reviews");
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
import OpenAI from "openai";
|
||||||
|
import { sourcebot_file_diff_review, sourcebot_file_diff_review_schema } from "@/features/agents/review-agent/types";
|
||||||
|
import { env } from "@/env.mjs";
|
||||||
|
import fs from "fs";
|
||||||
|
|
||||||
|
export const invokeDiffReviewLlm = async (reviewAgentLogPath: string | undefined, prompt: string): Promise<sourcebot_file_diff_review> => {
|
||||||
|
console.log("Executing invoke_diff_review_llm");
|
||||||
|
|
||||||
|
if (!env.OPENAI_API_KEY) {
|
||||||
|
console.error("OPENAI_API_KEY is not set, skipping review agent");
|
||||||
|
throw new Error("OPENAI_API_KEY is not set, skipping review agent");
|
||||||
|
}
|
||||||
|
|
||||||
|
const openai = new OpenAI({
|
||||||
|
apiKey: env.OPENAI_API_KEY,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (reviewAgentLogPath) {
|
||||||
|
fs.appendFileSync(reviewAgentLogPath, `\n\nPrompt:\n${prompt}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const completion = await openai.chat.completions.create({
|
||||||
|
model: "gpt-4.1-mini",
|
||||||
|
messages: [
|
||||||
|
{ role: "system", content: prompt }
|
||||||
|
]
|
||||||
|
});
|
||||||
|
|
||||||
|
const openaiResponse = completion.choices[0].message.content;
|
||||||
|
if (reviewAgentLogPath) {
|
||||||
|
fs.appendFileSync(reviewAgentLogPath, `\n\nResponse:\n${openaiResponse}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const diffReviewJson = JSON.parse(openaiResponse || '{}');
|
||||||
|
const diffReview = sourcebot_file_diff_review_schema.safeParse(diffReviewJson);
|
||||||
|
|
||||||
|
if (!diffReview.success) {
|
||||||
|
throw new Error(`Invalid diff review format: ${diffReview.error}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("Completed invoke_diff_review_llm");
|
||||||
|
return diffReview.data;
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Error calling OpenAI:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
50
packages/web/src/features/agents/review-agent/types.ts
Normal file
50
packages/web/src/features/agents/review-agent/types.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
||||||
|
import { components } from "@octokit/openapi-types";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
export type GitHubPullRequest = components["schemas"]["pull-request"];
|
||||||
|
|
||||||
|
export const sourcebot_diff_schema = z.object({
|
||||||
|
oldSnippet: z.string(),
|
||||||
|
newSnippet: z.string(),
|
||||||
|
});
|
||||||
|
export type sourcebot_diff = z.infer<typeof sourcebot_diff_schema>;
|
||||||
|
|
||||||
|
export const sourcebot_file_diff_schema = z.object({
|
||||||
|
from: z.string(),
|
||||||
|
to: z.string(),
|
||||||
|
diffs: z.array(sourcebot_diff_schema),
|
||||||
|
});
|
||||||
|
export type sourcebot_file_diff = z.infer<typeof sourcebot_file_diff_schema>;
|
||||||
|
|
||||||
|
export const sourcebot_pr_payload_schema = z.object({
|
||||||
|
title: z.string(),
|
||||||
|
description: z.string(),
|
||||||
|
hostDomain: z.string(),
|
||||||
|
owner: z.string(),
|
||||||
|
repo: z.string(),
|
||||||
|
file_diffs: z.array(sourcebot_file_diff_schema),
|
||||||
|
number: z.number(),
|
||||||
|
head_sha: z.string()
|
||||||
|
});
|
||||||
|
export type sourcebot_pr_payload = z.infer<typeof sourcebot_pr_payload_schema>;
|
||||||
|
|
||||||
|
export const sourcebot_context_schema = z.object({
|
||||||
|
type: z.enum(["pr_title", "pr_description", "pr_summary", "comment_chains", "file_content"]),
|
||||||
|
description: z.string().optional(),
|
||||||
|
context: z.string(),
|
||||||
|
});
|
||||||
|
export type sourcebot_context = z.infer<typeof sourcebot_context_schema>;
|
||||||
|
|
||||||
|
export const sourcebot_diff_review_schema = z.object({
|
||||||
|
line_start: z.number(),
|
||||||
|
line_end: z.number(),
|
||||||
|
review: z.string(),
|
||||||
|
});
|
||||||
|
export type sourcebot_diff_review = z.infer<typeof sourcebot_diff_review_schema>;
|
||||||
|
|
||||||
|
export const sourcebot_file_diff_review_schema = z.object({
|
||||||
|
filename: z.string(),
|
||||||
|
reviews: z.array(sourcebot_diff_review_schema),
|
||||||
|
});
|
||||||
|
export type sourcebot_file_diff_review = z.infer<typeof sourcebot_file_diff_review_schema>;
|
||||||
|
|
||||||
|
|
@ -1,28 +0,0 @@
|
||||||
# fly.toml app configuration file generated for sourcebot-staging on 2025-01-29T15:57:18-08:00
|
|
||||||
#
|
|
||||||
# See https://fly.io/docs/reference/configuration/ for information about how to use this file.
|
|
||||||
#
|
|
||||||
|
|
||||||
app = 'sourcebot-staging'
|
|
||||||
primary_region = 'sea'
|
|
||||||
|
|
||||||
[build]
|
|
||||||
image = 'ghcr.io/sourcebot-dev/sourcebot:staging'
|
|
||||||
|
|
||||||
[[mounts]]
|
|
||||||
source = 'sourcebot_staging_data'
|
|
||||||
destination = '/data'
|
|
||||||
initial_size = "60GB"
|
|
||||||
|
|
||||||
[http_service]
|
|
||||||
internal_port = 3000
|
|
||||||
force_https = true
|
|
||||||
auto_stop_machines = true
|
|
||||||
auto_start_machines = true
|
|
||||||
min_machines_running = 0
|
|
||||||
processes = ['app']
|
|
||||||
|
|
||||||
[[vm]]
|
|
||||||
memory = '4gb'
|
|
||||||
cpu_kind = 'performance'
|
|
||||||
cpus = 2
|
|
||||||
|
|
@ -22,7 +22,7 @@ stdout_logfile_maxbytes=0
|
||||||
redirect_stderr=true
|
redirect_stderr=true
|
||||||
|
|
||||||
[program:backend]
|
[program:backend]
|
||||||
command=./prefix-output.sh node packages/backend/dist/index.js --cacheDir %(ENV_DATA_CACHE_DIR)s
|
command=./prefix-output.sh node packages/backend/dist/index.js
|
||||||
autostart=true
|
autostart=true
|
||||||
autorestart=true
|
autorestart=true
|
||||||
startretries=3
|
startretries=3
|
||||||
|
|
|
||||||
446
yarn.lock
446
yarn.lock
|
|
@ -2253,6 +2253,75 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/app@npm:^15.1.6":
|
||||||
|
version: 15.1.6
|
||||||
|
resolution: "@octokit/app@npm:15.1.6"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/auth-app": "npm:^7.2.1"
|
||||||
|
"@octokit/auth-unauthenticated": "npm:^6.1.3"
|
||||||
|
"@octokit/core": "npm:^6.1.5"
|
||||||
|
"@octokit/oauth-app": "npm:^7.1.6"
|
||||||
|
"@octokit/plugin-paginate-rest": "npm:^12.0.0"
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
"@octokit/webhooks": "npm:^13.6.1"
|
||||||
|
checksum: 10c0/865098127d85cc58adda78c9b86cae58c502410a0d9c23d6eeabe633bc6c5e7d5f8901f243c519a0ce72342a8d08d73f120b32a864a8f6e4eeb3ad33326b6825
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/auth-app@npm:^7.2.1":
|
||||||
|
version: 7.2.1
|
||||||
|
resolution: "@octokit/auth-app@npm:7.2.1"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/auth-oauth-app": "npm:^8.1.4"
|
||||||
|
"@octokit/auth-oauth-user": "npm:^5.1.4"
|
||||||
|
"@octokit/request": "npm:^9.2.3"
|
||||||
|
"@octokit/request-error": "npm:^6.1.8"
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
toad-cache: "npm:^3.7.0"
|
||||||
|
universal-github-app-jwt: "npm:^2.2.0"
|
||||||
|
universal-user-agent: "npm:^7.0.0"
|
||||||
|
checksum: 10c0/da8890ad8ae554697a4d58427d7633c8d4d6f7acbfc14e98345b85035cca6773c393f5db5767b455dfc8de9bc5bac4da2d24e443cd48e701de11dd52fa128385
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/auth-oauth-app@npm:^8.1.3, @octokit/auth-oauth-app@npm:^8.1.4":
|
||||||
|
version: 8.1.4
|
||||||
|
resolution: "@octokit/auth-oauth-app@npm:8.1.4"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/auth-oauth-device": "npm:^7.1.5"
|
||||||
|
"@octokit/auth-oauth-user": "npm:^5.1.4"
|
||||||
|
"@octokit/request": "npm:^9.2.3"
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
universal-user-agent: "npm:^7.0.0"
|
||||||
|
checksum: 10c0/2e50711be9ee6c3bf85cf1d58a1d8ae56c36eb894dcfdacabda92b9454b2c49bccc56fb1a989d3e56625885f1ef36278cc01f65c01cde6e3b505b363eac66cc6
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/auth-oauth-device@npm:^7.1.5":
|
||||||
|
version: 7.1.5
|
||||||
|
resolution: "@octokit/auth-oauth-device@npm:7.1.5"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/oauth-methods": "npm:^5.1.5"
|
||||||
|
"@octokit/request": "npm:^9.2.3"
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
universal-user-agent: "npm:^7.0.0"
|
||||||
|
checksum: 10c0/f93a67473c58e8b855af15c7300a0937c9d3c6ea898e5e810f2f9762100c6cee22ae52e18c7f926b0e4c6c52573751d4c4ab6294c44116bed2d9fdde5cbdd35d
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/auth-oauth-user@npm:^5.1.3, @octokit/auth-oauth-user@npm:^5.1.4":
|
||||||
|
version: 5.1.4
|
||||||
|
resolution: "@octokit/auth-oauth-user@npm:5.1.4"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/auth-oauth-device": "npm:^7.1.5"
|
||||||
|
"@octokit/oauth-methods": "npm:^5.1.5"
|
||||||
|
"@octokit/request": "npm:^9.2.3"
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
universal-user-agent: "npm:^7.0.0"
|
||||||
|
checksum: 10c0/2bb597b2e50fbd5c03bee3a276efa72b03105aff1d9e243c18a71b72d9fe4ad4b1cee52c2df3e022c4169c7c1d37ab14d05455d5de982528914af965e14b763a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@octokit/auth-token@npm:^5.0.0":
|
"@octokit/auth-token@npm:^5.0.0":
|
||||||
version: 5.1.2
|
version: 5.1.2
|
||||||
resolution: "@octokit/auth-token@npm:5.1.2"
|
resolution: "@octokit/auth-token@npm:5.1.2"
|
||||||
|
|
@ -2260,6 +2329,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/auth-unauthenticated@npm:^6.1.2, @octokit/auth-unauthenticated@npm:^6.1.3":
|
||||||
|
version: 6.1.3
|
||||||
|
resolution: "@octokit/auth-unauthenticated@npm:6.1.3"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/request-error": "npm:^6.1.8"
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
checksum: 10c0/60639987fa30e68c4ecd98dd9f1604b3f4368384979cdfa2ab9ea2d0b04c50b42a990e67167cf2a0098205a994b3a80d76b23bb0de4c8c956a898b977f5ce7d0
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@octokit/core@npm:^6.1.4":
|
"@octokit/core@npm:^6.1.4":
|
||||||
version: 6.1.4
|
version: 6.1.4
|
||||||
resolution: "@octokit/core@npm:6.1.4"
|
resolution: "@octokit/core@npm:6.1.4"
|
||||||
|
|
@ -2275,6 +2354,21 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/core@npm:^6.1.5":
|
||||||
|
version: 6.1.5
|
||||||
|
resolution: "@octokit/core@npm:6.1.5"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/auth-token": "npm:^5.0.0"
|
||||||
|
"@octokit/graphql": "npm:^8.2.2"
|
||||||
|
"@octokit/request": "npm:^9.2.3"
|
||||||
|
"@octokit/request-error": "npm:^6.1.8"
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
before-after-hook: "npm:^3.0.2"
|
||||||
|
universal-user-agent: "npm:^7.0.0"
|
||||||
|
checksum: 10c0/c89ea754cc33da740fdd69fadb971b4b65c89971bba4e8ad545d3ea7aba79759ee3e195c3b72e7df78f14b8b1d392bddc56e7c385d48b5272319ea6a0246ac7c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@octokit/endpoint@npm:^10.1.3":
|
"@octokit/endpoint@npm:^10.1.3":
|
||||||
version: 10.1.3
|
version: 10.1.3
|
||||||
resolution: "@octokit/endpoint@npm:10.1.3"
|
resolution: "@octokit/endpoint@npm:10.1.3"
|
||||||
|
|
@ -2285,6 +2379,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/endpoint@npm:^10.1.4":
|
||||||
|
version: 10.1.4
|
||||||
|
resolution: "@octokit/endpoint@npm:10.1.4"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
universal-user-agent: "npm:^7.0.2"
|
||||||
|
checksum: 10c0/bf7cca71a05dc4751df658588e32642e59c98768e7509521226b997ea4837e2d16efd35c391231c76d888226f4daf80e6a9f347dee01a69f490253654dada581
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@octokit/graphql@npm:^8.1.2":
|
"@octokit/graphql@npm:^8.1.2":
|
||||||
version: 8.2.1
|
version: 8.2.1
|
||||||
resolution: "@octokit/graphql@npm:8.2.1"
|
resolution: "@octokit/graphql@npm:8.2.1"
|
||||||
|
|
@ -2296,6 +2400,52 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/graphql@npm:^8.2.2":
|
||||||
|
version: 8.2.2
|
||||||
|
resolution: "@octokit/graphql@npm:8.2.2"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/request": "npm:^9.2.3"
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
universal-user-agent: "npm:^7.0.0"
|
||||||
|
checksum: 10c0/29cd5af5ed04e416d28798a11907ab861dc73c0af47f8c9c3f4183d81d2e77d88228643825538acc81e7015f78d891f84107929019a673b06a6b38ccea6a24e0
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/oauth-app@npm:^7.1.6":
|
||||||
|
version: 7.1.6
|
||||||
|
resolution: "@octokit/oauth-app@npm:7.1.6"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/auth-oauth-app": "npm:^8.1.3"
|
||||||
|
"@octokit/auth-oauth-user": "npm:^5.1.3"
|
||||||
|
"@octokit/auth-unauthenticated": "npm:^6.1.2"
|
||||||
|
"@octokit/core": "npm:^6.1.4"
|
||||||
|
"@octokit/oauth-authorization-url": "npm:^7.1.1"
|
||||||
|
"@octokit/oauth-methods": "npm:^5.1.4"
|
||||||
|
"@types/aws-lambda": "npm:^8.10.83"
|
||||||
|
universal-user-agent: "npm:^7.0.0"
|
||||||
|
checksum: 10c0/75264f6cb9336baf815bb85ea450d69c5d33eb70754065c9c5307b10d0efec2d76bb17c7788346dfb8b5e4ad0205e6df841b9c709eaf077390bba793787841f5
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/oauth-authorization-url@npm:^7.0.0, @octokit/oauth-authorization-url@npm:^7.1.1":
|
||||||
|
version: 7.1.1
|
||||||
|
resolution: "@octokit/oauth-authorization-url@npm:7.1.1"
|
||||||
|
checksum: 10c0/a2723dde503693d4b0793bc43988d7445bdbd1a4e4994f4e94e635816c87b12a3058609eb5982d91783ddf6cdf663ccdb954b5d05efdc59cb66bc0456d7ba370
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/oauth-methods@npm:^5.1.4, @octokit/oauth-methods@npm:^5.1.5":
|
||||||
|
version: 5.1.5
|
||||||
|
resolution: "@octokit/oauth-methods@npm:5.1.5"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/oauth-authorization-url": "npm:^7.0.0"
|
||||||
|
"@octokit/request": "npm:^9.2.3"
|
||||||
|
"@octokit/request-error": "npm:^6.1.8"
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
checksum: 10c0/2b1c5f9ef0fcdb2f19fd864303a67bdda296fcb2cc058efc51bf3fbb3cb582475a5532eab05bd7a57277607730fa4a7796431564693fffdb9c4cb2b471484a5c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@octokit/openapi-types@npm:^24.2.0":
|
"@octokit/openapi-types@npm:^24.2.0":
|
||||||
version: 24.2.0
|
version: 24.2.0
|
||||||
resolution: "@octokit/openapi-types@npm:24.2.0"
|
resolution: "@octokit/openapi-types@npm:24.2.0"
|
||||||
|
|
@ -2303,6 +2453,29 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/openapi-types@npm:^25.0.0":
|
||||||
|
version: 25.0.0
|
||||||
|
resolution: "@octokit/openapi-types@npm:25.0.0"
|
||||||
|
checksum: 10c0/59c9e5998e08cecec155b776c93d8f6f88ab1a812add61cc65f3de8f3744201565545eac308083d18c9fa330a4381a27bcd771a311ac0348d3590a00f333f233
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/openapi-webhooks-types@npm:11.0.0":
|
||||||
|
version: 11.0.0
|
||||||
|
resolution: "@octokit/openapi-webhooks-types@npm:11.0.0"
|
||||||
|
checksum: 10c0/cea59ba6b976a242fa4e6bedfab7e6fc3437381557d2c1876ca3aea5f6d4231559a378f9bc35e09593cb2d466afb4a2415be66b960f3e0a38b65b8b9f22ff90e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/plugin-paginate-graphql@npm:^5.2.4":
|
||||||
|
version: 5.2.4
|
||||||
|
resolution: "@octokit/plugin-paginate-graphql@npm:5.2.4"
|
||||||
|
peerDependencies:
|
||||||
|
"@octokit/core": ">=6"
|
||||||
|
checksum: 10c0/30601cf11d78e5683098d68fbff071a3d20b1e23758f40b1f43fbc93f69b3d0e07f2c9aaaaee113e586af7f604e809ba93702d932b1a4ea65998c7ab39a40a54
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@octokit/plugin-paginate-rest@npm:^11.4.2":
|
"@octokit/plugin-paginate-rest@npm:^11.4.2":
|
||||||
version: 11.6.0
|
version: 11.6.0
|
||||||
resolution: "@octokit/plugin-paginate-rest@npm:11.6.0"
|
resolution: "@octokit/plugin-paginate-rest@npm:11.6.0"
|
||||||
|
|
@ -2314,6 +2487,17 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/plugin-paginate-rest@npm:^12.0.0":
|
||||||
|
version: 12.0.0
|
||||||
|
resolution: "@octokit/plugin-paginate-rest@npm:12.0.0"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
peerDependencies:
|
||||||
|
"@octokit/core": ">=6"
|
||||||
|
checksum: 10c0/4ed04e8c111ac8cfb0692f917fe09ff6484b7436f0605c661e8051c6fb281c0260c9b067c1422529b948e53b22221b0f7664e2d10a28dcd9db14465c02c7182f
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@octokit/plugin-request-log@npm:^5.3.1":
|
"@octokit/plugin-request-log@npm:^5.3.1":
|
||||||
version: 5.3.1
|
version: 5.3.1
|
||||||
resolution: "@octokit/plugin-request-log@npm:5.3.1"
|
resolution: "@octokit/plugin-request-log@npm:5.3.1"
|
||||||
|
|
@ -2334,6 +2518,42 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/plugin-rest-endpoint-methods@npm:^14.0.0":
|
||||||
|
version: 14.0.0
|
||||||
|
resolution: "@octokit/plugin-rest-endpoint-methods@npm:14.0.0"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
peerDependencies:
|
||||||
|
"@octokit/core": ">=6"
|
||||||
|
checksum: 10c0/c3f26c5277d4aa0c898d8fdbf84326943ea80496e6f60ae34834415384ab629e1e3702d1ed82d40c31a7370edfcb5fa9fe434b0357b302b3be309879bad1d4e6
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/plugin-retry@npm:^7.2.1":
|
||||||
|
version: 7.2.1
|
||||||
|
resolution: "@octokit/plugin-retry@npm:7.2.1"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/request-error": "npm:^6.1.8"
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
bottleneck: "npm:^2.15.3"
|
||||||
|
peerDependencies:
|
||||||
|
"@octokit/core": ">=6"
|
||||||
|
checksum: 10c0/0cac8aa32bfe9612cbaba36f51382c69c882ef7927e1deb4b166fe664959887e952205adbf8b9ff461e0128ac3e1bd807ca58e38041a55ddb3214397584f0406
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/plugin-throttling@npm:^10.0.0":
|
||||||
|
version: 10.0.0
|
||||||
|
resolution: "@octokit/plugin-throttling@npm:10.0.0"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
bottleneck: "npm:^2.15.3"
|
||||||
|
peerDependencies:
|
||||||
|
"@octokit/core": ^6.1.3
|
||||||
|
checksum: 10c0/60294f89bcc03b034fce557dffcb0dba1b02d1fa1834b3b4f542f8635750df4bd23fc143f7c71f802a22a1aaed089c5da77979e6803abe11908b1c91aa1ba419
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@octokit/request-error@npm:^6.1.7":
|
"@octokit/request-error@npm:^6.1.7":
|
||||||
version: 6.1.7
|
version: 6.1.7
|
||||||
resolution: "@octokit/request-error@npm:6.1.7"
|
resolution: "@octokit/request-error@npm:6.1.7"
|
||||||
|
|
@ -2343,6 +2563,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/request-error@npm:^6.1.8":
|
||||||
|
version: 6.1.8
|
||||||
|
resolution: "@octokit/request-error@npm:6.1.8"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
checksum: 10c0/02aa5bfebb5b1b9e152558b4a6f4f7dcb149b41538778ffe0fce3395fd0da5c0862311a78e94723435667581b2a58a7cefa458cf7aa19ae2948ae419276f7ee1
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@octokit/request@npm:^9.2.1, @octokit/request@npm:^9.2.2":
|
"@octokit/request@npm:^9.2.1, @octokit/request@npm:^9.2.2":
|
||||||
version: 9.2.2
|
version: 9.2.2
|
||||||
resolution: "@octokit/request@npm:9.2.2"
|
resolution: "@octokit/request@npm:9.2.2"
|
||||||
|
|
@ -2356,6 +2585,19 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/request@npm:^9.2.3":
|
||||||
|
version: 9.2.3
|
||||||
|
resolution: "@octokit/request@npm:9.2.3"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/endpoint": "npm:^10.1.4"
|
||||||
|
"@octokit/request-error": "npm:^6.1.8"
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
fast-content-type-parse: "npm:^2.0.0"
|
||||||
|
universal-user-agent: "npm:^7.0.2"
|
||||||
|
checksum: 10c0/96067fc9a5f30f2faa00f08015309930561c3ea0536b543e1c91c475f965eabc81c48fc27d401681ebdb3f6c1acc5d46eaa69163ab98b0faa08be1c02ea5b684
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@octokit/rest@npm:^21.0.2":
|
"@octokit/rest@npm:^21.0.2":
|
||||||
version: 21.1.1
|
version: 21.1.1
|
||||||
resolution: "@octokit/rest@npm:21.1.1"
|
resolution: "@octokit/rest@npm:21.1.1"
|
||||||
|
|
@ -2377,6 +2619,33 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/types@npm:^14.0.0":
|
||||||
|
version: 14.0.0
|
||||||
|
resolution: "@octokit/types@npm:14.0.0"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/openapi-types": "npm:^25.0.0"
|
||||||
|
checksum: 10c0/c82da635fe99f265dbef7bf954d45a23ca7ce9c6fc9a8478c247b5435799e5d0eab3ff42f085785ee0882b2de293cab0ab831b379c66f41d00b78412df850ba4
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/webhooks-methods@npm:^5.1.1":
|
||||||
|
version: 5.1.1
|
||||||
|
resolution: "@octokit/webhooks-methods@npm:5.1.1"
|
||||||
|
checksum: 10c0/837aa49dbc7f8bc01448f4eaea32cfb0c1cbfa0b4ac570f7bcda385c71f43e4be05e91a3fb63708448410b27e246570fde42056b6b87d755154d84eff5a6500c
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
|
"@octokit/webhooks@npm:^13.6.1":
|
||||||
|
version: 13.8.2
|
||||||
|
resolution: "@octokit/webhooks@npm:13.8.2"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/openapi-webhooks-types": "npm:11.0.0"
|
||||||
|
"@octokit/request-error": "npm:^6.1.7"
|
||||||
|
"@octokit/webhooks-methods": "npm:^5.1.1"
|
||||||
|
checksum: 10c0/5053ab9cff8afe4cd6e7d7a41af3f1b0c0ccc5058482577aa82bb8e5003f3002896c68bd59d7da363204c2d6baa4cca73ed684bb7a5a9286ca4b43172cd1fe9e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@opentelemetry/api-logs@npm:0.57.2":
|
"@opentelemetry/api-logs@npm:0.57.2":
|
||||||
version: 0.57.2
|
version: 0.57.2
|
||||||
resolution: "@opentelemetry/api-logs@npm:0.57.2"
|
resolution: "@opentelemetry/api-logs@npm:0.57.2"
|
||||||
|
|
@ -5401,6 +5670,9 @@ __metadata:
|
||||||
next-themes: "npm:^0.3.0"
|
next-themes: "npm:^0.3.0"
|
||||||
nodemailer: "npm:^6.10.0"
|
nodemailer: "npm:^6.10.0"
|
||||||
npm-run-all: "npm:^4.1.5"
|
npm-run-all: "npm:^4.1.5"
|
||||||
|
octokit: "npm:^4.1.3"
|
||||||
|
openai: "npm:^4.98.0"
|
||||||
|
parse-diff: "npm:^0.11.1"
|
||||||
postcss: "npm:^8"
|
postcss: "npm:^8"
|
||||||
posthog-js: "npm:^1.161.5"
|
posthog-js: "npm:^1.161.5"
|
||||||
pretty-bytes: "npm:^6.1.1"
|
pretty-bytes: "npm:^6.1.1"
|
||||||
|
|
@ -5426,6 +5698,7 @@ __metadata:
|
||||||
vite-tsconfig-paths: "npm:^5.1.3"
|
vite-tsconfig-paths: "npm:^5.1.3"
|
||||||
vitest: "npm:^2.1.5"
|
vitest: "npm:^2.1.5"
|
||||||
zod: "npm:^3.24.3"
|
zod: "npm:^3.24.3"
|
||||||
|
zod-to-json-schema: "npm:^3.24.5"
|
||||||
languageName: unknown
|
languageName: unknown
|
||||||
linkType: soft
|
linkType: soft
|
||||||
|
|
||||||
|
|
@ -5606,6 +5879,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/aws-lambda@npm:^8.10.83":
|
||||||
|
version: 8.10.149
|
||||||
|
resolution: "@types/aws-lambda@npm:8.10.149"
|
||||||
|
checksum: 10c0/9ef41214a1b69fa30d89cab575429793f1ccc49cfe3a7aa75228aef31a202bb6d2c306a5b33def61ef29e0d0a1a324412bf6a4fa5a615e61117685584a394047
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/body-parser@npm:*":
|
"@types/body-parser@npm:*":
|
||||||
version: 1.19.5
|
version: 1.19.5
|
||||||
resolution: "@types/body-parser@npm:1.19.5"
|
resolution: "@types/body-parser@npm:1.19.5"
|
||||||
|
|
@ -5749,6 +6029,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/node-fetch@npm:^2.6.4":
|
||||||
|
version: 2.6.12
|
||||||
|
resolution: "@types/node-fetch@npm:2.6.12"
|
||||||
|
dependencies:
|
||||||
|
"@types/node": "npm:*"
|
||||||
|
form-data: "npm:^4.0.0"
|
||||||
|
checksum: 10c0/7693acad5499b7df2d1727d46cff092a63896dc04645f36b973dd6dd754a59a7faba76fcb777bdaa35d80625c6a9dd7257cca9c401a4bab03b04480cda7fd1af
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/node@npm:*, @types/node@npm:>=10.0.0, @types/node@npm:>=8.1.0, @types/node@npm:^22.7.5":
|
"@types/node@npm:*, @types/node@npm:>=10.0.0, @types/node@npm:>=8.1.0, @types/node@npm:^22.7.5":
|
||||||
version: 22.13.11
|
version: 22.13.11
|
||||||
resolution: "@types/node@npm:22.13.11"
|
resolution: "@types/node@npm:22.13.11"
|
||||||
|
|
@ -5758,6 +6048,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"@types/node@npm:^18.11.18":
|
||||||
|
version: 18.19.100
|
||||||
|
resolution: "@types/node@npm:18.19.100"
|
||||||
|
dependencies:
|
||||||
|
undici-types: "npm:~5.26.4"
|
||||||
|
checksum: 10c0/5524303171eee6788df45d736f5783b5bea27803a596b9cd5669f45487a619e5d8d41d56dd55b8c85c677ffd7c045edd8daea8c4b37e70290bee2a482fc605f6
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"@types/node@npm:^20":
|
"@types/node@npm:^20":
|
||||||
version: 20.17.25
|
version: 20.17.25
|
||||||
resolution: "@types/node@npm:20.17.25"
|
resolution: "@types/node@npm:20.17.25"
|
||||||
|
|
@ -6364,6 +6663,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"abort-controller@npm:^3.0.0":
|
||||||
|
version: 3.0.0
|
||||||
|
resolution: "abort-controller@npm:3.0.0"
|
||||||
|
dependencies:
|
||||||
|
event-target-shim: "npm:^5.0.0"
|
||||||
|
checksum: 10c0/90ccc50f010250152509a344eb2e71977fbf8db0ab8f1061197e3275ddf6c61a41a6edfd7b9409c664513131dd96e962065415325ef23efa5db931b382d24ca5
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"accepts@npm:^2.0.0":
|
"accepts@npm:^2.0.0":
|
||||||
version: 2.0.0
|
version: 2.0.0
|
||||||
resolution: "accepts@npm:2.0.0"
|
resolution: "accepts@npm:2.0.0"
|
||||||
|
|
@ -6427,6 +6735,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"agentkeepalive@npm:^4.2.1":
|
||||||
|
version: 4.6.0
|
||||||
|
resolution: "agentkeepalive@npm:4.6.0"
|
||||||
|
dependencies:
|
||||||
|
humanize-ms: "npm:^1.2.1"
|
||||||
|
checksum: 10c0/235c182432f75046835b05f239708107138a40103deee23b6a08caee5136873709155753b394ec212e49e60e94a378189562cb01347765515cff61b692c69187
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"ajv@npm:^6.12.4":
|
"ajv@npm:^6.12.4":
|
||||||
version: 6.12.6
|
version: 6.12.6
|
||||||
resolution: "ajv@npm:6.12.6"
|
resolution: "ajv@npm:6.12.6"
|
||||||
|
|
@ -6831,6 +7148,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"bottleneck@npm:^2.15.3":
|
||||||
|
version: 2.19.5
|
||||||
|
resolution: "bottleneck@npm:2.19.5"
|
||||||
|
checksum: 10c0/b0f72e45b2e0f56a21ba720183f16bef8e693452fb0495d997fa354e42904353a94bd8fd429868e6751bc85e54b6755190519eed5a0ae0a94a5185209ae7c6d0
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"brace-expansion@npm:^1.1.7":
|
"brace-expansion@npm:^1.1.7":
|
||||||
version: 1.1.11
|
version: 1.1.11
|
||||||
resolution: "brace-expansion@npm:1.1.11"
|
resolution: "brace-expansion@npm:1.1.11"
|
||||||
|
|
@ -8982,6 +9306,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"event-target-shim@npm:^5.0.0":
|
||||||
|
version: 5.0.1
|
||||||
|
resolution: "event-target-shim@npm:5.0.1"
|
||||||
|
checksum: 10c0/0255d9f936215fd206156fd4caa9e8d35e62075d720dc7d847e89b417e5e62cf1ce6c9b4e0a1633a9256de0efefaf9f8d26924b1f3c8620cffb9db78e7d3076b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"eventsource-parser@npm:^3.0.1":
|
"eventsource-parser@npm:^3.0.1":
|
||||||
version: 3.0.1
|
version: 3.0.1
|
||||||
resolution: "eventsource-parser@npm:3.0.1"
|
resolution: "eventsource-parser@npm:3.0.1"
|
||||||
|
|
@ -9303,6 +9634,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"form-data-encoder@npm:1.7.2":
|
||||||
|
version: 1.7.2
|
||||||
|
resolution: "form-data-encoder@npm:1.7.2"
|
||||||
|
checksum: 10c0/56553768037b6d55d9de524f97fe70555f0e415e781cb56fc457a68263de3d40fadea2304d4beef2d40b1a851269bd7854e42c362107071892cb5238debe9464
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"form-data@npm:^4.0.0":
|
"form-data@npm:^4.0.0":
|
||||||
version: 4.0.2
|
version: 4.0.2
|
||||||
resolution: "form-data@npm:4.0.2"
|
resolution: "form-data@npm:4.0.2"
|
||||||
|
|
@ -9315,6 +9653,16 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"formdata-node@npm:^4.3.2":
|
||||||
|
version: 4.4.1
|
||||||
|
resolution: "formdata-node@npm:4.4.1"
|
||||||
|
dependencies:
|
||||||
|
node-domexception: "npm:1.0.0"
|
||||||
|
web-streams-polyfill: "npm:4.0.0-beta.3"
|
||||||
|
checksum: 10c0/74151e7b228ffb33b565cec69182694ad07cc3fdd9126a8240468bb70a8ba66e97e097072b60bcb08729b24c7ce3fd3e0bd7f1f80df6f9f662b9656786e76f6a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"forwarded-parse@npm:2.1.2":
|
"forwarded-parse@npm:2.1.2":
|
||||||
version: 2.1.2
|
version: 2.1.2
|
||||||
resolution: "forwarded-parse@npm:2.1.2"
|
resolution: "forwarded-parse@npm:2.1.2"
|
||||||
|
|
@ -9891,6 +10239,15 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"humanize-ms@npm:^1.2.1":
|
||||||
|
version: 1.2.1
|
||||||
|
resolution: "humanize-ms@npm:1.2.1"
|
||||||
|
dependencies:
|
||||||
|
ms: "npm:^2.0.0"
|
||||||
|
checksum: 10c0/f34a2c20161d02303c2807badec2f3b49cbfbbb409abd4f95a07377ae01cfe6b59e3d15ac609cffcd8f2521f0eb37b7e1091acf65da99aa2a4f1ad63c21e7e7a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"iconv-lite@npm:0.4.24":
|
"iconv-lite@npm:0.4.24":
|
||||||
version: 0.4.24
|
version: 0.4.24
|
||||||
resolution: "iconv-lite@npm:0.4.24"
|
resolution: "iconv-lite@npm:0.4.24"
|
||||||
|
|
@ -11295,7 +11652,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"ms@npm:2.1.3, ms@npm:^2.1.1, ms@npm:^2.1.3":
|
"ms@npm:2.1.3, ms@npm:^2.0.0, ms@npm:^2.1.1, ms@npm:^2.1.3":
|
||||||
version: 2.1.3
|
version: 2.1.3
|
||||||
resolution: "ms@npm:2.1.3"
|
resolution: "ms@npm:2.1.3"
|
||||||
checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48
|
checksum: 10c0/d924b57e7312b3b63ad21fc5b3dc0af5e78d61a1fc7cfb5457edaf26326bf62be5307cc87ffb6862ef1c2b33b0233cdb5d4f01c4c958cc0d660948b65a287a48
|
||||||
|
|
@ -11581,6 +11938,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"node-domexception@npm:1.0.0":
|
||||||
|
version: 1.0.0
|
||||||
|
resolution: "node-domexception@npm:1.0.0"
|
||||||
|
checksum: 10c0/5e5d63cda29856402df9472335af4bb13875e1927ad3be861dc5ebde38917aecbf9ae337923777af52a48c426b70148815e890a5d72760f1b4d758cc671b1a2b
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"node-fetch@npm:^2.6.7, node-fetch@npm:^2.7.0":
|
"node-fetch@npm:^2.6.7, node-fetch@npm:^2.7.0":
|
||||||
version: 2.7.0
|
version: 2.7.0
|
||||||
resolution: "node-fetch@npm:2.7.0"
|
resolution: "node-fetch@npm:2.7.0"
|
||||||
|
|
@ -11830,6 +12194,24 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"octokit@npm:^4.1.3":
|
||||||
|
version: 4.1.3
|
||||||
|
resolution: "octokit@npm:4.1.3"
|
||||||
|
dependencies:
|
||||||
|
"@octokit/app": "npm:^15.1.6"
|
||||||
|
"@octokit/core": "npm:^6.1.5"
|
||||||
|
"@octokit/oauth-app": "npm:^7.1.6"
|
||||||
|
"@octokit/plugin-paginate-graphql": "npm:^5.2.4"
|
||||||
|
"@octokit/plugin-paginate-rest": "npm:^12.0.0"
|
||||||
|
"@octokit/plugin-rest-endpoint-methods": "npm:^14.0.0"
|
||||||
|
"@octokit/plugin-retry": "npm:^7.2.1"
|
||||||
|
"@octokit/plugin-throttling": "npm:^10.0.0"
|
||||||
|
"@octokit/request-error": "npm:^6.1.8"
|
||||||
|
"@octokit/types": "npm:^14.0.0"
|
||||||
|
checksum: 10c0/a35352dff1d7bacf8123e491489650c29b830a765f78113064edd6bd0aad0e58e8933874394892972fb8b0e43369b6f7a7b354426c61f4d9fc37408891fde582
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"on-finished@npm:2.4.1, on-finished@npm:^2.4.1":
|
"on-finished@npm:2.4.1, on-finished@npm:^2.4.1":
|
||||||
version: 2.4.1
|
version: 2.4.1
|
||||||
resolution: "on-finished@npm:2.4.1"
|
resolution: "on-finished@npm:2.4.1"
|
||||||
|
|
@ -11877,6 +12259,31 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"openai@npm:^4.98.0":
|
||||||
|
version: 4.98.0
|
||||||
|
resolution: "openai@npm:4.98.0"
|
||||||
|
dependencies:
|
||||||
|
"@types/node": "npm:^18.11.18"
|
||||||
|
"@types/node-fetch": "npm:^2.6.4"
|
||||||
|
abort-controller: "npm:^3.0.0"
|
||||||
|
agentkeepalive: "npm:^4.2.1"
|
||||||
|
form-data-encoder: "npm:1.7.2"
|
||||||
|
formdata-node: "npm:^4.3.2"
|
||||||
|
node-fetch: "npm:^2.6.7"
|
||||||
|
peerDependencies:
|
||||||
|
ws: ^8.18.0
|
||||||
|
zod: ^3.23.8
|
||||||
|
peerDependenciesMeta:
|
||||||
|
ws:
|
||||||
|
optional: true
|
||||||
|
zod:
|
||||||
|
optional: true
|
||||||
|
bin:
|
||||||
|
openai: bin/cli
|
||||||
|
checksum: 10c0/399f07cd04c47d05be89cbcf3edb98650177ca09322ae664ade347bd56830cc0423834b4635341950bd9af59fdf203d3fad1de7927f4d8d2449b08c642c0ee3e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"openapi-fetch@npm:^0.13.4":
|
"openapi-fetch@npm:^0.13.4":
|
||||||
version: 0.13.5
|
version: 0.13.5
|
||||||
resolution: "openapi-fetch@npm:0.13.5"
|
resolution: "openapi-fetch@npm:0.13.5"
|
||||||
|
|
@ -11976,6 +12383,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"parse-diff@npm:^0.11.1":
|
||||||
|
version: 0.11.1
|
||||||
|
resolution: "parse-diff@npm:0.11.1"
|
||||||
|
checksum: 10c0/b8a488039f535e0ddaf1cfd4a13c2adc6d142f4e6263de6dc603f9762b59da89703a8f0dc8aacb7c7c66cdbdd2d075a57c63813fb74f66c9b8f5fe8ad2e89689
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"parse-json@npm:^4.0.0":
|
"parse-json@npm:^4.0.0":
|
||||||
version: 4.0.0
|
version: 4.0.0
|
||||||
resolution: "parse-json@npm:4.0.0"
|
resolution: "parse-json@npm:4.0.0"
|
||||||
|
|
@ -14587,6 +15001,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"toad-cache@npm:^3.7.0":
|
||||||
|
version: 3.7.0
|
||||||
|
resolution: "toad-cache@npm:3.7.0"
|
||||||
|
checksum: 10c0/7dae2782ee20b22c9798bb8b71dec7ec6a0091021d2ea9dd6e8afccab6b65b358fdba49a02209fac574499702e2c000660721516c87c2538d1b2c0ba03e8c0c3
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"toidentifier@npm:1.0.1":
|
"toidentifier@npm:1.0.1":
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
resolution: "toidentifier@npm:1.0.1"
|
resolution: "toidentifier@npm:1.0.1"
|
||||||
|
|
@ -14920,6 +15341,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"undici-types@npm:~5.26.4":
|
||||||
|
version: 5.26.5
|
||||||
|
resolution: "undici-types@npm:5.26.5"
|
||||||
|
checksum: 10c0/bb673d7876c2d411b6eb6c560e0c571eef4a01c1c19925175d16e3a30c4c428181fb8d7ae802a261f283e4166a0ac435e2f505743aa9e45d893f9a3df017b501
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"undici-types@npm:~6.19.2":
|
"undici-types@npm:~6.19.2":
|
||||||
version: 6.19.8
|
version: 6.19.8
|
||||||
resolution: "undici-types@npm:6.19.8"
|
resolution: "undici-types@npm:6.19.8"
|
||||||
|
|
@ -15000,6 +15428,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"universal-github-app-jwt@npm:^2.2.0":
|
||||||
|
version: 2.2.2
|
||||||
|
resolution: "universal-github-app-jwt@npm:2.2.2"
|
||||||
|
checksum: 10c0/7ae5f031fb89c01a4407459b764c5e6341d725d436e1ceec161f9b754dd4883d9704cc8de53d5b6314b7e1bef8dbc7561799fc23001e706f213d468c17026fb6
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"universal-user-agent@npm:^7.0.0, universal-user-agent@npm:^7.0.2":
|
"universal-user-agent@npm:^7.0.0, universal-user-agent@npm:^7.0.2":
|
||||||
version: 7.0.2
|
version: 7.0.2
|
||||||
resolution: "universal-user-agent@npm:7.0.2"
|
resolution: "universal-user-agent@npm:7.0.2"
|
||||||
|
|
@ -15314,6 +15749,13 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"web-streams-polyfill@npm:4.0.0-beta.3":
|
||||||
|
version: 4.0.0-beta.3
|
||||||
|
resolution: "web-streams-polyfill@npm:4.0.0-beta.3"
|
||||||
|
checksum: 10c0/a9596779db2766990117ed3a158e0b0e9f69b887a6d6ba0779940259e95f99dc3922e534acc3e5a117b5f5905300f527d6fbf8a9f0957faf1d8e585ce3452e8e
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"web-vitals@npm:^4.2.4":
|
"web-vitals@npm:^4.2.4":
|
||||||
version: 4.2.4
|
version: 4.2.4
|
||||||
resolution: "web-vitals@npm:4.2.4"
|
resolution: "web-vitals@npm:4.2.4"
|
||||||
|
|
@ -15652,7 +16094,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"zod-to-json-schema@npm:^3.24.1":
|
"zod-to-json-schema@npm:^3.24.1, zod-to-json-schema@npm:^3.24.5":
|
||||||
version: 3.24.5
|
version: 3.24.5
|
||||||
resolution: "zod-to-json-schema@npm:3.24.5"
|
resolution: "zod-to-json-schema@npm:3.24.5"
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue