- Prepaid credit system: org wallet, debit on usage, chat gate, admin credit console - Engine UI: /manager, /tasks, /tasks/[id], /workforce, /dashboard, /traces pages - Direct task creation (HTTP POST /tasks, MCP tasks_create) at pending_manager_review - Pause/resume/cancel/answer actions in engine API and UI - Employee cap (7 per org default), review pipeline guard (active reviewer required) - Scheduler: wide window prevents org starvation; archived employees excluded from cap - Tenant isolation: project-id cross-org 404, engine never uses another tenant's sandbox - Order route fix: manager built with pipeline states + employee profiles - Contract extension: ModelGrantPort.get_org_policy with DefaultOrgPolicy - Engine event types in @agy/contracts (task.step, task.gate, run.log, run.tool, team.changed) - api-engine.ts typed client; api-credit.ts client - Alembic migration c4d5e6f7a8b9: prepaid credit + engine UI tables - 859 tests passed, 1 skipped; ruff/mypy/tsc/eslint/vitest all green Refs: PLAN-v2.md §9 (T1–T43), todo-v2-final.md
149 lines
5.8 KiB
Bash
149 lines
5.8 KiB
Bash
# ---------------------------------------------------------------------------
|
|
# Smart Organization — sample environment file.
|
|
# Copy to `.env` and fill in real values. NEVER commit a real `.env`.
|
|
# Every external provider defaults to `mock` so the stack runs with zero
|
|
# credentials. Flip the *_PROVIDER vars once real credentials exist.
|
|
# ---------------------------------------------------------------------------
|
|
|
|
APP_ENV=development
|
|
APP_URL=http://localhost:3000
|
|
API_URL=http://localhost:8000
|
|
|
|
# Origins the browser is allowed to call the API from, comma-separated.
|
|
# `localhost` and `127.0.0.1` are DIFFERENT origins to a browser: if you start
|
|
# the dev server with `-H 127.0.0.1` and this list only has `localhost`, every
|
|
# request fails with an opaque "Disallowed CORS origin". Both are listed here.
|
|
# Production must set this explicitly — the dev default is rejected at boot.
|
|
CORS_ORIGINS=http://localhost:3000,http://127.0.0.1:3000
|
|
|
|
# --- Data stores -----------------------------------------------------------
|
|
DATABASE_URL=postgresql+psycopg://agy:agy@localhost:5432/agy_web
|
|
REDIS_URL=redis://localhost:6379/0
|
|
|
|
# --- Security --------------------------------------------------------------
|
|
# Generate with: python -c "import secrets; print(secrets.token_urlsafe(48))"
|
|
JWT_SECRET=change-me
|
|
# Must be exactly 32 bytes, base64/hex encoded.
|
|
ENCRYPTION_KEY=change-me-32-bytes
|
|
|
|
# --- AI models (hidden from customers) -------------------------------------
|
|
# agy (Google Antigravity) is the only model provider. The setting is kept for
|
|
# compatibility with older .env files; any value is ignored (with a warning).
|
|
AI_DEFAULT_PROVIDER=agy
|
|
|
|
# --- agy (Google Antigravity) ----------------------------------------------
|
|
# The only model provider. There are no API keys: accounts are Google
|
|
# identities logged in via OAuth from the admin console
|
|
# (/admin/agy-accounts → افزودن اکانت agy). Any number of accounts can be added —
|
|
# the rotation pool spreads load across them and benches a rate-limited one
|
|
# until its quota window resets. AGY_CLIENT_ID/SECRET default to the public
|
|
# Antigravity CLI application; override them to use your own Google OAuth
|
|
# client. AGY_REDIRECT_URI must stay a loopback URL.
|
|
AGY_CLIENT_ID=
|
|
AGY_CLIENT_SECRET=
|
|
AGY_REDIRECT_URI=http://localhost:51121/oauth-callback
|
|
# Seconds an account is benched after a 429 when Google sends no Retry-After.
|
|
AGY_429_COOLDOWN_SECONDS=900
|
|
|
|
# --- Git provider ----------------------------------------------------------
|
|
# mock | gitea
|
|
GIT_PROVIDER=mock
|
|
GITEA_URL=
|
|
GITEA_INTERNAL_URL=
|
|
GITEA_ADMIN_TOKEN=
|
|
|
|
# --- Preview domain routing ------------------------------------------------
|
|
# mock | caddy
|
|
DOMAIN_ROUTER=mock
|
|
PREVIEW_ROOT_DOMAIN=msa.artacloud.ir
|
|
PREVIEW_PORT_START=8080
|
|
PREVIEW_PORT_END=8999
|
|
CADDYFILE_PATH=/etc/caddy/Caddyfile
|
|
|
|
# --- Sandbox ---------------------------------------------------------------
|
|
# mock | daytona | e2b
|
|
SANDBOX_PROVIDER=mock
|
|
DAYTONA_API_KEY=
|
|
DAYTONA_API_URL=
|
|
E2B_API_KEY=
|
|
|
|
# --- Payments --------------------------------------------------------------
|
|
# mock | stripe
|
|
PAYMENT_PROVIDER=mock
|
|
STRIPE_SECRET_KEY=
|
|
STRIPE_WEBHOOK_SECRET=
|
|
|
|
# --- Error logging ---------------------------------------------------------
|
|
# Every failure the platform catches is written to the `error_events` table and
|
|
# is readable at /admin/errors (platform owner only). Errors are redacted before
|
|
# they are stored — passwords, tokens, API keys, JWTs and DSN credentials are
|
|
# stripped by app/core/redact.py.
|
|
#
|
|
# ERROR_LOG_ENABLED=0 turns persistence off entirely; failures still reach
|
|
# stderr, but nothing is written to the database.
|
|
ERROR_LOG_ENABLED=1
|
|
|
|
# Whether 4xx responses are recorded too. Off by default: a public API receives
|
|
# a constant stream of 404s from scanners, and recording them all buries the
|
|
# genuine bugs. Turn it on while debugging a misbehaving client.
|
|
# 5xx responses are always recorded, whatever this is set to.
|
|
ERROR_LOG_CLIENT_ERRORS=0
|
|
|
|
# ===========================================================================
|
|
# v2 workstream settings. Each agent edits ONLY its own block.
|
|
# ===========================================================================
|
|
# >>> agent-1 (org platform)
|
|
MCP_GATEWAY_HOST=127.0.0.1
|
|
MCP_GATEWAY_PORT=8765
|
|
MCP_GATEWAY_ENABLED=true
|
|
MCP_TOKEN_TTL_DAYS=90
|
|
MCP_RATE_LIMIT_PER_MINUTE=60
|
|
MEMORY_ORG_CHAR_CAP=60000
|
|
PLATFORM_INVITE_TTL_HOURS=72
|
|
# <<< agent-1
|
|
|
|
# >>> agent-2 (AI workforce engine)
|
|
ENGINE_MAX_TOOL_CALLS_PER_TURN=40
|
|
#: Consecutive malformed replies tolerated before a turn gives up.
|
|
ENGINE_MAX_PROTOCOL_RETRIES=3
|
|
ENGINE_TURN_TIMEOUT_SECONDS=900
|
|
#: Turns running at once, globally and per organization.
|
|
ENGINE_MAX_CONCURRENT_TURNS=8
|
|
ENGINE_MAX_TURNS_PER_ORG=3
|
|
#: The tests gate's own budget, and how many merge conflicts before the
|
|
#: manager takes over.
|
|
ENGINE_TESTS_TIMEOUT_SECONDS=600
|
|
ENGINE_MAX_MERGE_CONFLICTS=3
|
|
#: Per-task credit ceiling (0 = no ceiling). An organization that runs out is
|
|
#: paused, not left spinning.
|
|
ENGINE_MAX_TASK_CREDITS=0
|
|
ENGINE_MAX_CYCLES=6
|
|
ENGINE_MAX_EMPLOYEES=20
|
|
ENGINE_TICK_SECONDS=10
|
|
# <<< agent-2
|
|
|
|
# >>> agent-3 (delivery & infra)
|
|
SANDBOX_DOCKER_BIN=docker
|
|
SANDBOX_WORKSPACES_ROOT=./.data/workspaces
|
|
SANDBOX_DEFAULT_CPUS=1
|
|
SANDBOX_DEFAULT_MEMORY_MB=1024
|
|
DEMO_PORT_START=8100
|
|
DEMO_PORT_END=8999
|
|
DELIVERY_POLL_SECONDS=60
|
|
DEPLOY_ALLOW_PRIVATE_HOSTS=false
|
|
ARTIFACTS_ROOT=./.data/artifacts
|
|
# fake (default, no git on the host) | local (real git workspaces)
|
|
GIT_WORKSPACE=fake
|
|
ALLOW_CUSTOM_DOMAINS=false
|
|
# `protocol.file.allow` for host git calls. The hardened default is `never`: a
|
|
# repository must not be able to make git read a local path through a submodule
|
|
# or `--upload-pack`. Set to true ONLY to test against a local bare repository.
|
|
GIT_ALLOW_FILE_PROTOCOL=false
|
|
# <<< agent-3
|
|
|
|
# >>> integration (billing)
|
|
# Credit given to every new organization at creation (prepaid). 0 means the
|
|
# platform owner credits new organizations by hand.
|
|
BILLING_STARTING_CREDIT=0
|
|
# <<< integration
|