fix(ui): clear eslint errors from dep bumps + track .env.example (#111)
Some checks are pending
CI / Lint (push) Waiting to run
CI / Format check (push) Waiting to run
CI / Unit tests (push) Waiting to run
CI / Playwright E2E (push) Waiting to run
CI / Docker build smoke (push) Waiting to run

* fix(ui): resolve eslint errors surfaced by dep bumps

Clear the 6 eslint errors introduced by the typescript-eslint / TS 6.0
dependency bumps:
- sidebarPrefs.ts, vite.config.ts: inline type imports -> top-level
  type-only imports; sort import members (autofix)
- cloud-agents.tsx: drop optional chain on session.data (already
  narrowed non-null by the earlier login guard)
- vite.config.ts: drop optional chain on proxyHead (typed Buffer from
  the upgrade event, always present)

No behavior change. eslint and tsc --noEmit both clean.

* docs(env): track .env.example and document deployment vars

- Un-ignore .env.example (!.env.example) so the template stays tracked;
  .env / .env.* secret files remain ignored.
- Add LLM_MODEL_ID, AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY (used by the
  Bedrock/managed deployment but previously undocumented).
- Mark LANGCHAIN_TRACING_V2 and LANGCHAIN_PROJECT as reserved on
  LangGraph Platform (the platform sets them; deploys are rejected if
  provided).
This commit is contained in:
Adam Moussa 2026-07-02 17:31:07 -04:00 • committed by GitHub
parent 232f22f9d0
commit f43606309e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
5 changed files with 132 additions and 6 deletions

123
.env.example Normal file
View file

@ -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

1
.gitignore vendored
View file

@ -39,6 +39,7 @@ yarn-error.log*
.env*.local
.env
.env.*
!.env.example
# vercel
.vercel

View file

@ -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"

View file

@ -331,7 +331,7 @@ function CloudAgentsPage() {
</div>
<CaretRightIcon className="size-3.5 shrink-0 text-muted-foreground" />
</Link>
{session.data?.is_admin && (
{session.data.is_admin && (
<Link
to="/agents/snapshots"
className="flex items-center justify-between gap-6 px-4 py-3 hover:bg-muted/40"

View file

@ -1,5 +1,5 @@
import http from "node:http"
import { defineConfig, type Plugin } from "vite"
import { defineConfig } from "vite"
import { devtools } from "@tanstack/devtools-vite"
import { tanstackStart } from "@tanstack/react-start/plugin/vite"
import viteReact from "@vitejs/plugin-react"
@ -7,6 +7,7 @@ import viteTsConfigPaths from "vite-tsconfig-paths"
import tailwindcss from "@tailwindcss/vite"
import { nitro } from "nitro/vite"
import { VitePWA } from "vite-plugin-pwa"
import type {Plugin} from "vite";
// Dev-only: when E2E_HARNESS is set (the `dev:mock` local harness) serve the app
// and the harness from one origin by proxying the API routes + the Yjs collab
@ -60,7 +61,7 @@ function mockHarnessProxy(): Plugin | null {
socket.write(
`HTTP/1.1 ${proxyRes.statusCode} ${proxyRes.statusMessage}\r\n${lines}\r\n\r\n`
)
if (proxyHead?.length) socket.write(proxyHead)
if (proxyHead.length) socket.write(proxyHead)
if (head?.length) proxySocket.write(head)
proxySocket.on("error", () => socket.destroy())
socket.on("error", () => proxySocket.destroy())