Skip to content

Latest commit

 

History

History
334 lines (238 loc) · 11.3 KB

File metadata and controls

334 lines (238 loc) · 11.3 KB

AI Agent Guidelines

This document contains critical rules and guidelines for AI agents working on this codebase.

Security Rules

CRITICAL: No Ad-Hoc Dynamic Values in Logs

By default, all log statements MUST use static strings only. Dynamic values are only allowed through the task-flow logging utility in lib/utils/task-flow-logs.ts.

Bad Examples (DO NOT DO THIS):

// BAD - Contains dynamic values
await logger.info(`Task created: ${taskId}`)
await logger.error(`Failed to process ${filename}`)
console.log(`User ${userId} logged in`)
console.error(`Error for ${provider}:`, error)

Good Examples (DO THIS):

// GOOD - Static strings only
await logger.info('Task created')
await logger.error('Failed to process file')
console.log('User logged in')
console.error('Error occurred:', error)

Approved Exception: Key Task Flow Logs

Key task flow logs may include selected dynamic values, but only when all of the following are true:

  1. The message is produced via formatKeyTaskLogMessage() from lib/utils/task-flow-logs.ts
  2. The metadata keys are from the allowlist in that file
  3. The values are operational identifiers only, not secrets or user content

Examples of allowed dynamic values:

  • sessionId
  • threadId
  • runtimeName
  • runtimeState
  • selectedModel
  • promptChars
  • transcriptCursor
  • turnStatus
  • mode
  • source
  • installedSkill

Examples that remain forbidden:

  • tokens, secrets, API keys, passwords
  • repository URLs and file paths
  • raw user prompts or assistant content
  • branch names, commit messages, personal identifiers

Rationale:

  • Prevents data leakage: Dynamic values in logs can expose sensitive information (user IDs, file paths, credentials, etc.) to end users
  • Security by default: Logs are displayed directly in the UI and returned in API responses
  • Outside the approved task-flow utility path, this applies to ALL log levels (info, error, success, command, console.log, console.error, console.warn, etc.)

Sensitive Data That Must NEVER Appear in Logs:

  • Devbox runtime credentials (DEVBOX_TOKEN, DEVBOX_JWT_SIGNING_KEY)
  • User IDs and personal information
  • File paths and repository URLs
  • Branch names and commit messages
  • Error details that may contain sensitive context
  • Any dynamic values that could reveal system internals

Credential Redaction

The redactSensitiveInfo() function in lib/utils/logging.ts automatically redacts known sensitive patterns, but this is a backup measure only. The primary defense is to never log dynamic values in the first place.

Current Redaction Patterns:

  • API keys (ANTHROPIC_API_KEY, OPENAI_API_KEY, etc.)
  • GitHub tokens (ghp*, gho*, ghu*, ghs*, ghr_)
  • Devbox runtime credentials (DEVBOX_TOKEN, DEVBOX_JWT_SIGNING_KEY)
  • Bearer tokens
  • JSON fields (teamId, projectId)
  • Environment variables containing KEY, TOKEN, SECRET, PASSWORD, TEAM_ID, PROJECT_ID

Code Quality Guidelines

Code Formatting and Quality Checks

Always run pnpm format, pnpm type-check, and pnpm lint after making changes to TypeScript/TSX files.

The project uses Prettier for code formatting, TypeScript for type checking, and ESLint for linting. After editing any .ts or .tsx files, run:

pnpm format
pnpm type-check
pnpm lint

If any errors are found:

  1. Type errors: Fix TypeScript type errors by correcting type annotations, adding missing imports, or fixing type mismatches
  2. Lint errors: Fix ESLint errors by following the suggested fixes or adjusting the code to meet the linting rules
  3. Do not skip or ignore errors - all errors must be resolved before considering the task complete

This ensures all code follows the project's formatting standards, type safety requirements, and linting rules, preventing issues in pull requests.

Use shadcn CLI for UI Components

When adding UI components, check if a shadcn/ui component exists and install it via CLI instead of writing it manually.

pnpm dlx shadcn@latest add <component-name>

Existing components are in components/ui/. See shadcn/ui docs for available components.

Logging Best Practices

  1. Use descriptive static messages

    // Instead of logging the value, log the action
    await logger.info('Sandbox created successfully')
    await logger.info('Dependencies installed')
    await logger.error('Build failed')
  2. Server-side logging for debugging

    // Use console.error for server-side debugging (not shown to users)
    // But still avoid sensitive data
    console.error('Sandbox creation error:', error)
  3. Progress updates

    // Use static progress messages
    await logger.updateProgress(50, 'Installing dependencies')
    await logger.updateProgress(75, 'Running build')

Error Handling

  1. Generic error messages to users

    await logger.error('Operation failed')
    // NOT: await logger.error(`Operation failed: ${error.message}`)
  2. Detailed server-side logging

    console.error('Detailed error for debugging:', error)
    // This appears in server logs, not user-facing logs

Testing Changes

When making changes that involve logging:

  1. Search for dynamic values

    # Check for logger statements with template literals
    grep -r "logger\.(info|error|success|command)\(\`.*\$\{" .
    
    # Check for console statements with template literals
    grep -r "console\.(log|error|warn|info)\(\`.*\$\{" .
  2. Verify no sensitive data exposure

    • Test the feature in the UI
    • Check the logs displayed to users
    • Ensure no sensitive information is visible

Configuration Security

Environment Variables

