"""computer runtime foundation

Revision ID: b4b19c645cff
Revises: f956db868bc2
"""
import uuid
from collections.abc import Sequence

import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects import postgresql

revision: str = "b4b19c645cff"
down_revision: str | Sequence[str] | None = "f956db868bc2"
branch_labels = None
depends_on = None

def upgrade() -> None:
    permissions = sa.table(
        "permissions", sa.column("key", sa.String), sa.column("description", sa.String)
    )
    op.bulk_insert(permissions, [{
        "key": "computer.emergency_stop",
        "description": "Stop or explicitly resume all AI computer activity",
    }])
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('computer_profiles',
    sa.Column('id', sa.Uuid(), nullable=False),
    sa.Column('workspace_id', sa.Uuid(), nullable=False),
    sa.Column('created_by_user_id', sa.Uuid(), nullable=False),
    sa.Column('profile_key', sa.String(length=80), nullable=False),
    sa.Column('name', sa.String(length=160), nullable=False),
    sa.Column('storage_key', sa.String(length=64), nullable=False),
    sa.Column('status', sa.String(length=24), nullable=False),
    sa.Column('retention_days', sa.Integer(), nullable=False),
    sa.Column('version', sa.Integer(), nullable=False),
    sa.Column('revoked_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
    sa.CheckConstraint("status IN ('active','disabled','revoked')", name='ck_computer_profile_status'),
    sa.CheckConstraint('retention_days BETWEEN 1 AND 3650', name='ck_computer_profile_retention'),
    sa.CheckConstraint('version > 0', name='ck_computer_profile_version'),
    sa.ForeignKeyConstraint(['workspace_id', 'created_by_user_id'], ['workspace_memberships.workspace_id', 'workspace_memberships.user_id'], name='fk_computer_profile_creator'),
    sa.ForeignKeyConstraint(['workspace_id'], ['workspaces.id'], ),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('workspace_id', 'id', name='uq_computer_profile_workspace_id'),
    sa.UniqueConstraint('workspace_id', 'profile_key', name='uq_computer_profile_workspace_key'),
    sa.UniqueConstraint('workspace_id', 'storage_key', name='uq_computer_profile_storage_key')
    )
    op.create_index(op.f('ix_computer_profiles_workspace_id'), 'computer_profiles', ['workspace_id'], unique=False)
    op.create_table('workspace_control_states',
    sa.Column('workspace_id', sa.Uuid(), nullable=False),
    sa.Column('emergency_stopped', sa.Boolean(), nullable=False),
    sa.Column('reason', sa.String(length=500), nullable=True),
    sa.Column('stopped_by_user_id', sa.Uuid(), nullable=True),
    sa.Column('stopped_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('resumed_by_user_id', sa.Uuid(), nullable=True),
    sa.Column('resumed_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('version', sa.Integer(), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
    sa.CheckConstraint('version > 0', name='ck_workspace_control_version'),
    sa.ForeignKeyConstraint(['workspace_id', 'resumed_by_user_id'], ['workspace_memberships.workspace_id', 'workspace_memberships.user_id'], name='fk_workspace_control_resumer'),
    sa.ForeignKeyConstraint(['workspace_id', 'stopped_by_user_id'], ['workspace_memberships.workspace_id', 'workspace_memberships.user_id'], name='fk_workspace_control_stopper'),
    sa.ForeignKeyConstraint(['workspace_id'], ['workspaces.id'], ),
    sa.PrimaryKeyConstraint('workspace_id')
    )
    op.create_table('computer_sessions',
    sa.Column('id', sa.Uuid(), nullable=False),
    sa.Column('workspace_id', sa.Uuid(), nullable=False),
    sa.Column('requested_by_user_id', sa.Uuid(), nullable=False),
    sa.Column('agent_id', sa.Uuid(), nullable=False),
    sa.Column('execution_id', sa.Uuid(), nullable=True),
    sa.Column('profile_id', sa.Uuid(), nullable=False),
    sa.Column('task_summary', sa.Text(), nullable=False),
    sa.Column('status', sa.String(length=32), nullable=False),
    sa.Column('control_owner', sa.String(length=16), nullable=False),
    sa.Column('worker_id', sa.String(length=160), nullable=True),
    sa.Column('current_url', sa.Text(), nullable=True),
    sa.Column('active_tab_id', sa.String(length=160), nullable=True),
    sa.Column('current_action_summary', sa.String(length=500), nullable=True),
    sa.Column('upcoming_action_summary', sa.String(length=500), nullable=True),
    sa.Column('failure_code', sa.String(length=80), nullable=True),
    sa.Column('failure_message', sa.String(length=500), nullable=True),
    sa.Column('lease_version', sa.Integer(), nullable=False),
    sa.Column('version', sa.Integer(), nullable=False),
    sa.Column('started_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('last_active_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('paused_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('stopped_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
    sa.Column('updated_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
    sa.CheckConstraint("(status = 'human_controlled' AND control_owner = 'human') OR (status = 'ai_controlled' AND control_owner = 'ai') OR status NOT IN ('human_controlled','ai_controlled')", name='ck_computer_session_control_state'),
    sa.CheckConstraint("control_owner IN ('ai','human','system','none')", name='ck_computer_session_control_owner'),
    sa.CheckConstraint("status IN ('starting','ready','ai_controlled','human_controlled','awaiting_human','paused','recovering','stopping','stopped','failed')", name='ck_computer_session_status'),
    sa.CheckConstraint('lease_version >= 0', name='ck_computer_session_lease_version'),
    sa.CheckConstraint('version > 0', name='ck_computer_session_version'),
    sa.ForeignKeyConstraint(['workspace_id', 'agent_id'], ['agents.workspace_id', 'agents.id'], name='fk_computer_session_agent'),
    sa.ForeignKeyConstraint(['workspace_id', 'execution_id'], ['executions.workspace_id', 'executions.id'], name='fk_computer_session_execution'),
    sa.ForeignKeyConstraint(['workspace_id', 'profile_id'], ['computer_profiles.workspace_id', 'computer_profiles.id'], name='fk_computer_session_profile'),
    sa.ForeignKeyConstraint(['workspace_id', 'requested_by_user_id'], ['workspace_memberships.workspace_id', 'workspace_memberships.user_id'], name='fk_computer_session_requester'),
    sa.ForeignKeyConstraint(['workspace_id'], ['workspaces.id'], ),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('workspace_id', 'id', name='uq_computer_session_workspace_id')
    )
    op.create_index('ix_computer_session_workspace_status_updated', 'computer_sessions', ['workspace_id', 'status', 'updated_at'], unique=False)
    op.create_index(op.f('ix_computer_sessions_agent_id'), 'computer_sessions', ['agent_id'], unique=False)
    op.create_index(op.f('ix_computer_sessions_execution_id'), 'computer_sessions', ['execution_id'], unique=False)
    op.create_index(op.f('ix_computer_sessions_profile_id'), 'computer_sessions', ['profile_id'], unique=False)
    op.create_index(op.f('ix_computer_sessions_workspace_id'), 'computer_sessions', ['workspace_id'], unique=False)
    op.create_table('computer_actions',
    sa.Column('id', sa.Uuid(), nullable=False),
    sa.Column('workspace_id', sa.Uuid(), nullable=False),
    sa.Column('session_id', sa.Uuid(), nullable=False),
    sa.Column('execution_id', sa.Uuid(), nullable=True),
    sa.Column('actor_type', sa.String(length=16), nullable=False),
    sa.Column('actor_id', sa.Uuid(), nullable=True),
    sa.Column('tool_name', sa.String(length=160), nullable=False),
    sa.Column('parameters_redacted', sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), 'postgresql'), nullable=False),
    sa.Column('risk', sa.String(length=16), nullable=False),
    sa.Column('access_type', sa.String(length=16), nullable=False),
    sa.Column('action_intent_hash', sa.String(length=64), nullable=True),
    sa.Column('status', sa.String(length=32), nullable=False),
    sa.Column('result_redacted', sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), 'postgresql'), nullable=True),
    sa.Column('verification', sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), 'postgresql'), nullable=True),
    sa.Column('error_code', sa.String(length=80), nullable=True),
    sa.Column('duration_ms', sa.Integer(), nullable=True),
    sa.Column('started_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('completed_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
    sa.CheckConstraint("access_type IN ('read','write','control')", name='ck_computer_action_access'),
    sa.CheckConstraint("actor_type IN ('user','agent','system')", name='ck_computer_action_actor_type'),
    sa.CheckConstraint("risk IN ('low','medium','high')", name='ck_computer_action_risk'),
    sa.CheckConstraint("status IN ('pending','running','awaiting_approval','blocked','succeeded','failed','cancelled','unknown')", name='ck_computer_action_status'),
    sa.CheckConstraint('duration_ms IS NULL OR duration_ms >= 0', name='ck_computer_action_duration'),
    sa.ForeignKeyConstraint(['workspace_id', 'execution_id'], ['executions.workspace_id', 'executions.id'], name='fk_computer_action_execution'),
    sa.ForeignKeyConstraint(['workspace_id', 'session_id'], ['computer_sessions.workspace_id', 'computer_sessions.id'], name='fk_computer_action_session', ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('workspace_id', 'id', name='uq_computer_action_workspace_id')
    )
    op.create_index(op.f('ix_computer_actions_execution_id'), 'computer_actions', ['execution_id'], unique=False)
    op.create_index(op.f('ix_computer_actions_session_id'), 'computer_actions', ['session_id'], unique=False)
    op.create_index(op.f('ix_computer_actions_workspace_id'), 'computer_actions', ['workspace_id'], unique=False)
    op.create_table('computer_control_leases',
    sa.Column('id', sa.Uuid(), nullable=False),
    sa.Column('workspace_id', sa.Uuid(), nullable=False),
    sa.Column('session_id', sa.Uuid(), nullable=False),
    sa.Column('owner', sa.String(length=16), nullable=False),
    sa.Column('actor_user_id', sa.Uuid(), nullable=True),
    sa.Column('fencing_token', sa.Integer(), nullable=False),
    sa.Column('issued_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('expires_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('heartbeat_at', sa.DateTime(timezone=True), nullable=False),
    sa.Column('released_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('release_reason', sa.String(length=160), nullable=True),
    sa.CheckConstraint("owner IN ('ai','human','system')", name='ck_computer_lease_owner'),
    sa.CheckConstraint('fencing_token > 0', name='ck_computer_lease_fencing_token'),
    sa.CheckConstraint('released_at IS NULL OR released_at >= issued_at', name='ck_computer_lease_release_time'),
    sa.ForeignKeyConstraint(['workspace_id', 'actor_user_id'], ['workspace_memberships.workspace_id', 'workspace_memberships.user_id'], name='fk_computer_lease_actor'),
    sa.ForeignKeyConstraint(['workspace_id', 'session_id'], ['computer_sessions.workspace_id', 'computer_sessions.id'], name='fk_computer_lease_session', ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('workspace_id', 'session_id', 'fencing_token', name='uq_computer_lease_fencing_token')
    )
    op.create_index(op.f('ix_computer_control_leases_session_id'), 'computer_control_leases', ['session_id'], unique=False)
    op.create_index(op.f('ix_computer_control_leases_workspace_id'), 'computer_control_leases', ['workspace_id'], unique=False)
    op.create_table('computer_artifacts',
    sa.Column('id', sa.Uuid(), nullable=False),
    sa.Column('workspace_id', sa.Uuid(), nullable=False),
    sa.Column('session_id', sa.Uuid(), nullable=False),
    sa.Column('action_id', sa.Uuid(), nullable=True),
    sa.Column('kind', sa.String(length=24), nullable=False),
    sa.Column('status', sa.String(length=24), nullable=False),
    sa.Column('storage_key', sa.String(length=255), nullable=False),
    sa.Column('sha256', sa.String(length=64), nullable=False),
    sa.Column('mime_type', sa.String(length=160), nullable=False),
    sa.Column('size_bytes', sa.Integer(), nullable=False),
    sa.Column('metadata_redacted', sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), 'postgresql'), nullable=False),
    sa.Column('expires_at', sa.DateTime(timezone=True), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
    sa.CheckConstraint("kind IN ('screenshot','download','upload','log')", name='ck_computer_artifact_kind'),
    sa.CheckConstraint("status IN ('quarantined','available','rejected','deleted','expired')", name='ck_computer_artifact_status'),
    sa.CheckConstraint('size_bytes >= 0', name='ck_computer_artifact_size'),
    sa.ForeignKeyConstraint(['workspace_id', 'action_id'], ['computer_actions.workspace_id', 'computer_actions.id'], name='fk_computer_artifact_action'),
    sa.ForeignKeyConstraint(['workspace_id', 'session_id'], ['computer_sessions.workspace_id', 'computer_sessions.id'], name='fk_computer_artifact_session', ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('workspace_id', 'id', name='uq_computer_artifact_workspace_id'),
    sa.UniqueConstraint('workspace_id', 'storage_key', name='uq_computer_artifact_storage_key')
    )
    op.create_index(op.f('ix_computer_artifacts_action_id'), 'computer_artifacts', ['action_id'], unique=False)
    op.create_index(op.f('ix_computer_artifacts_session_id'), 'computer_artifacts', ['session_id'], unique=False)
    op.create_index(op.f('ix_computer_artifacts_workspace_id'), 'computer_artifacts', ['workspace_id'], unique=False)
    op.create_table('computer_checkpoints',
    sa.Column('id', sa.Uuid(), nullable=False),
    sa.Column('workspace_id', sa.Uuid(), nullable=False),
    sa.Column('session_id', sa.Uuid(), nullable=False),
    sa.Column('action_id', sa.Uuid(), nullable=True),
    sa.Column('sequence', sa.Integer(), nullable=False),
    sa.Column('checkpoint_type', sa.String(length=32), nullable=False),
    sa.Column('current_url', sa.Text(), nullable=True),
    sa.Column('active_tab_id', sa.String(length=160), nullable=True),
    sa.Column('tabs', sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), 'postgresql'), nullable=False),
    sa.Column('state_redacted', sa.JSON().with_variant(postgresql.JSONB(astext_type=sa.Text()), 'postgresql'), nullable=False),
    sa.Column('screenshot_artifact_id', sa.Uuid(), nullable=True),
    sa.Column('created_at', sa.DateTime(timezone=True), server_default=sa.text('(CURRENT_TIMESTAMP)'), nullable=False),
    sa.CheckConstraint("checkpoint_type IN ('session_started','before_action','after_action','takeover','return_control','pause','recovery','failure','completion')", name='ck_computer_checkpoint_type'),
    sa.CheckConstraint('sequence > 0', name='ck_computer_checkpoint_sequence'),
    sa.ForeignKeyConstraint(['workspace_id', 'action_id'], ['computer_actions.workspace_id', 'computer_actions.id'], name='fk_computer_checkpoint_action'),
    sa.ForeignKeyConstraint(['workspace_id', 'screenshot_artifact_id'], ['computer_artifacts.workspace_id', 'computer_artifacts.id'], name='fk_computer_checkpoint_screenshot'),
    sa.ForeignKeyConstraint(['workspace_id', 'session_id'], ['computer_sessions.workspace_id', 'computer_sessions.id'], name='fk_computer_checkpoint_session', ondelete='CASCADE'),
    sa.PrimaryKeyConstraint('id'),
    sa.UniqueConstraint('workspace_id', 'session_id', 'sequence', name='uq_computer_checkpoint_sequence')
    )
    op.create_index(op.f('ix_computer_checkpoints_session_id'), 'computer_checkpoints', ['session_id'], unique=False)
    op.create_index(op.f('ix_computer_checkpoints_workspace_id'), 'computer_checkpoints', ['workspace_id'], unique=False)
    _seed_control_state_and_personal_profiles()
    _grant_emergency_stop_permission()
    _grant_default_browser_tools()
    # ### end Alembic commands ###

def downgrade() -> None:
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_computer_checkpoints_workspace_id'), table_name='computer_checkpoints')
    op.drop_index(op.f('ix_computer_checkpoints_session_id'), table_name='computer_checkpoints')
    op.drop_table('computer_checkpoints')
    op.drop_index(op.f('ix_computer_artifacts_workspace_id'), table_name='computer_artifacts')
    op.drop_index(op.f('ix_computer_artifacts_session_id'), table_name='computer_artifacts')
    op.drop_index(op.f('ix_computer_artifacts_action_id'), table_name='computer_artifacts')
    op.drop_table('computer_artifacts')
    op.drop_index(op.f('ix_computer_control_leases_workspace_id'), table_name='computer_control_leases')
    op.drop_index(op.f('ix_computer_control_leases_session_id'), table_name='computer_control_leases')
    op.drop_table('computer_control_leases')
    op.drop_index(op.f('ix_computer_actions_workspace_id'), table_name='computer_actions')
    op.drop_index(op.f('ix_computer_actions_session_id'), table_name='computer_actions')
    op.drop_index(op.f('ix_computer_actions_execution_id'), table_name='computer_actions')
    op.drop_table('computer_actions')
    op.drop_index(op.f('ix_computer_sessions_workspace_id'), table_name='computer_sessions')
    op.drop_index(op.f('ix_computer_sessions_profile_id'), table_name='computer_sessions')
    op.drop_index(op.f('ix_computer_sessions_execution_id'), table_name='computer_sessions')
    op.drop_index(op.f('ix_computer_sessions_agent_id'), table_name='computer_sessions')
    op.drop_index('ix_computer_session_workspace_status_updated', table_name='computer_sessions')
    op.drop_table('computer_sessions')
    op.drop_table('workspace_control_states')
    op.drop_index(op.f('ix_computer_profiles_workspace_id'), table_name='computer_profiles')
    op.drop_table('computer_profiles')
    role_permissions = sa.table(
        "role_permissions", sa.column("permission_key", sa.String)
    )
    permissions = sa.table("permissions", sa.column("key", sa.String))
    connection = op.get_bind()
    connection.execute(role_permissions.delete().where(
        role_permissions.c.permission_key == "computer.emergency_stop"
    ))
    connection.execute(permissions.delete().where(
        permissions.c.key == "computer.emergency_stop"
    ))
    # ### end Alembic commands ###


def _seed_control_state_and_personal_profiles() -> None:
    workspaces = sa.table("workspaces", sa.column("id", sa.Uuid))
    roles = sa.table(
        "roles", sa.column("id", sa.Uuid), sa.column("workspace_id", sa.Uuid),
        sa.column("name", sa.String), sa.column("is_system", sa.Boolean),
    )
    membership_roles = sa.table(
        "membership_roles", sa.column("workspace_id", sa.Uuid),
        sa.column("membership_id", sa.Uuid), sa.column("role_id", sa.Uuid),
    )
    memberships = sa.table(
        "workspace_memberships", sa.column("id", sa.Uuid),
        sa.column("workspace_id", sa.Uuid), sa.column("user_id", sa.Uuid),
        sa.column("status", sa.String),
    )
    controls = sa.table(
        "workspace_control_states", sa.column("workspace_id", sa.Uuid),
        sa.column("emergency_stopped", sa.Boolean), sa.column("version", sa.Integer),
    )
    profiles = sa.table(
        "computer_profiles", sa.column("id", sa.Uuid),
        sa.column("workspace_id", sa.Uuid), sa.column("created_by_user_id", sa.Uuid),
        sa.column("profile_key", sa.String), sa.column("name", sa.String),
        sa.column("storage_key", sa.String), sa.column("status", sa.String),
        sa.column("retention_days", sa.Integer), sa.column("version", sa.Integer),
    )
    connection = op.get_bind()
    connection.execute(controls.insert().from_select(
        ["workspace_id", "emergency_stopped", "version"],
        sa.select(workspaces.c.id, sa.literal(False), sa.literal(1)),
    ))
    owners = connection.execute(
        sa.select(roles.c.workspace_id, memberships.c.user_id)
        .select_from(
            roles.join(
                membership_roles,
                (membership_roles.c.workspace_id == roles.c.workspace_id)
                & (membership_roles.c.role_id == roles.c.id),
            ).join(
                memberships,
                (memberships.c.workspace_id == membership_roles.c.workspace_id)
                & (memberships.c.id == membership_roles.c.membership_id),
            )
        )
        .where(
            roles.c.name == "Owner",
            roles.c.is_system.is_(True),
            memberships.c.status == "active",
        )
    ).all()
    for workspace_id, user_id in owners:
        connection.execute(profiles.insert().values(
            id=uuid.uuid4(), workspace_id=workspace_id, created_by_user_id=user_id,
            profile_key="personal", name="Personal Computer",
            storage_key=uuid.uuid4().hex, status="active", retention_days=30, version=1,
        ))


def _grant_emergency_stop_permission() -> None:
    roles = sa.table(
        "roles", sa.column("id", sa.Uuid), sa.column("workspace_id", sa.Uuid),
        sa.column("name", sa.String), sa.column("is_system", sa.Boolean),
    )
    role_permissions = sa.table(
        "role_permissions", sa.column("workspace_id", sa.Uuid),
        sa.column("role_id", sa.Uuid), sa.column("permission_key", sa.String),
    )
    op.get_bind().execute(role_permissions.insert().from_select(
        ["workspace_id", "role_id", "permission_key"],
        sa.select(
            roles.c.workspace_id, roles.c.id, sa.literal("computer.emergency_stop")
        ).where(
            roles.c.is_system.is_(True),
            roles.c.name.in_(["Owner", "Administrator"]),
        ),
    ))


def _grant_default_browser_tools() -> None:
    agents = sa.table(
        "agents", sa.column("id", sa.Uuid), sa.column("workspace_id", sa.Uuid),
        sa.column("name", sa.String),
    )
    agent_permissions = sa.table(
        "agent_permissions", sa.column("workspace_id", sa.Uuid),
        sa.column("agent_id", sa.Uuid), sa.column("permission_key", sa.String),
    )
    agent_tools = sa.table(
        "agent_tools", sa.column("workspace_id", sa.Uuid),
        sa.column("agent_id", sa.Uuid), sa.column("tool_name", sa.String),
        sa.column("constraints", sa.JSON),
    )
    connection = op.get_bind()
    default_agents = connection.execute(sa.select(
        agents.c.workspace_id, agents.c.id
    ).where(agents.c.name == "Personal Executive Assistant")).all()
    tools = [
        "browser.observe", "browser.navigate", "browser.wait_for", "browser.extract",
        "browser.tab_list", "browser.screenshot", "browser.click", "browser.type",
        "browser.press", "browser.tab_open", "browser.tab_switch", "browser.tab_close",
    ]
    for workspace_id, agent_id in default_agents:
        existing_permissions = set(connection.execute(sa.select(
            agent_permissions.c.permission_key
        ).where(
            agent_permissions.c.workspace_id == workspace_id,
            agent_permissions.c.agent_id == agent_id,
        )).scalars())
        for permission_key in {"computer.observe", "computer.control"} - existing_permissions:
            connection.execute(agent_permissions.insert().values(
                workspace_id=workspace_id, agent_id=agent_id,
                permission_key=permission_key,
            ))
        existing_tools = set(connection.execute(sa.select(
            agent_tools.c.tool_name
        ).where(
            agent_tools.c.workspace_id == workspace_id,
            agent_tools.c.agent_id == agent_id,
        )).scalars())
        for tool_name in set(tools) - existing_tools:
            connection.execute(agent_tools.insert().values(
                workspace_id=workspace_id, agent_id=agent_id,
                tool_name=tool_name, constraints={},
            ))
