feat(integration): prepaid billing, engine UI, credits console, direct tasks, v2 final
- 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
This commit is contained in:
@@ -38,6 +38,7 @@ from app.infrastructure.repositories.delivery import PipelineRunRepository
|
||||
from app.infrastructure.repositories.engine import PipelineStateRepository
|
||||
from app.infrastructure.repositories.workforce import EmployeeRepository, TaskRepository
|
||||
from app.workers.ai_runtime import AiRuntimeWorker
|
||||
from tests.billing_helpers import fund_org
|
||||
from tests.conftest import auth_header
|
||||
from tests.engine_fakes import ScriptedModel, ScriptedReply
|
||||
from tests.test_org_wizard import _complete, _manager
|
||||
@@ -107,6 +108,8 @@ async def test_a_manager_order_ships_through_the_engine(
|
||||
org_id = body["organization"]["id"]
|
||||
slug = body["organization"]["slug"]
|
||||
project_id = body["project"]["id"]
|
||||
# prepaid: the owner credits a new org before work
|
||||
await fund_org(session_factory, org_id, 1000.0)
|
||||
|
||||
async with session_factory() as session:
|
||||
roles = {e.role_key for e in await EmployeeRepository(session).list_for_org(org_id)}
|
||||
@@ -132,8 +135,9 @@ async def test_a_manager_order_ships_through_the_engine(
|
||||
thread_id = created.json()["id"]
|
||||
|
||||
# A manager order in that thread becomes one task with a pipeline state. The order goes to
|
||||
# the engine's manager directly: the HTTP message route builds its manager without pipeline
|
||||
# states (see test_integration_thread_project.py).
|
||||
# the engine's manager directly, only to read the reply and the states in this session: the
|
||||
# HTTP message route builds its manager with the pipeline states too
|
||||
# (test_integration_order_route.py).
|
||||
async with session_factory() as session:
|
||||
await build_scheduler(session).manager.chat(
|
||||
organization_id=org_id,
|
||||
|
||||
Reference in New Issue
Block a user