diff --git a/.env.example b/.env.example new file mode 100644 index 00000000..a0a6bb48 --- /dev/null +++ b/.env.example @@ -0,0 +1,123 @@ +# === LangSmith === +LANGSMITH_API_KEY_PROD="" # From step 4a +# NOTE: LANGCHAIN_TRACING_V2 and LANGCHAIN_PROJECT are RESERVED on LangGraph Platform +# (LangSmith deployments) — the platform sets them itself and rejects the deploy if +# you provide them. Only set them for local/self-hosted runs, not in a deployment's env. +LANGSMITH_TENANT_ID_PROD="" +LANGSMITH_TRACING_PROJECT_ID_PROD="" # Fallback project ID for "View trace" links; graphs trace into the open-swe-agent / open-swe-review projects by name +LANGSMITH_URL_PROD="https://smith.langchain.com" + +# === LLM === +LLM_MODEL_ID="" # Default model, e.g. "bedrock_converse:us.anthropic.claude-opus-4-8" +ANTHROPIC_API_KEY="" # Anthropic API key +OPENAI_API_KEY="" # OpenAI API key (when using openai: models) +GOOGLE_API_KEY="" # Google AI API key (when using google_genai: models) +FIREWORKS_API_KEY="" # Fireworks API key (when using fireworks: models) +# AWS credentials for Bedrock (when using bedrock_converse: models). Region defaults to us-east-1. +AWS_ACCESS_KEY_ID="" +AWS_SECRET_ACCESS_KEY="" + +# === GitHub App (required) === +GITHUB_APP_ID="" # From step 3c +GITHUB_APP_PRIVATE_KEY="-----BEGIN RSA PRIVATE KEY----- +... +-----END RSA PRIVATE KEY----- +" +GITHUB_APP_INSTALLATION_ID="" # From step 3d + +# === GitHub Webhook (required) === +GITHUB_WEBHOOK_SECRET="" # The secret you generated in step 3b + +# === Dashboard GitHub OAuth (required for the dashboard) === +# Direct GitHub OAuth used by the dashboard login flow (not via LangSmith). +GITHUB_APP_CLIENT_ID="" # From step 3c +GITHUB_APP_CLIENT_SECRET="" # From step 3c + +# === Agent-runtime GitHub OAuth via LangSmith (optional) === +# Without these, all agent operations use the GitHub App's bot token. +# With these, each agent run authenticates as the triggering user. +GITHUB_OAUTH_PROVIDER_ID="" # The provider ID from steps 3a / 4b +# Secret used to mint short-lived service JWTs that ask LangSmith to resolve a +# specific user's GitHub token. Needed for per-user token resolution in deployed mode. +X_SERVICE_AUTH_JWT_SECRET="" + +# === Repo Allowlist (optional) === +# Comma-separated list of GitHub orgs the agent is allowed to operate on. +# Also gates dashboard login to members of these orgs (requires the GitHub App's +# Organization -> Members: Read-only permission; without it, all dashboard logins are rejected). +# Leave empty to allow all orgs. +ALLOWED_GITHUB_ORGS="" # e.g. "my-org,my-other-org" +# Comma-separated list of specific owner/repo pairs the agent is allowed to operate on. +# For GitHub/Linear webhooks, a repo is allowed if its org is in ALLOWED_GITHUB_ORGS OR its owner/repo is in ALLOWED_GITHUB_REPOS. +# Slack mentions are not rejected from regex-inferred repository text; repository access is bounded by GitHub App installation permissions. +# Leave both empty to allow all repos. +ALLOWED_GITHUB_REPOS="" # e.g. "some-user/their-repo,another-org/specific-repo" + +# === Default Repository === +# Used across all triggers when no repo is specified. +DEFAULT_REPO_OWNER="" # Default GitHub org (e.g. "my-org") +DEFAULT_REPO_NAME="" # Default GitHub repo (e.g. "my-repo") + +# === Dashboard (required to run the web dashboard) === +# Public URL that browsers use for /dashboard/api/* and OAuth callbacks. +# Use the FastAPI backend URL for local/cross-origin direct API calls. +# Use the dashboard frontend URL when a same-origin frontend rewrite proxies /dashboard/api/*. +# Its scheme drives cookie security: http:// => SameSite=Lax (local); +# https:// => Secure + SameSite=None (production). +DASHBOARD_API_BASE_URL="http://localhost:2024" +# Public base URL of the dashboard frontend (the ui/ app). Default post-login redirect. +DASHBOARD_BASE_URL="http://localhost:3000" +# HMAC secret for dashboard JWTs (session cookie and OAuth state). +DASHBOARD_JWT_SECRET="" # Generate with: openssl rand -hex 32 +# Comma-separated origins allowed for credentialed CORS and post-login redirects. +# Required whenever the frontend and API are on different origins — including local +# dev (UI :3000 -> API :2024 is cross-origin). CORS is only enabled when this is set. +DASHBOARD_ALLOWED_ORIGINS="http://localhost:3000" # prod: your frontend origin(s) +# Comma-separated GitHub login or email allowlist for admin dashboard endpoints. +# Empty => nobody is an admin. +CONFIGURED_ADMINS="" # e.g. "alice,bob@my-org.com" +# URL of the LangGraph server the FastAPI side calls to trigger/stream runs. +# Defaults to http://localhost:2024 locally; set to your deployment URL in prod. +LANGGRAPH_URL="http://localhost:2024" + +# === Linear (if using Linear trigger) === +LINEAR_API_KEY="" # From step 5 +LINEAR_WEBHOOK_SECRET="" # From step 5 + +# === Slack (if using Slack trigger) === +SLACK_BOT_TOKEN="" # From step 5 +SLACK_BOT_USER_ID="" +SLACK_BOT_USERNAME="" +SLACK_SIGNING_SECRET="" +# Optional: Slack-specific default repo (falls back to DEFAULT_REPO_OWNER/NAME). +SLACK_REPO_OWNER="" +SLACK_REPO_NAME="" +# Optional: "Sign in with Slack" account linking (GitHub <-> Slack). See step 5. +SLACK_CLIENT_ID="" +SLACK_CLIENT_SECRET="" +SLACK_TEAM_ID="" # Optional; restrict linking to one workspace (T...) + +# === Exa (optional — enables web search tool) === +EXA_API_KEY="" # From https://dashboard.exa.ai + +# === Reviewer / Analyzer (optional) === +# LangSmith dataset where reviewer finding outcomes are recorded and read back by +# the analyzer. Defaults to "openswe-reviewer-outcomes" if unset. +REVIEWER_OUTCOMES_DATASET="" +# Single GitHub org whose members may trigger the agent on *public* repos. +# Empty => no public-repo gate (back-compat). Distinct from ALLOWED_GITHUB_ORGS. +PUBLIC_REPO_ORG_GATE="" + +# === Sandbox (optional) === +# Provider: langsmith (default), modal, daytona, runloop, or local. See CUSTOMIZATION.md. +SANDBOX_TYPE="langsmith" +DEFAULT_SANDBOX_SNAPSHOT_ID="" # Required when SANDBOX_TYPE=langsmith (see step 4c) +DEFAULT_SANDBOX_SNAPSHOT_FS_CAPACITY_BYTES="" # Root FS size in bytes (default: 32 GiB) +DEFAULT_SANDBOX_VCPUS="" # vCPUs per sandbox (default: 4) +DEFAULT_SANDBOX_MEM_BYTES="" # Memory in bytes per sandbox (default: 15 GiB) +DEFAULT_SANDBOX_IDLE_TTL_SECONDS="" # Auto-stop after N seconds idle (default: 7200; 0 disables) +DEFAULT_SANDBOX_DELETE_AFTER_STOP_SECONDS="" # Delete N seconds after stop (default: 86400; 0 disables) + +# === Token Encryption === +TOKEN_ENCRYPTION_KEY="" # Generate with: openssl rand -base64 32 + # Supports key rotation: see "Rotating TOKEN_ENCRYPTION_KEY" below diff --git a/.gitignore b/.gitignore index 6153a317..1a0c7a41 100644 --- a/.gitignore +++ b/.gitignore @@ -39,6 +39,7 @@ yarn-error.log* .env*.local .env .env.* +!.env.example # vercel .vercel diff --git a/ui/src/lib/agents/sidebarPrefs.ts b/ui/src/lib/agents/sidebarPrefs.ts index d254a826..f845e029 100644 --- a/ui/src/lib/agents/sidebarPrefs.ts +++ b/ui/src/lib/agents/sidebarPrefs.ts @@ -1,10 +1,11 @@ import { useCallback, useEffect, useState } from "react" import { - DEFAULT_SIDEBAR_FILTERS, - type SidebarFilters, - type SidebarGroupMode, + DEFAULT_SIDEBAR_FILTERS + + } from "./sidebarFilter" +import type {SidebarFilters, SidebarGroupMode} from "./sidebarFilter"; const STORAGE_KEY = "open-swe.agents.sidebar-prefs" diff --git a/ui/src/routes/cloud-agents.tsx b/ui/src/routes/cloud-agents.tsx index b0e8f52d..fc497049 100644 --- a/ui/src/routes/cloud-agents.tsx +++ b/ui/src/routes/cloud-agents.tsx @@ -331,7 +331,7 @@ function CloudAgentsPage() { - {session.data?.is_admin && ( + {session.data.is_admin && ( socket.destroy()) socket.on("error", () => proxySocket.destroy())