Never expose these in logs or to the client:

  • POSTGRES_URL - Database connection string that may contain credentials

  • SEALOS_HOST - Sealos cluster host configuration

  • DEVBOX_TOKEN - Devbox runtime API token

  • DEVBOX_JWT_SIGNING_KEY - Devbox JWT signing secret

  • AI_GATEWAY_API_KEY - AI Gateway API key

  • ANTHROPIC_API_KEY - Anthropic/Claude API key

  • OPENAI_API_KEY - OpenAI API key

  • GEMINI_API_KEY - Google Gemini API key

  • CURSOR_API_KEY - Cursor API key

  • GH_TOKEN / GITHUB_TOKEN - GitHub personal access token

  • JWE_SECRET - Encryption secret

  • ENCRYPTION_KEY - Encryption key

  • Any user-provided API keys

Client-Safe Variables

The current app does not require any client-safe auth provider variables. Do not add NEXT_PUBLIC_ variables unless the app code explicitly needs them.

Runtime Variables Used By Current App Code

The current codebase expects these environment variables:

  • Required core runtime: POSTGRES_URL, SEALOS_HOST, DEVBOX_TOKEN, JWE_SECRET, ENCRYPTION_KEY, GITHUB_CLIENT_ID, GITHUB_CLIENT_SECRET
  • Required for Devbox JWT auth when DEVBOX_TOKEN is not set: DEVBOX_JWT_SIGNING_KEY
  • Required for AI-generated branch names, titles, and commit messages: AI_GATEWAY_API_KEY
  • Optional callback override for self-hosted deployments: APP_BASE_URL

Do not rename these without updating the corresponding code paths. In particular, GitHub OAuth currently uses GITHUB_CLIENT_ID on the server, not NEXT_PUBLIC_GITHUB_CLIENT_ID.

Architecture Guidelines

Repository Page Structure

The repository page uses a nested routing structure with separate pages for each tab:

Route Structure

app/repos/[owner]/[repo]/
├── layout.tsx           # Shared layout with navigation tabs
├── page.tsx            # Redirects to /commits by default
├── commits/
│   └── page.tsx        # Commits page
├── issues/
│   └── page.tsx        # Issues page
└── pull-requests/
    └── page.tsx        # Pull Requests page

Components

  • components/repo-layout.tsx - Shared layout component with tab navigation
  • components/repo-commits.tsx - Commits list component
  • components/repo-issues.tsx - Issues list component
  • components/repo-pull-requests.tsx - Pull requests list component

API Routes

app/api/repos/[owner]/[repo]/
├── commits/route.ts         # GET - Fetch commits
├── issues/route.ts          # GET - Fetch issues
└── pull-requests/route.ts   # GET - Fetch pull requests

Key Features

  1. Tab Navigation: Uses Next.js Link components for client-side navigation between tabs
  2. Separate Pages: Each tab renders on its own route (commits, issues, pull-requests)
  3. Default Route: Visiting /repos/[owner]/[repo] redirects to /repos/[owner]/[repo]/commits
  4. Active State: The active tab is determined by matching the current pathname
  5. GitHub Integration: All data is fetched from GitHub API using Octokit client

Adding New Tabs

To add a new tab to the repository page:

  1. Create a new directory under app/repos/[owner]/[repo]/[tab-name]/
  2. Add a page.tsx file that renders your component
  3. Create the component in components/repo-[tab-name].tsx
  4. Add an API route in app/api/repos/[owner]/[repo]/[tab-name]/route.ts
  5. Update the tabs array in components/repo-layout.tsx to include the new tab
  6. Follow the existing patterns for data fetching and error handling

Compliance Checklist

Before submitting changes, verify:

  • No template literals with ${} in any log statements
  • All logger calls use static strings
  • All console calls use static strings (for user-facing logs)
  • No sensitive data in error messages
  • Tested in UI to confirm no data leakage
  • Server-side debugging logs don't expose credentials
  • Ran pnpm format and code is properly formatted
  • Ran pnpm format:check to verify formatting
  • Ran pnpm type-check and all type errors are fixed
  • Ran pnpm lint and all linting errors are fixed
  • Ran pnpm build only when the user requested it or the task required production build verification

Questions?

If you need to log information for debugging purposes:

  1. Use server-side console logs (not shown to users)
  2. Still avoid logging sensitive credentials
  3. Consider adding better error handling instead of logging details
  4. Use generic user-facing messages

Remember: When in doubt, use a static string. No exceptions.

Source Code Reference

Source code for dependencies is available in opensrc/ for deeper understanding of implementation details.

See opensrc/sources.json for the list of available packages and their versions.

Use this source code when you need to understand how a package works internally, not just its types/interface.

Fetching Additional Source Code

To fetch source code for a package or repository you need to understand, run:

npx opensrc <package>           # npm package (e.g., npx opensrc zod)
npx opensrc pypi:<package>      # Python package (e.g., npx opensrc pypi:requests)
npx opensrc crates:<package>    # Rust crate (e.g., npx opensrc crates:serde)
npx opensrc <owner>/<repo>      # GitHub repo (e.g., npx opensrc vercel/ai)
  1. Use task-flow logs for approved runtime identifiers

    import { formatKeyTaskLogMessage, TASK_FLOW_LOGS } from '@/lib/utils/task-flow-logs'
    
    const message = formatKeyTaskLogMessage(TASK_FLOW_LOGS.GATEWAY_SESSION_READY, {
      sessionId,
      mode: 'created',
    })
    await logger.success(message)
    console.info(message)