chore(project-map): regenerate .pi-map artifacts across the repo

This commit is contained in:
Developer
2026-06-17 11:31:24 +00:00
parent 0dd5f2317b
commit 93da9b42a2
683 changed files with 5075 additions and 4965 deletions
+2 -5
View File
@@ -2,7 +2,7 @@
dir: apps/api/src
## role
Core application package for the Headquarter API, handling configuration, database connectivity, logging infrastructure, and FastAPI application lifecycle.
Core backend API package for the "Headquarter API" FastAPI application, handling configuration, database setup, logging, and application bootstrap.
## parent
index: apps/api/.pi-map.index.md
map: apps/api/.pi-map.md
@@ -13,9 +13,6 @@ map: apps/api/.pi-map.md
- apps/api/src/auth
index: apps/api/src/auth/.pi-map.index.md
map: apps/api/src/auth/.pi-map.md
- apps/api/src/headquarter_api.egg-info
index: apps/api/src/headquarter_api.egg-info/.pi-map.index.md
map: apps/api/src/headquarter_api.egg-info/.pi-map.md
- apps/api/src/models
index: apps/api/src/models/.pi-map.index.md
map: apps/api/src/models/.pi-map.md
@@ -49,6 +46,6 @@ map: apps/api/src/.pi-map.md
- change src config
read: config.py, logging_config.py
- explore src subdirectories
index: apps/api/src/api/.pi-map.index.md, apps/api/src/auth/.pi-map.index.md, apps/api/src/headquarter_api.egg-info/.pi-map.index.md
index: apps/api/src/api/.pi-map.index.md, apps/api/src/auth/.pi-map.index.md, apps/api/src/models/.pi-map.index.md
## dirty
-
+8 -8
View File
@@ -4,17 +4,17 @@ dir: apps/api/src
index: apps/api/src/.pi-map.index.md
## role
Core application package for the Headquarter API, handling configuration, database connectivity, logging infrastructure, and FastAPI application lifecycle.
Core backend API package for the "Headquarter API" FastAPI application, handling configuration, database setup, logging, and application bootstrap.
## files
- __init__.py | Marks the directory as a Python package for the Headquarter API.
- config.py | Defines application configuration settings with environment-based overrides using Pydantic, including database URLs, service domains, OAuth/Authentik integration, JWT/session settings, and computed properties for environment-specific behavior. | exp: class:Settings, func:build_database_url(user: str, password: str, host: str, port: int, database: str) → str | dep: pydantic, pydantic_settings
- database.py | Sets up async SQLAlchemy database engine and session factory, with retry logic for database connectivity testing and Alembic migration execution via subprocess. | exp: func:init_database(max_retries, retry_delay) → bool, call:range, call:engine.connect, call:test_conn.execute, call:text, call:test_conn.close, call:logger.info, call:asyncio.get_event_loop().run_in_executor, call:subprocess.run, call:os.path.dirname, call:os.path.abspath, call:logger.debug, call:logger.error, call:asyncio.sleep, call:str(exc).lower, call:logger.warning | dep: asyncio, logging, os, subprocess, sqlalchemy.ext.asyncio, sqlalchemy.pool, src.config, sqlalchemy
- logging_config.py | Configures structured JSON logging with correlation ID injection, custom formatters, and HTTP request/exception middleware for a FastAPI application. | exp: class:CorrelationIdFilter, method:filter(self, record: logging.LogRecord) → bool, call:get_correlation_id, class:JSONFormatter, method:format(self, record: logging.LogRecord) → str, call:self.formatTime, call:record.getMessage, call:getattr, call:self.formatException, call:json.dumps, method:formatTime(self, record: logging.LogRecord, datefmt) → str, call:time.strftime, call:time.gmtime, class:RequestLoggingMiddleware, method:dispatch(self, request: Request, call_next: Callable) → Response, call:time.time, call:logger.info, call:call_next, call:int, call:logger.error, call:type, call:traceback.format_exc, class:ExceptionLoggingMiddleware, method:dispatch(self, request: Request, call_next: Callable) → Response, call:call_next, call:logger.critical, call:traceback.format_exc, func:configure_logging(level) → None, call:JSONFormatter, call:logging.StreamHandler, call:console_handler.setFormatter, call:console_handler.addFilter, call:CorrelationIdFilter, call:root_logger.setLevel, call:logging.getLogger("uvicorn").setLevel, call:logging.getLogger("uvicorn.access").setLevel, call:logging.getLogger("sqlalchemy.engine").setLevel, call:logger.info, call:logging.getLevelName | dep: json, logging, sys, time, traceback, collections.abc, fastapi, starlette.middleware.base, src.services.shared.correlation
- main.py | Initializes and configures a FastAPI application for the "Headquarter API" with database setup, middleware, routing, and background services. | exp: func:_sanitize_validation_errors(errors), call:error.get, call:str, call:ctx.items, call:isinstance, call:type, call:sanitized.append, func:validation_exception_handler(request: Request, exc: RequestValidationError), call:exc.errors, call:logger.warning, call:_sanitize_validation_errors, call:JSONResponse, func:on_startup(), call:logger.info, call:init_database, call:logger.error, call:sys.exit, call:_health_monitor.start, call:seed_builtin_tool_types, func:on_shutdown(), call:logger.info, call:_health_monitor.stop | dep: logging, os, fastapi, fastapi.exceptions, fastapi.middleware.cors, fastapi.responses, fastapi.staticfiles, src.api.config, src.api.project, src.api.system, src.api.tool, src.api.user, src.api.workspace, src.config, src.models, src.database, src.logging_config, src.seeds.builtin_tool_types, src.services.instance, src.services.shared, sys, src.api.*
- config.py | Defines application configuration settings with environment variable loading, database URL construction, and computed properties for service URLs and security settings. | exp: class:Settings, func:build_database_url(user: str, password: str, host: str, port: int, database: str) → str | dep: pydantic, pydantic_settings
- database.py | Sets up an async SQLAlchemy database engine with retry logic and runs Alembic migrations via subprocess to initialize the database. | exp: func:init_database(max_retries, retry_delay) → bool, call:range, call:engine.connect, call:test_conn.execute, call:text, call:test_conn.close, call:logger.info, call:asyncio.get_event_loop().run_in_executor, call:subprocess.run, call:os.path.dirname, call:os.path.abspath, call:logger.debug, call:logger.error, call:asyncio.sleep, call:str(exc).lower, call:logger.warning | dep: asyncio, logging, os, subprocess, sqlalchemy.ext.asyncio, sqlalchemy.pool, src.config, sqlalchemy
- logging_config.py | Configures structured JSON logging with correlation ID injection, request/response logging middleware, and exception handling for a FastAPI application. | exp: class:CorrelationIdFilter, method:filter(self, record: logging.LogRecord) → bool, call:get_correlation_id, class:JSONFormatter, method:format(self, record: logging.LogRecord) → str, call:self.formatTime, call:record.getMessage, call:getattr, call:self.formatException, call:json.dumps, method:formatTime(self, record: logging.LogRecord, datefmt) → str, call:time.strftime, call:time.gmtime, class:RequestLoggingMiddleware, method:dispatch(self, request: Request, call_next: Callable) → Response, call:time.time, call:logger.info, call:call_next, call:int, call:logger.error, call:type, call:traceback.format_exc, class:ExceptionLoggingMiddleware, method:dispatch(self, request: Request, call_next: Callable) → Response, call:call_next, call:logger.critical, call:traceback.format_exc, func:configure_logging(level) → None, call:JSONFormatter, call:logging.StreamHandler, call:console_handler.setFormatter, call:console_handler.addFilter, call:CorrelationIdFilter, call:root_logger.setLevel, call:logging.getLogger("uvicorn").setLevel, call:logging.getLogger("uvicorn.access").setLevel, call:logging.getLogger("sqlalchemy.engine").setLevel, call:logger.info, call:logging.getLevelName | dep: json, logging, sys, time, traceback, collections.abc, fastapi, starlette.middleware.base, src.services.shared.correlation, starlette
- main.py | Bootstraps a FastAPI application called "Headquarter API" with database initialization, health monitoring, CORS, logging middleware, and modular API routers. | exp: func:_sanitize_validation_errors(errors), call:error.get, call:str, call:ctx.items, call:isinstance, call:type, call:sanitized.append, func:validation_exception_handler(request: Request, exc: RequestValidationError), call:exc.errors, call:logger.warning, call:_sanitize_validation_errors, call:JSONResponse, func:on_startup(), call:logger.info, call:init_database, call:logger.error, call:sys.exit, call:_health_monitor.start, call:seed_builtin_tool_types, func:on_shutdown(), call:logger.info, call:_health_monitor.stop | dep: logging, os, fastapi, fastapi.exceptions, fastapi.middleware.cors, fastapi.responses, fastapi.staticfiles, src.api.config, src.api.project, src.api.system, src.api.tool, src.api.user, src.api.workspace, src.config, src.models, src.database, src.logging_config, src.seeds.builtin_tool_types, src.services.instance, src.services.shared, sys, src.api
## arch
Layered architecture with Pydantic-based settings management, async SQLAlchemy with Alembic migrations, structured JSON logging with correlation ID tracking, and modular FastAPI initialization with middleware pipeline.
Layered architecture with separation of concerns across config (settings/env), database (async SQLAlchemy with Alembic migrations), logging (structured JSON with middleware), and main (app composition with modular routers and health monitoring).
## tags
src, database, logging, call:logger.info, api, middleware, fastapi, filter
src, logging, database, api, call:logger.info, middleware, fastapi, filter
## symbols
- Settings
- CorrelationIdFilter
@@ -30,6 +30,6 @@ src, database, logging, call:logger.info, api, middleware, fastapi, filter
- change src config
read: config.py, logging_config.py
- explore src subdirectories
index: apps/api/src/api/.pi-map.index.md, apps/api/src/auth/.pi-map.index.md, apps/api/src/headquarter_api.egg-info/.pi-map.index.md
index: apps/api/src/api/.pi-map.index.md, apps/api/src/auth/.pi-map.index.md, apps/api/src/models/.pi-map.index.md
## dirty
-
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/api
## role
Defines the API routing package and shared validation utilities for the REST API layer.
Provides shared Pydantic validators and package initialization for API schema validation across the API layer.
## parent
index: apps/api/src/.pi-map.index.md
map: apps/api/src/.pi-map.md
+4 -4
View File
@@ -4,14 +4,14 @@ dir: apps/api/src/api
index: apps/api/src/api/.pi-map.index.md
## role
Defines the API routing package and shared validation utilities for the REST API layer.
Provides shared Pydantic validators and package initialization for API schema validation across the API layer.
## files
- __init__.py | Marks the directory as a Python package for API routers.
- shared_validators.py | Provides reusable Pydantic validator functions for API schema validation including mount paths, files, environment variables, and volume mounts. | exp: func:validate_mount_path(v: str | None) → str | None, call:v.startswith, raise:ValueError, func:validate_files(v: dict | None, max_size_bytes) → dict | None, call:v.items, call:path.startswith, call:len, call:content.encode, raise:ValueError, func:validate_env_vars(v: dict | None) → dict | None, call:isinstance, raise:ValueError, func:validate_volumes(v: list | None) → list | None, call:isinstance, call:enumerate, raise:ValueError
- shared_validators.py | Provides reusable Pydantic validators for API schema fields including mount paths, file dictionaries, environment variables, and volume mounts. | exp: func:validate_mount_path(v: str | None) → str | None, call:v.startswith, raise:ValueError, func:validate_files(v: dict | None, max_size_bytes) → dict | None, call:v.items, call:path.startswith, call:len, call:content.encode, raise:ValueError, func:validate_env_vars(v: dict | None) → dict | None, call:isinstance, raise:ValueError, func:validate_volumes(v: list | None) → list | None, call:isinstance, call:enumerate, raise:ValueError
## arch
Modular package structure with reusable Pydantic validators for cross-cutting API schema concerns.
Utility module pattern with reusable cross-cutting Pydantic validators for common API field types (mount paths, files, env vars, volumes).
## tags
validate, raise:value, error, call:isinstance, mount, api, init, path
validate, raise:value, error, call:isinstance, validators, mount, api, init
## symbols
- validate_mount_path
- validate_files
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/api/config
## role
Provides FastAPI API endpoints for managing user configuration settings and configuration profiles.
Provides FastAPI API endpoints for managing user configuration settings and config profiles.
## parent
index: apps/api/src/api/.pi-map.index.md
map: apps/api/src/api/.pi-map.md
+6 -6
View File
@@ -4,15 +4,15 @@ dir: apps/api/src/api/config
index: apps/api/src/api/config/.pi-map.index.md
## role
Provides FastAPI API endpoints for managing user configuration settings and configuration profiles.
Provides FastAPI API endpoints for managing user configuration settings and config profiles.
## files
- __init__.py | Aggregates and exports configuration-related API routers for the config module. | dep: src.api.config.config_profiles, src.api.config.user_config
- config_profiles.py | FastAPI router providing CRUD endpoints for user config profiles with includes, resolution, defaults, and git URL validation | exp: func:list_config_profiles(project_id, tool_type_id, current_user_id, session), call:select(ConfigProfile) .where(ConfigProfile.user_id == user_uuid) .options, call:selectinload, call:uuid.UUID, call:conditions.append, call:ConfigProfile.project_id.is_, call:ConfigProfile.tool_type_id.is_, call:query.where, call:or_, call:session.execute, call:result.scalars().all, call:profile_to_response, func:create_config_profile(data: ConfigProfileCreate, current_user_id, session), call:create_profile, call:logger.debug, call:profile_to_response, func:get_config_profile(profile_id: str, current_user_id, session), call:get_profile_with_includes, call:uuid.UUID, call:profile_to_response, raise:HTTPException, func:update_config_profile(profile_id: str, data: ConfigProfileUpdate, current_user_id, session), call:get_profile_with_includes, call:uuid.UUID, call:update_profile, call:logger.debug, call:profile_to_response, raise:HTTPException, func:delete_config_profile(profile_id: str, current_user_id, session), call:get_profile_with_includes, call:uuid.UUID, call:session.delete, call:session.commit, call:logger.debug, raise:HTTPException, func:update_profile_includes_endpoint(profile_id: str, data: ConfigProfileIncludeUpdate, current_user_id, session), call:get_profile_with_includes, call:uuid.UUID, call:update_includes, call:session.execute, call:select(ConfigProfileInclude).where, call:inc_result.scalars().all, call:logger.debug, call:profile_to_response, call:list, raise:HTTPException, func:preview_config_profile(profile_id: str, current_user_id, session), call:get_profile_with_includes, call:uuid.UUID, call:resolve_profile, call:resolved_profile_to_dict, raise:HTTPException, func:resolve_default_profile_endpoint(project_id, tool_type_id, current_user_id, session), call:resolve_default_profile, call:uuid.UUID, func:get_default_profiles_endpoint(user_id, session) → dict, call:session.execute, call:select(UserConfig).where, call:result.scalar_one_or_none, func:set_default_profiles_endpoint(data: DefaultProfilesUpdate, user_id, session) → dict, call:validate_default_profiles, call:get_or_create_user_config, call:session.commit, call:session.refresh, func:get_default_profile_for_tool_type_endpoint(tool_type_id: str, user_id, session) → dict, call:session.execute, call:select(UserConfig).where, call:result.scalar_one_or_none, call:user_config.default_profiles.get, func:validate_git_url_endpoint(data: ValidateGitUrlRequest, current_user_id, session) → ValidateGitUrlResponse, call:validate_git_url | dep: logging, uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, sqlalchemy.orm, src.auth.dependencies, src.models, src.schemas.config, src.services.config.config_profile_resolver, src.services.config.crud_service, src.services.config.resolver_service
- user_config.py | Provides FastAPI endpoints to get and update the current user's configuration settings, creating a default config if none exists. | exp: func:_get_or_create_config(session: AsyncSession, user_id: uuid.UUID) → UserConfig, call:session.execute, call:select(UserConfig).where, call:result.scalar_one_or_none, call:UserConfig, call:session.add, call:session.commit, call:session.refresh, func:get_user_config(user_id, session) → UserConfigResponse, call:_get_user, call:_get_or_create_config, call:UserConfigResponse.model_validate, func:update_user_config(data: UserConfigUpdate, user_id, session) → UserConfigResponse, call:_get_user, call:_get_or_create_config, call:data.model_dump, call:logger.debug, call:session.commit, call:session.refresh, call:UserConfigResponse.model_validate | dep: logging, uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.schemas.user
- __init__.py | Aggregates and exports config-related API routers for module-level access | dep: src.api.config.config_profiles, src.api.config.user_config
- config_profiles.py | FastAPI router providing CRUD endpoints for user-owned config profiles with include resolution, default profile management, and git URL validation. | exp: func:list_config_profiles(project_id, tool_type_id, current_user_id, session), call:select(ConfigProfile) .where(ConfigProfile.user_id == user_uuid) .options, call:selectinload, call:uuid.UUID, call:conditions.append, call:ConfigProfile.project_id.is_, call:ConfigProfile.tool_type_id.is_, call:query.where, call:or_, call:session.execute, call:result.scalars().all, call:profile_to_response, func:create_config_profile(data: ConfigProfileCreate, current_user_id, session), call:create_profile, call:logger.debug, call:profile_to_response, func:get_config_profile(profile_id: str, current_user_id, session), call:get_profile_with_includes, call:uuid.UUID, call:profile_to_response, raise:HTTPException, func:update_config_profile(profile_id: str, data: ConfigProfileUpdate, current_user_id, session), call:get_profile_with_includes, call:uuid.UUID, call:update_profile, call:logger.debug, call:profile_to_response, raise:HTTPException, func:delete_config_profile(profile_id: str, current_user_id, session), call:get_profile_with_includes, call:uuid.UUID, call:session.delete, call:session.commit, call:logger.debug, raise:HTTPException, func:update_profile_includes_endpoint(profile_id: str, data: ConfigProfileIncludeUpdate, current_user_id, session), call:get_profile_with_includes, call:uuid.UUID, call:update_includes, call:session.execute, call:select(ConfigProfileInclude).where, call:inc_result.scalars().all, call:logger.debug, call:profile_to_response, call:list, raise:HTTPException, func:preview_config_profile(profile_id: str, current_user_id, session), call:get_profile_with_includes, call:uuid.UUID, call:resolve_profile, call:resolved_profile_to_dict, raise:HTTPException, func:resolve_default_profile_endpoint(project_id, tool_type_id, current_user_id, session), call:resolve_default_profile, call:uuid.UUID, func:get_default_profiles_endpoint(user_id, session) → dict, call:session.execute, call:select(UserConfig).where, call:result.scalar_one_or_none, func:set_default_profiles_endpoint(data: DefaultProfilesUpdate, user_id, session) → dict, call:validate_default_profiles, call:get_or_create_user_config, call:session.commit, call:session.refresh, func:get_default_profile_for_tool_type_endpoint(tool_type_id: str, user_id, session) → dict, call:session.execute, call:select(UserConfig).where, call:result.scalar_one_or_none, call:user_config.default_profiles.get, func:validate_git_url_endpoint(data: ValidateGitUrlRequest, current_user_id, session) → ValidateGitUrlResponse, call:validate_git_url | dep: logging, uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, sqlalchemy.orm, src.auth.dependencies, src.models, src.schemas.config, src.services.config.config_profile_resolver, src.services.config.crud_service, src.services.config.resolver_service
- user_config.py | Provides FastAPI endpoints for retrieving and updating user configuration settings with automatic record creation. | exp: func:_get_or_create_config(session: AsyncSession, user_id: uuid.UUID) → UserConfig, call:session.execute, call:select(UserConfig).where, call:result.scalar_one_or_none, call:UserConfig, call:session.add, call:session.commit, call:session.refresh, func:get_user_config(user_id, session) → UserConfigResponse, call:_get_user, call:_get_or_create_config, call:UserConfigResponse.model_validate, func:update_user_config(data: UserConfigUpdate, user_id, session) → UserConfigResponse, call:_get_user, call:_get_or_create_config, call:data.model_dump, call:logger.debug, call:session.commit, call:session.refresh, call:UserConfigResponse.model_validate | dep: logging, uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.schemas.user
## arch
Modular FastAPI router pattern with separate route modules for distinct resource domains (user config vs config profiles), each implementing standard CRUD operations with validation and default initialization logic.
Modular router-based architecture using FastAPI with separate route modules for distinct config domains (profiles vs. user settings), CRUD patterns, and include resolution for hierarchical config.
## tags
config, profile, get, user, includes, call:uuid.uuid, or, default
config, profile, get, user, call:uuid.uuid, includes, or, default
## symbols
- list_config_profiles
- create_config_profile
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/api/project
## role
Provides FastAPI REST API endpoints for project and Git repository management, serving as the HTTP interface layer for the project's core domain operations.
Provides FastAPI REST API endpoints for project and Git repository management, exposing CRUD operations and version control functionality to API consumers.
## parent
index: apps/api/src/api/.pi-map.index.md
map: apps/api/src/api/.pi-map.md
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/api/system
## role
Provides system-level API endpoints for monitoring, administration, and infrastructure interaction including dashboards, health checks, event streaming, notifications, and container terminal access.
Provides system-level API endpoints for monitoring, administration, and operational infrastructure including health checks, dashboards, real-time events, notifications, and container terminal access.
## parent
index: apps/api/src/api/.pi-map.index.md
map: apps/api/src/api/.pi-map.md
+10 -10
View File
@@ -4,19 +4,19 @@ dir: apps/api/src/api/system
index: apps/api/src/api/system/.pi-map.index.md
## role
Provides system-level API endpoints for monitoring, administration, and infrastructure interaction including dashboards, health checks, event streaming, notifications, and container terminal access.
Provides system-level API endpoints for monitoring, administration, and operational infrastructure including health checks, dashboards, real-time events, notifications, and container terminal access.
## files
- __init__.py | Aggregates and re-exports system API router modules from submodules for centralized access. | dep: src.api.system.dashboard, src.api.system.events, src.api.system.health, src.api.system.instance_proxy, src.api.system.notifications, src.api.system.terminal
- dashboard.py | Provides a FastAPI endpoint that returns a dashboard summary with aggregated counts of projects, repositories, SSH keys, and recent activity for the authenticated user. | exp: func:get_dashboard_summary(user_id, session) → dict, call:session.execute, call:select(func.count()).select_from(Project).where, call:func.count, call:projects_result.scalar, call:select(func.count()).select_from(GitRepository).where, call:repos_result.scalar, call:select(func.count()).select_from(SSHKey).where, call:ssh_keys_result.scalar, call:select(Project) .where(Project.owner_id == user_id) .order_by(Project.created_at.desc()) .limit, call:Project.created_at.desc, call:recent_projects.scalars().all | dep: uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.models.project, src.models (GitRepository, Project, SSHKey)
- events.py | Implements an SSE streaming endpoint that delivers instance events to authenticated users with per-user connection limits and keep-alive pings. | exp: func:events_stream(request: Request, user_id) → StreamingResponse, call:_connection_counts.get, call:InstanceEventBus, call:asyncio.Queue, call:queue.put_nowait, call:contextlib.suppress, call:queue.get_nowait, call:event_bus.subscribe, call:asyncio.wait_for, call:queue.get, call:json.dumps, call:unsubscribe, call:max, call:_connection_counts.pop, call:StreamingResponse, call:event_generator, raise:HTTPException, func:event_generator() → AsyncGenerator[str, None], call:InstanceEventBus, call:asyncio.Queue, call:queue.put_nowait, call:contextlib.suppress, call:queue.get_nowait, call:event_bus.subscribe, call:asyncio.wait_for, call:queue.get, call:json.dumps, call:unsubscribe, call:max, call:_connection_counts.get, call:_connection_counts.pop, func:on_event(payload: InstanceEventPayload) → None, call:queue.put_nowait, call:contextlib.suppress, call:queue.get_nowait | dep: asyncio, contextlib, json, uuid, collections.abc, fastapi, fastapi.responses, src.auth.dependencies, src.services.instance.event_bus
- health.py | Implements FastAPI health check endpoints for monitoring system status including database connectivity and disk space. | exp: func:health_check() → dict[str, Any], call:HealthChecks, call:time_module.perf_counter, call:SessionLocal, call:session.execute, call:text, call:DatabaseHealth, call:round, call:shutil.disk_usage, call:DiskHealth, call:HealthResponse( status=overall_status, timestamp=datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"), version="0.1.0", checks=checks, uptime_seconds=round(time.time() - _start_time, 2), ).model_dump, call:datetime.now(timezone.utc).isoformat().replace, call:time.time, func:health_check_db() → dict[str, Any], call:time_module.perf_counter, call:SessionLocal, call:session.execute, call:text, call:DatabaseHealthResponse( status="healthy", response_time_ms=round(db_time, 2), ).model_dump, call:round, call:DatabaseHealthResponse( status="unhealthy", response_time_ms=0.0, ).model_dump | dep: time, datetime, typing, fastapi, sqlalchemy, src.database, src.schemas.system, shutil
- instance_proxy.py | Proxies HTTP requests from FastAPI endpoints to running containerized tool instances after verifying ownership and status. | exp: func:_proxy_request(request: Request, instance_id: uuid.UUID, path: str, user_id: uuid.UUID, session: AsyncSession) → Response, call:session.get, call:str, call:request.headers.items, call:key.lower, call:httpx.AsyncClient, call:request.body, call:client.request, call:logger.error, call:dict, call:response_headers.pop, call:Response, raise:HTTPException, func:proxy_to_instance(request: Request, instance_id: uuid.UUID, path, user_id, session) → Response, call:_proxy_request | dep: logging, uuid, httpx, fastapi, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models
- notifications.py | Defines FastAPI REST endpoints for managing user notifications (list, unread count, mark read, dismiss/clear) with support for muted categories from user config. | exp: class:NotificationItem, class:NotificationListResponse, class:UnreadCountResponse, class:MarkAllReadResponse, class:ClearAllResponse, func:_get_mute_categories(session: AsyncSession, user_id: uuid.UUID) → list[str], call:session.execute, call:select(UserConfig).where, call:result.scalar_one_or_none, call:config.config.get, call:isinstance, func:list_notifications(limit, offset, unread_only, user, session) → NotificationListResponse, call:_get_mute_categories, call:notification_service.list_notifications, call:NotificationListResponse, call:NotificationItem.model_validate, func:get_unread_count(user, session) → UnreadCountResponse, call:notification_service.get_unread_count, call:UnreadCountResponse, func:mark_notification_read(notification_id: uuid.UUID, user, session) → NotificationItem, call:notification_service.mark_read, call:NotificationItem.model_validate, raise:HTTPException, func:mark_all_read(user, session) → MarkAllReadResponse, call:notification_service.mark_all_read, call:MarkAllReadResponse, func:clear_all_notifications(user, session) → ClearAllResponse, call:notification_service.dismiss_all, call:ClearAllResponse, func:dismiss_notification(notification_id: uuid.UUID, user, session) → None, call:notification_service.dismiss, raise:HTTPException | dep: uuid, datetime, fastapi, pydantic, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models.user, src.models, src.services.shared.notification_service, sqlalchemy
- terminal.py | Provides WebSocket and HTTP endpoints for managing interactive terminal sessions attached to running Docker container tool instances, including session creation, attachment, input/output streaming, resize/reset control messages, and session listing. | exp: class:SessionRef, method:__init__(self, session, slot_session_id), func:terminal_websocket_default(websocket: WebSocket, instance_id: str, db_session) → None, call:_handle_terminal_websocket, func:terminal_websocket_specific(websocket: WebSocket, instance_id: str, session_id: str, db_session) → None, call:_handle_terminal_websocket, func:_handle_terminal_websocket(websocket: WebSocket, instance_id: str, target_session_id: str | None, db_session: AsyncSession) → None, call:logger.debug, call:websocket.accept, call:uuid.UUID, call:logger.error, call:websocket.close, call:_get_user_from_websocket, call:logger.warning, call:db_session.get, call:get_container_status, call:terminal_manager.get_or_create_session, call:terminal_manager.get_session, call:logger.info, call:terminal_manager.create_session, call:terminal_manager._find_key_by_internal_id, call:terminal_manager.attach_websocket, call:websocket.send_json, call:SessionRef, call:asyncio.create_task, call:_write_loop, call:_heartbeat_loop, call:asyncio.wait, call:len, call:task.cancel, call:str, call:suppress, call:terminal_manager.detach_websocket, func:_write_loop(session_ref: SessionRef, websocket, instance_id: str) → None, call:session.is_alive, call:asyncio.sleep, call:websocket.receive, call:session.write_input, call:text.startswith, call:json.loads, call:ctrl.get, call:logger.debug, call:session.resize, call:session.acknowledge_data, call:websocket.send_json, call:terminal_manager.reset_session, call:terminal_manager.attach_websocket, call:text.encode, func:_heartbeat_loop(websocket: WebSocket) → None, call:asyncio.sleep, call:websocket.send_json, func:_get_terminal_instance(instance_id: uuid.UUID, user_id: uuid.UUID, db_session: AsyncSession) → ToolInstance, call:db_session.get, raise:HTTPException, func:list_terminal_sessions(instance_id: uuid.UUID, user_id, db_session) → dict, call:_get_terminal_instance, call:db_session.execute, call:select(TerminalSessionModel) .where(TerminalSessionModel.instance_id == instance_id) .where(TerminalSessionModel.status != "closed") .order_by, call:TerminalSessionModel.created_at.asc, call:result.scalars().all, call:terminal_manager.get_session, call:str, call:sessions.append, call:live_session.has_websockets, call:row.created_at.isoformat, call:row.last_activity_at.isoformat, func:create_terminal_session(instance_id: uuid.UUID, data: dict, user_id, db_session) → dict, call:_get_terminal_instance, call:db_session.get, call:data.get, call:terminal_manager.create_session, raise:HTTPException, func:close_terminal_session(instance_id: uuid.UUID, session_id: str, user_id, db_session) → dict, call:_get_terminal_instance, call:terminal_manager._find_key_by_internal_id, call:str, call:terminal_manager.get_session, call:terminal_manager.close_session, raise:HTTPException, func:reset_specific_terminal_session(instance_id: uuid.UUID, session_id: str, user_id, db_session) → dict, call:_get_terminal_instance, call:terminal_manager._find_key_by_internal_id, call:str, call:terminal_manager.get_session, call:db_session.get, call:terminal_manager.reset_session, raise:HTTPException, func:rename_terminal_session(instance_id: uuid.UUID, session_id: str, data: dict, user_id, db_session) → dict, call:_get_terminal_instance, call:data.get, call:isinstance, call:terminal_manager.get_session, call:str, call:db_session.get, call:uuid.UUID, call:db_session.commit, raise:HTTPException, func:reset_terminal_session(instance_id: uuid.UUID, user_id, db_session) → dict, call:_get_terminal_instance, call:db_session.get, call:terminal_manager.reset_session, call:logger.info, call:str, call:logger.error, raise:HTTPException, func:_get_user_from_websocket(websocket: WebSocket, db_session: AsyncSession) → uuid.UUID | None, call:websocket.cookies.get, call:Settings, call:decode_session_cookie, call:uuid.UUID, call:str | dep: asyncio, json, logging, uuid, contextlib, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, starlette.websockets, src.auth.dependencies, src.models, src.services.terminal.terminal_manager, src.services.docker, src.auth.session, src.config, starlette
- __init__.py | Aggregates and re-exports system API routers from submodules for centralized access. | dep: src.api.system.dashboard, src.api.system.events, src.api.system.health, src.api.system.instance_proxy, src.api.system.notifications, src.api.system.terminal
- dashboard.py | Provides a FastAPI endpoint that returns a dashboard summary with counts of projects, repositories, SSH keys, and recent activity for the authenticated user. | exp: func:get_dashboard_summary(user_id, session) → dict, call:session.execute, call:select(func.count()).select_from(Project).where, call:func.count, call:projects_result.scalar, call:select(func.count()).select_from(GitRepository).where, call:repos_result.scalar, call:select(func.count()).select_from(SSHKey).where, call:ssh_keys_result.scalar, call:select(Project) .where(Project.owner_id == user_id) .order_by(Project.created_at.desc()) .limit, call:Project.created_at.desc, call:recent_projects.scalars().all | dep: uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.models.project
- events.py | Implements an SSE streaming endpoint that broadcasts instance events to authenticated users with per-user connection limits and backpressure handling. | exp: func:events_stream(request: Request, user_id) → StreamingResponse, call:_connection_counts.get, call:InstanceEventBus, call:asyncio.Queue, call:queue.put_nowait, call:contextlib.suppress, call:queue.get_nowait, call:event_bus.subscribe, call:asyncio.wait_for, call:queue.get, call:json.dumps, call:unsubscribe, call:max, call:_connection_counts.pop, call:StreamingResponse, call:event_generator, raise:HTTPException, func:event_generator() → AsyncGenerator[str, None], call:InstanceEventBus, call:asyncio.Queue, call:queue.put_nowait, call:contextlib.suppress, call:queue.get_nowait, call:event_bus.subscribe, call:asyncio.wait_for, call:queue.get, call:json.dumps, call:unsubscribe, call:max, call:_connection_counts.get, call:_connection_counts.pop, func:on_event(payload: InstanceEventPayload) → None, call:queue.put_nowait, call:contextlib.suppress, call:queue.get_nowait | dep: asyncio, contextlib, json, uuid, collections.abc, fastapi, fastapi.responses, src.auth.dependencies, src.services.instance.event_bus
- health.py | Provides FastAPI health check endpoints that monitor database connectivity, disk space, and system uptime with performance timing. | exp: func:health_check() → dict[str, Any], call:HealthChecks, call:time_module.perf_counter, call:SessionLocal, call:session.execute, call:text, call:DatabaseHealth, call:round, call:shutil.disk_usage, call:DiskHealth, call:HealthResponse( status=overall_status, timestamp=datetime.now(timezone.utc).isoformat().replace("+00:00", "Z"), version="0.1.0", checks=checks, uptime_seconds=round(time.time() - _start_time, 2), ).model_dump, call:datetime.now(timezone.utc).isoformat().replace, call:time.time, func:health_check_db() → dict[str, Any], call:time_module.perf_counter, call:SessionLocal, call:session.execute, call:text, call:DatabaseHealthResponse( status="healthy", response_time_ms=round(db_time, 2), ).model_dump, call:round, call:DatabaseHealthResponse( status="unhealthy", response_time_ms=0.0, ).model_dump | dep: time, datetime, typing, fastapi, sqlalchemy, src.database, src.schemas.system, shutil
- instance_proxy.py | HTTP proxy router that forwards incoming requests to running containerized tool instances after verifying ownership and instance status. | exp: func:_proxy_request(request: Request, instance_id: uuid.UUID, path: str, user_id: uuid.UUID, session: AsyncSession) → Response, call:session.get, call:str, call:request.headers.items, call:key.lower, call:httpx.AsyncClient, call:request.body, call:client.request, call:logger.error, call:dict, call:response_headers.pop, call:Response, raise:HTTPException, func:proxy_to_instance(request: Request, instance_id: uuid.UUID, path, user_id, session) → Response, call:_proxy_request | dep: logging, uuid, httpx, fastapi, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models
- notifications.py | Provides FastAPI REST endpoints for managing user notifications including listing, marking read/unread, dismissing, and clearing all notifications with support for muted categories. | exp: class:NotificationItem, class:NotificationListResponse, class:UnreadCountResponse, class:MarkAllReadResponse, class:ClearAllResponse, func:_get_mute_categories(session: AsyncSession, user_id: uuid.UUID) → list[str], call:session.execute, call:select(UserConfig).where, call:result.scalar_one_or_none, call:config.config.get, call:isinstance, func:list_notifications(limit, offset, unread_only, user, session) → NotificationListResponse, call:_get_mute_categories, call:notification_service.list_notifications, call:NotificationListResponse, call:NotificationItem.model_validate, func:get_unread_count(user, session) → UnreadCountResponse, call:notification_service.get_unread_count, call:UnreadCountResponse, func:mark_notification_read(notification_id: uuid.UUID, user, session) → NotificationItem, call:notification_service.mark_read, call:NotificationItem.model_validate, raise:HTTPException, func:mark_all_read(user, session) → MarkAllReadResponse, call:notification_service.mark_all_read, call:MarkAllReadResponse, func:clear_all_notifications(user, session) → ClearAllResponse, call:notification_service.dismiss_all, call:ClearAllResponse, func:dismiss_notification(notification_id: uuid.UUID, user, session) → None, call:notification_service.dismiss, raise:HTTPException | dep: uuid, datetime, fastapi, pydantic, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models.user, src.models, src.services.shared.notification_service, sqlalchemy
- terminal.py | Provides WebSocket and REST endpoints for browser-based terminal access to running Docker container tool instances, supporting multiple named sessions, authentication, and terminal reset/reconnect functionality. | exp: class:SessionRef, method:__init__(self, session, slot_session_id), func:terminal_websocket_default(websocket: WebSocket, instance_id: str, db_session) → None, call:_handle_terminal_websocket, func:terminal_websocket_specific(websocket: WebSocket, instance_id: str, session_id: str, db_session) → None, call:_handle_terminal_websocket, func:_handle_terminal_websocket(websocket: WebSocket, instance_id: str, target_session_id: str | None, db_session: AsyncSession) → None, call:logger.debug, call:websocket.accept, call:uuid.UUID, call:logger.error, call:websocket.close, call:_get_user_from_websocket, call:logger.warning, call:db_session.get, call:get_container_status, call:terminal_manager.get_or_create_session, call:terminal_manager.get_session, call:logger.info, call:terminal_manager.create_session, call:terminal_manager._find_key_by_internal_id, call:terminal_manager.attach_websocket, call:websocket.send_json, call:SessionRef, call:asyncio.create_task, call:_write_loop, call:_heartbeat_loop, call:asyncio.wait, call:len, call:task.cancel, call:str, call:suppress, call:terminal_manager.detach_websocket, func:_write_loop(session_ref: SessionRef, websocket, instance_id: str) → None, call:session.is_alive, call:asyncio.sleep, call:websocket.receive, call:session.write_input, call:text.startswith, call:json.loads, call:ctrl.get, call:logger.debug, call:session.resize, call:session.acknowledge_data, call:websocket.send_json, call:terminal_manager.reset_session, call:terminal_manager.attach_websocket, call:text.encode, func:_heartbeat_loop(websocket: WebSocket) → None, call:asyncio.sleep, call:websocket.send_json, func:_get_terminal_instance(instance_id: uuid.UUID, user_id: uuid.UUID, db_session: AsyncSession) → ToolInstance, call:db_session.get, raise:HTTPException, func:list_terminal_sessions(instance_id: uuid.UUID, user_id, db_session) → dict, call:_get_terminal_instance, call:db_session.execute, call:select(TerminalSessionModel) .where(TerminalSessionModel.instance_id == instance_id) .where(TerminalSessionModel.status != "closed") .order_by, call:TerminalSessionModel.created_at.asc, call:result.scalars().all, call:terminal_manager.get_session, call:str, call:sessions.append, call:live_session.has_websockets, call:row.created_at.isoformat, call:row.last_activity_at.isoformat, func:create_terminal_session(instance_id: uuid.UUID, data: dict, user_id, db_session) → dict, call:_get_terminal_instance, call:db_session.get, call:data.get, call:terminal_manager.create_session, raise:HTTPException, func:close_terminal_session(instance_id: uuid.UUID, session_id: str, user_id, db_session) → dict, call:_get_terminal_instance, call:terminal_manager._find_key_by_internal_id, call:str, call:terminal_manager.get_session, call:terminal_manager.close_session, raise:HTTPException, func:reset_specific_terminal_session(instance_id: uuid.UUID, session_id: str, user_id, db_session) → dict, call:_get_terminal_instance, call:terminal_manager._find_key_by_internal_id, call:str, call:terminal_manager.get_session, call:db_session.get, call:terminal_manager.reset_session, raise:HTTPException, func:rename_terminal_session(instance_id: uuid.UUID, session_id: str, data: dict, user_id, db_session) → dict, call:_get_terminal_instance, call:data.get, call:isinstance, call:terminal_manager.get_session, call:str, call:db_session.get, call:uuid.UUID, call:db_session.commit, raise:HTTPException, func:reset_terminal_session(instance_id: uuid.UUID, user_id, db_session) → dict, call:_get_terminal_instance, call:db_session.get, call:terminal_manager.reset_session, call:logger.info, call:str, call:logger.error, raise:HTTPException, func:_get_user_from_websocket(websocket: WebSocket, db_session: AsyncSession) → uuid.UUID | None, call:websocket.cookies.get, call:Settings, call:decode_session_cookie, call:uuid.UUID, call:str | dep: asyncio, json, logging, uuid, contextlib, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, starlette.websockets, src.auth.dependencies, src.models, src.services.terminal.terminal_manager, src.services.docker, src.auth.session, src.config, starlette
## arch
FastAPI router modules organized by domain concern with async/await patterns, SSE/WebSocket for real-time streaming, proxy pattern for container instance forwarding, and per-user authentication/authorization with connection limiting.
FastAPI router composition pattern with modular sub-routers aggregated via __init__.py, combining synchronous REST endpoints, SSE streaming, and WebSocket connections for real-time features, with authentication enforcement and resource ownership validation across operational and infrastructure concerns.
## tags
session, terminal, call:terminal, call:, src, get, response, websocket
terminal, session, call:terminal, call:, get, src, response, instance
## symbols
- NotificationItem
- NotificationListResponse
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/api/tool
## role
Provides FastAPI REST API endpoints for managing Docker-based tools, including their definitions, types, instances, lifecycle operations, and active sessions.
Provides FastAPI REST API endpoints for managing containerized tools throughout their lifecycle, including type definitions, instance management, session tracking, and Docker operations.
## parent
index: apps/api/src/api/.pi-map.index.md
map: apps/api/src/api/.pi-map.md
+8 -8
View File
@@ -4,17 +4,17 @@ dir: apps/api/src/api/tool
index: apps/api/src/api/tool/.pi-map.index.md
## role
Provides FastAPI REST API endpoints for managing Docker-based tools, including their definitions, types, instances, lifecycle operations, and active sessions.
Provides FastAPI REST API endpoints for managing containerized tools throughout their lifecycle, including type definitions, instance management, session tracking, and Docker operations.
## files
- __init__.py | Aggregates and exports all tool-related API routers from submodules as a unified module interface. | dep: src.api.tool.sessions, src.api.tool.tool_definitions, src.api.tool.tool_instances, src.api.tool.tool_lifecycle, src.api.tool.tool_types
- sessions.py | Provides a FastAPI endpoint to retrieve all active tool instances (sessions) for the currently authenticated user with related metadata. | exp: func:get_user_sessions(user_id, session) → dict, call:_get_user, call:session.execute, call:select(ToolInstance) .where(ToolInstance.owner_id == user_id) .where( ToolInstance.status.in_( ["running", "building", "pending", "stopped", "error"] ) ) .order_by, call:ToolInstance.status.in_, call:ToolInstance.created_at.desc, call:result.scalars().all, call:session.get, call:sessions.append, call:str, call:instance.created_at.isoformat | dep: uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.models (GitRepository, Project, ToolInstance, ToolType, Workspace)
- tool_definitions.py | FastAPI router providing CRUD endpoints and manifest compilation for tool definition manifests stored in a database. | exp: class:CreateToolDefinitionRequest, class:UpdateToolDefinitionRequest, func:create_tool_definition(data: CreateToolDefinitionRequest, user_id, session) → dict, call:uuid.UUID, call:session.get, call:session.execute, call:select(ToolDefinitionManifest).where, call:existing.scalar_one_or_none, call:ToolDefinitionManifest, call:session.add, call:session.commit, call:session.refresh, call:logger.info, call:str, call:definition.created_at.isoformat, raise:HTTPException, func:list_tool_definitions(user_id, session, include_bases) → dict, call:select, call:query.where, call:ToolDefinitionManifest.is_base.is_, call:session.execute, call:query.order_by, call:ToolDefinitionManifest.created_at.desc, call:result.scalars().all, call:str, call:d.created_at.isoformat, func:get_tool_definition(definition_id: uuid.UUID, user_id, session) → dict, call:session.get, call:str, call:definition.created_at.isoformat, call:definition.updated_at.isoformat, raise:HTTPException, func:update_tool_definition(definition_id: uuid.UUID, data: UpdateToolDefinitionRequest, user_id, session) → dict, call:session.get, call:session.commit, call:session.refresh, call:logger.info, call:str, call:definition.updated_at.isoformat, raise:HTTPException, func:delete_tool_definition(definition_id: uuid.UUID, user_id, session) → dict, call:session.get, call:session.execute, call:select(ToolType).where, call:result.scalars().all, call:", ".join, call:session.delete, call:session.commit, call:logger.info, call:str, raise:HTTPException, func:compile_tool_definition(definition_id: uuid.UUID, user_id, session) → dict, call:session.get, call:dict, call:resolve_base, call:deep_merge, call:compile_dockerfile, call:compile_entrypoint, call:compute_image_tag, call:compile_compose, call:session.commit, call:str, raise:HTTPException | dep: logging, uuid, fastapi, pydantic, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.services.build.manifest_compiler
- tool_instances.py | Provides FastAPI REST endpoints for managing tool instances including CRUD operations, logs, health checks, tunnel recreation, event history, and HTTP proxying to running containers. | exp: func:create_instance(project_id: uuid.UUID, repo_id: uuid.UUID, data: CreateInstanceRequest, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:create_tool_instance, call:str, call:instance.created_at.isoformat, raise:HTTPException, func:list_instances(project_id: uuid.UUID, repo_id: uuid.UUID, user_id, session) → list[dict], call:_get_user, call:_get_owned_project, call:session.execute, call:select(ToolInstance) .where(ToolInstance.repository_id == repo_id) .where(ToolInstance.owner_id == user_id) .order_by, call:ToolInstance.created_at.desc, call:result.scalars().all, call:str, call:i.created_at.isoformat, func:get_instance(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:session.get, call:get_container_status, call:str, call:instance.created_at.isoformat, call:instance.last_started_at.isoformat, raise:HTTPException, func:rename_instance(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, data: dict, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:data.get("display_name", "").strip, call:rename_tool_instance, call:str, raise:HTTPException, func:get_instance_logs(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, tail, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:session.get, call:get_container_logs, raise:HTTPException, func:recreate_tunnel_endpoint(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:recreate_instance_tunnel, raise:HTTPException, func:check_instance_tunnel_health(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:session.get, call:get_container_status, call:instance.probe_result.get, call:"\n".join, call:check_tunnel_health, call:tunnel_health.get, raise:HTTPException, func:get_instance_events(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, limit, user_id, session) → list[dict], call:_get_user, call:_get_owned_project, call:session.get, call:session.execute, call:select(InstanceEvent) .where(InstanceEvent.instance_id == instance_id) .order_by(InstanceEvent.created_at.desc()) .limit, call:InstanceEvent.created_at.desc, call:result.scalars().all, call:str, call:row.created_at.isoformat, raise:HTTPException, func:proxy_to_instance(request: Request, project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, path, user_id, session) → Response, call:session.get, call:str, call:dict, call:headers.pop, call:httpx.AsyncClient, call:request.body, call:client.request, call:logger.error, call:response_headers.pop, call:Response, raise:HTTPException | dep: logging, uuid, httpx, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.services.docker, src.services.shared.tunnel, src.schemas.tool, src.services.tool.instance_service
- __init__.py | Aggregates and exports router modules for the Tool API package. | dep: src.api.tool.sessions, src.api.tool.tool_definitions, src.api.tool.tool_instances, src.api.tool.tool_lifecycle, src.api.tool.tool_types
- sessions.py | Provides a FastAPI endpoint to retrieve all active tool sessions (running instances) for the currently authenticated user with related metadata. | exp: func:get_user_sessions(user_id, session) → dict, call:_get_user, call:session.execute, call:select(ToolInstance) .where(ToolInstance.owner_id == user_id) .where( ToolInstance.status.in_( ["running", "building", "pending", "stopped", "error"] ) ) .order_by, call:ToolInstance.status.in_, call:ToolInstance.created_at.desc, call:result.scalars().all, call:session.get, call:sessions.append, call:str, call:instance.created_at.isoformat | dep: uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models
- tool_definitions.py | Provides FastAPI CRUD endpoints for managing tool definition manifests with compilation to Dockerfile and Docker Compose previews. | exp: class:CreateToolDefinitionRequest, class:UpdateToolDefinitionRequest, func:create_tool_definition(data: CreateToolDefinitionRequest, user_id, session) → dict, call:uuid.UUID, call:session.get, call:session.execute, call:select(ToolDefinitionManifest).where, call:existing.scalar_one_or_none, call:ToolDefinitionManifest, call:session.add, call:session.commit, call:session.refresh, call:logger.info, call:str, call:definition.created_at.isoformat, raise:HTTPException, func:list_tool_definitions(user_id, session, include_bases) → dict, call:select, call:query.where, call:ToolDefinitionManifest.is_base.is_, call:session.execute, call:query.order_by, call:ToolDefinitionManifest.created_at.desc, call:result.scalars().all, call:str, call:d.created_at.isoformat, func:get_tool_definition(definition_id: uuid.UUID, user_id, session) → dict, call:session.get, call:str, call:definition.created_at.isoformat, call:definition.updated_at.isoformat, raise:HTTPException, func:update_tool_definition(definition_id: uuid.UUID, data: UpdateToolDefinitionRequest, user_id, session) → dict, call:session.get, call:session.commit, call:session.refresh, call:logger.info, call:str, call:definition.updated_at.isoformat, raise:HTTPException, func:delete_tool_definition(definition_id: uuid.UUID, user_id, session) → dict, call:session.get, call:session.execute, call:select(ToolType).where, call:result.scalars().all, call:", ".join, call:session.delete, call:session.commit, call:logger.info, call:str, raise:HTTPException, func:compile_tool_definition(definition_id: uuid.UUID, user_id, session) → dict, call:session.get, call:dict, call:resolve_base, call:deep_merge, call:compile_dockerfile, call:compile_entrypoint, call:compute_image_tag, call:compile_compose, call:session.commit, call:str, raise:HTTPException | dep: logging, uuid, fastapi, pydantic, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.services.build.manifest_compiler
- tool_instances.py | FastAPI router providing REST endpoints for managing tool instances (CRUD, logs, health checks, tunnel management, proxying, and event history) within project repositories. | exp: func:create_instance(project_id: uuid.UUID, repo_id: uuid.UUID, data: CreateInstanceRequest, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:create_tool_instance, call:str, call:instance.created_at.isoformat, raise:HTTPException, func:list_instances(project_id: uuid.UUID, repo_id: uuid.UUID, user_id, session) → list[dict], call:_get_user, call:_get_owned_project, call:session.execute, call:select(ToolInstance) .where(ToolInstance.repository_id == repo_id) .where(ToolInstance.owner_id == user_id) .order_by, call:ToolInstance.created_at.desc, call:result.scalars().all, call:str, call:i.created_at.isoformat, func:get_instance(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:session.get, call:get_container_status, call:str, call:instance.created_at.isoformat, call:instance.last_started_at.isoformat, raise:HTTPException, func:rename_instance(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, data: dict, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:data.get("display_name", "").strip, call:rename_tool_instance, call:str, raise:HTTPException, func:get_instance_logs(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, tail, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:session.get, call:get_container_logs, raise:HTTPException, func:recreate_tunnel_endpoint(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:recreate_instance_tunnel, raise:HTTPException, func:check_instance_tunnel_health(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:session.get, call:get_container_status, call:instance.probe_result.get, call:"\n".join, call:check_tunnel_health, call:tunnel_health.get, raise:HTTPException, func:get_instance_events(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, limit, user_id, session) → list[dict], call:_get_user, call:_get_owned_project, call:session.get, call:session.execute, call:select(InstanceEvent) .where(InstanceEvent.instance_id == instance_id) .order_by(InstanceEvent.created_at.desc()) .limit, call:InstanceEvent.created_at.desc, call:result.scalars().all, call:str, call:row.created_at.isoformat, raise:HTTPException, func:proxy_to_instance(request: Request, project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, path, user_id, session) → Response, call:session.get, call:str, call:dict, call:headers.pop, call:httpx.AsyncClient, call:request.body, call:client.request, call:logger.error, call:response_headers.pop, call:Response, raise:HTTPException | dep: logging, uuid, httpx, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.services.docker, src.services.shared.tunnel, src.schemas.tool, src.services.tool.instance_service
- tool_lifecycle.py | FastAPI router providing REST endpoints for managing Docker-based tool instance lifecycle operations (start, stop, restart, delete). | exp: func:start_instance(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, data, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:start_tool_instance, raise:HTTPException, func:stop_instance(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:stop_tool_instance, raise:HTTPException, func:restart_instance(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, user_id, session) → dict, call:_get_user, call:_get_owned_project, call:restart_tool_instance, raise:HTTPException, func:delete_instance(project_id: uuid.UUID, repo_id: uuid.UUID, instance_id: uuid.UUID, force, user_id, session) → None, call:_get_user, call:_get_owned_project, call:delete_tool_instance, call:str, call:detail.lower, raise:HTTPException | dep: logging, uuid, fastapi, sqlalchemy.ext.asyncio, src.auth.dependencies, src.schemas.tool, src.services.tool.instance_service
- tool_types.py | Defines FastAPI routes for CRUD operations and validation of Docker tool types with compose/dockerfile/manifest definitions. | exp: func:_require_admin(user: User) → None, func:create_tool_type(data: ToolTypeCreate, user_id, session) → ToolType, call:_get_user, call:_require_admin, call:session.scalar, call:select(ToolType).where, call:ToolType, call:session.add, call:session.commit, call:session.refresh, raise:HTTPException, func:list_tool_types(user_id, session) → list[ToolType], call:_get_user, call:session.execute, call:select(ToolType).order_by, call:list, call:result.scalars().all, func:get_tool_type(tool_type_id: uuid.UUID, user_id, session) → ToolType, call:_get_user, call:session.get, raise:HTTPException, func:update_tool_type(tool_type_id: uuid.UUID, data: ToolTypeUpdate, user_id, session) → ToolType, call:_get_user, call:_require_admin, call:session.get, call:data.model_dump, call:update_data.get, call:validate_compose_yaml, call:check_port_exposed, call:validate_required_variables, call:update_data.items, call:setattr, call:session.commit, call:session.refresh, raise:HTTPException, func:validate_tool_type_template(data: ToolTypeValidateRequest, user_id, session) → dict, call:_get_user, call:errors.append, call:validate_compose_yaml, call:str, call:data.dockerfile_template.strip().startswith, call:len, func:validate_tool_type(tool_type_id: uuid.UUID, user_id, session) → dict, call:_get_user, call:session.get, call:errors.append, call:validate_compose_yaml, call:str, call:tool_type.dockerfile_template.strip().startswith, call:len, raise:HTTPException, func:delete_tool_type(tool_type_id: uuid.UUID, user_id, session) → None, call:_get_user, call:_require_admin, call:session.get, call:session.delete, call:session.commit, raise:HTTPException | dep: uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.api.tool.tool_types_validation, src.auth.dependencies, src.models, src.models.user, src.schemas.tool
- tool_types_validation.py | Validates Docker Compose YAML templates by sanitizing template variables, parsing YAML structure, checking port exposure, and verifying required variables exist. | exp: func:sanitize_template_vars(template: str) → str, call:re.sub, func:validate_compose_yaml(template: str) → dict, call:sanitize_template_vars, call:yaml.safe_load, call:isinstance, raise:ValueError, func:check_port_exposed(parsed: dict, port: int) → bool, call:str, call:isinstance, call:parsed["services"].values, call:port_mapping.split, call:mapping.split, func:validate_required_variables(template: str, variables: list[str]) → None, raise:HTTPException | dep: re, yaml, fastapi
- tool_types.py | Defines FastAPI REST endpoints for CRUD operations on tool types with validation for Docker Compose, Dockerfile, and manifest definitions. | exp: func:_require_admin(user: User) → None, func:create_tool_type(data: ToolTypeCreate, user_id, session) → ToolType, call:_get_user, call:_require_admin, call:session.scalar, call:select(ToolType).where, call:ToolType, call:session.add, call:session.commit, call:session.refresh, raise:HTTPException, func:list_tool_types(user_id, session) → list[ToolType], call:_get_user, call:session.execute, call:select(ToolType).order_by, call:list, call:result.scalars().all, func:get_tool_type(tool_type_id: uuid.UUID, user_id, session) → ToolType, call:_get_user, call:session.get, raise:HTTPException, func:update_tool_type(tool_type_id: uuid.UUID, data: ToolTypeUpdate, user_id, session) → ToolType, call:_get_user, call:_require_admin, call:session.get, call:data.model_dump, call:update_data.get, call:validate_compose_yaml, call:check_port_exposed, call:validate_required_variables, call:update_data.items, call:setattr, call:session.commit, call:session.refresh, raise:HTTPException, func:validate_tool_type_template(data: ToolTypeValidateRequest, user_id, session) → dict, call:_get_user, call:errors.append, call:validate_compose_yaml, call:str, call:data.dockerfile_template.strip().startswith, call:len, func:validate_tool_type(tool_type_id: uuid.UUID, user_id, session) → dict, call:_get_user, call:session.get, call:errors.append, call:validate_compose_yaml, call:str, call:tool_type.dockerfile_template.strip().startswith, call:len, raise:HTTPException, func:delete_tool_type(tool_type_id: uuid.UUID, user_id, session) → None, call:_get_user, call:_require_admin, call:session.get, call:session.delete, call:session.commit, raise:HTTPException | dep: uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.api.tool.tool_types_validation, src.auth.dependencies, src.models, src.models.user, src.schemas.tool
- tool_types_validation.py | Provides validation utilities for Docker Compose templates including YAML parsing, port exposure checking, and required template variable verification. | exp: func:sanitize_template_vars(template: str) → str, call:re.sub, func:validate_compose_yaml(template: str) → dict, call:sanitize_template_vars, call:yaml.safe_load, call:isinstance, raise:ValueError, func:check_port_exposed(parsed: dict, port: int) → bool, call:str, call:isinstance, call:parsed["services"].values, call:port_mapping.split, call:mapping.split, func:validate_required_variables(template: str, variables: list[str]) → None, raise:HTTPException | dep: re, yaml, fastapi
## arch
Modular FastAPI router organization with clear separation of concerns across CRUD operations, Docker lifecycle management, YAML/Compose validation, and container proxying/tunneling.
Modular FastAPI router pattern with domain-driven separation of concerns (types, instances, sessions, lifecycle) and Docker-centric validation/compilation utilities for container orchestration.
## tags
get, call:, tool, raise:httpexception, user, instance, call:str, call:session.get
## symbols
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/api/user
## role
Provides authentication, user profile management, and SSH key operations for the API backend.
Provides user-facing API endpoints for authentication, profile management, and SSH key operations in the FastAPI backend.
## parent
index: apps/api/src/api/.pi-map.index.md
map: apps/api/src/api/.pi-map.md
+6 -6
View File
@@ -4,14 +4,14 @@ dir: apps/api/src/api/user
index: apps/api/src/api/user/.pi-map.index.md
## role
Provides authentication, user profile management, and SSH key operations for the API backend.
Provides user-facing API endpoints for authentication, profile management, and SSH key operations in the FastAPI backend.
## files
- __init__.py | Aggregates and exports user-related API routers from submodules for easy importing | dep: src.api.user.auth, src.api.user.ssh_keys, src.api.user.users
- auth.py | Implements OAuth2/OIDC authentication endpoints for a FastAPI application using Authentik as the identity provider, including login initiation, callback handling, logout, and current user retrieval. | exp: func:get_db_session() → AsyncGenerator[AsyncSession, None], call:SessionLocal, func:login(next) → RedirectResponse, call:Settings, call:token_urlsafe, call:build_login_redirect_url, call:logger.debug, call:RedirectResponse, call:response.set_cookie, func:callback(code: str, state: str, auth_state, auth_next, session) → RedirectResponse, call:logger.debug, call:logger.warning, call:Settings, call:httpx.AsyncClient, call:exchange_code_for_tokens, call:logger.info, call:logger.error, call:fetch_user_info, call:str, call:user_info.get, call:session.scalar, call:select(User).where, call:User, call:session.add, call:session.commit, call:session.refresh, call:create_session_cookie, call:build_cookie_options, call:cast, call:bool, call:cookie_options.get, call:RedirectResponse, call:redirect_response.set_cookie, call:redirect_response.delete_cookie, raise:HTTPException, func:logout(response: Response) → dict[str, str], call:Settings, call:build_cookie_options, call:cast, call:bool, call:str, call:cookie_options.get, call:response.delete_cookie, func:me(session_cookie, session) → dict[str, Any], call:logger.debug, call:bool, call:logger.warning, call:Settings, call:decode_session_cookie, call:session.get, call:logger.info, call:str, raise:HTTPException | dep: logging, secrets, typing, httpx, fastapi, fastapi.responses, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.cookies, src.auth.oidc, src.auth.session, src.config, src.database, src.models.user
- ssh_keys.py | Implements a FastAPI router for managing Ed25519 SSH key pairs, including generation, storage with encrypted private keys, listing, deletion, and cryptographic signing/verification operations. | exp: func:_get_fernet() → Fernet, call:Settings, call:hashlib.sha256(settings.session_secret.encode()).digest, call:settings.session_secret.encode, call:base64.urlsafe_b64encode, call:Fernet, func:generate_ssh_key_pair() → tuple[str, str], call:Ed25519PrivateKey.generate, call:private_key.public_key, call:private_key.private_bytes, call:serialization.NoEncryption, call:public_key.public_bytes, call:private_bytes.decode, call:public_bytes.decode, func:create_ssh_key(data: SSHKeyCreate, user_id, session) → SSHKey, call:_get_user, call:generate_ssh_key_pair, call:_get_fernet, call:fernet.encrypt(private_key.encode()).decode, call:private_key.encode, call:SSHKey, call:session.add, call:session.commit, call:session.refresh, func:list_ssh_keys(user_id, session) → list[SSHKey], call:_get_user, call:session.execute, call:select(SSHKey).where, call:list, call:result.scalars().all, func:delete_ssh_key(key_id: uuid.UUID, user_id, session) → None, call:_get_user, call:session.get, call:session.delete, call:session.commit, raise:HTTPException, func:sign_payload(key_id: uuid.UUID, data: SignPayloadRequest, user_id, session) → SignatureResponse, call:_get_user, call:session.get, call:_get_fernet, call:fernet.decrypt(ssh_key.private_key_encrypted.encode()).decode, call:ssh_key.private_key_encrypted.encode, call:serialization.load_ssh_private_key, call:private_key_pem.encode, call:private_key.sign, call:data.payload.encode, call:SignatureResponse, call:base64.b64encode(signature).decode, raise:HTTPException, func:verify_signature(key_id: uuid.UUID, data: VerifySignatureRequest, user_id, session) → VerifySignatureResponse, call:_get_user, call:session.get, call:serialization.load_ssh_public_key, call:ssh_key.public_key.encode, call:base64.b64decode, call:public_key.verify, call:data.payload.encode, call:VerifySignatureResponse, raise:HTTPException | dep: base64, uuid, cryptography.fernet, cryptography.hazmat.primitives, cryptography.hazmat.primitives.asymmetric.ed25519, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.config, src.models, src.schemas.project, hashlib, cryptography
- users.py | Implements FastAPI endpoints for authenticated user profile management including retrieval, updates, and avatar uploads. | exp: func:get_profile(user_id, session) → User, call:_get_user, func:update_profile(data: UserProfileUpdate, user_id, session) → User, call:_get_user, call:len, call:data.name.strip, call:data.email.strip, call:session.commit, call:session.refresh, raise:HTTPException, func:upload_avatar(file: UploadFile, user_id, session) → User, call:_get_user, call:file.read, call:len, call:Path, call:old_path.exists, call:old_path.unlink, call:filename_part.split(".")[-1].lower, call:uuid.uuid4, call:file_path.write_bytes, call:session.commit, call:session.refresh, raise:HTTPException | dep: uuid, pathlib, fastapi, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models.user, src.schemas.user
- __init__.py | Aggregates and exports user-related API routers from submodules for easy importing. | dep: src.api.user.auth, src.api.user.ssh_keys, src.api.user.users
- auth.py | Implements OAuth2/OIDC authentication endpoints for a FastAPI application using Authentik as the identity provider, including login initiation, callback handling, session management, logout, and current user retrieval. | exp: func:get_db_session() → AsyncGenerator[AsyncSession, None], call:SessionLocal, func:login(next) → RedirectResponse, call:Settings, call:token_urlsafe, call:build_login_redirect_url, call:logger.debug, call:RedirectResponse, call:response.set_cookie, func:callback(code: str, state: str, auth_state, auth_next, session) → RedirectResponse, call:logger.debug, call:logger.warning, call:Settings, call:httpx.AsyncClient, call:exchange_code_for_tokens, call:logger.info, call:logger.error, call:fetch_user_info, call:str, call:user_info.get, call:session.scalar, call:select(User).where, call:User, call:session.add, call:session.commit, call:session.refresh, call:create_session_cookie, call:build_cookie_options, call:cast, call:bool, call:cookie_options.get, call:RedirectResponse, call:redirect_response.set_cookie, call:redirect_response.delete_cookie, raise:HTTPException, func:logout(response: Response) → dict[str, str], call:Settings, call:build_cookie_options, call:cast, call:bool, call:str, call:cookie_options.get, call:response.delete_cookie, func:me(session_cookie, session) → dict[str, Any], call:logger.debug, call:bool, call:logger.warning, call:Settings, call:decode_session_cookie, call:session.get, call:logger.info, call:str, raise:HTTPException | dep: logging, secrets, typing, httpx, fastapi, fastapi.responses, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.cookies, src.auth.oidc, src.auth.session, src.config, src.database, src.models.user
- ssh_keys.py | FastAPI router for managing Ed25519 SSH keys including generation, storage with encrypted private keys, signing payloads, and signature verification | exp: func:_get_fernet() → Fernet, call:Settings, call:hashlib.sha256(settings.session_secret.encode()).digest, call:settings.session_secret.encode, call:base64.urlsafe_b64encode, call:Fernet, func:generate_ssh_key_pair() → tuple[str, str], call:Ed25519PrivateKey.generate, call:private_key.public_key, call:private_key.private_bytes, call:serialization.NoEncryption, call:public_key.public_bytes, call:private_bytes.decode, call:public_bytes.decode, func:create_ssh_key(data: SSHKeyCreate, user_id, session) → SSHKey, call:_get_user, call:generate_ssh_key_pair, call:_get_fernet, call:fernet.encrypt(private_key.encode()).decode, call:private_key.encode, call:SSHKey, call:session.add, call:session.commit, call:session.refresh, func:list_ssh_keys(user_id, session) → list[SSHKey], call:_get_user, call:session.execute, call:select(SSHKey).where, call:list, call:result.scalars().all, func:delete_ssh_key(key_id: uuid.UUID, user_id, session) → None, call:_get_user, call:session.get, call:session.delete, call:session.commit, raise:HTTPException, func:sign_payload(key_id: uuid.UUID, data: SignPayloadRequest, user_id, session) → SignatureResponse, call:_get_user, call:session.get, call:_get_fernet, call:fernet.decrypt(ssh_key.private_key_encrypted.encode()).decode, call:ssh_key.private_key_encrypted.encode, call:serialization.load_ssh_private_key, call:private_key_pem.encode, call:private_key.sign, call:data.payload.encode, call:SignatureResponse, call:base64.b64encode(signature).decode, raise:HTTPException, func:verify_signature(key_id: uuid.UUID, data: VerifySignatureRequest, user_id, session) → VerifySignatureResponse, call:_get_user, call:session.get, call:serialization.load_ssh_public_key, call:ssh_key.public_key.encode, call:base64.b64decode, call:public_key.verify, call:data.payload.encode, call:VerifySignatureResponse, raise:HTTPException | dep: base64, uuid, cryptography.fernet, cryptography.hazmat.primitives, cryptography.hazmat.primitives.asymmetric.ed25519, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.config, src.models, src.schemas.project, hashlib, cryptography
- users.py | Implements FastAPI endpoints for user profile management including retrieval, updates, and avatar uploads with file validation. | exp: func:get_profile(user_id, session) → User, call:_get_user, func:update_profile(data: UserProfileUpdate, user_id, session) → User, call:_get_user, call:len, call:data.name.strip, call:data.email.strip, call:session.commit, call:session.refresh, raise:HTTPException, func:upload_avatar(file: UploadFile, user_id, session) → User, call:_get_user, call:file.read, call:len, call:Path, call:old_path.exists, call:old_path.unlink, call:filename_part.split(".")[-1].lower, call:uuid.uuid4, call:file_path.write_bytes, call:session.commit, call:session.refresh, raise:HTTPException | dep: uuid, pathlib, fastapi, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models.user, src.schemas.user, sqlalchemy
## arch
Modular FastAPI router pattern with OAuth2/OIDC external identity provider integration, encrypted key storage, and file-based avatar handling.
Modular FastAPI router pattern with separate submodules for distinct concerns (auth, profile, SSH keys), using OAuth2/OIDC external identity provider (Authentik), encrypted key storage, and file upload handling.
## tags
user, get, call:, key, ssh, src, cookie, raise:httpexception
## symbols
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/api/workspace
## role
Provides FastAPI REST API endpoints for workspace management, including file operations, git version control, and tool instance orchestration within user-scoped development environments.
Provides REST API endpoints for managing user workspaces, including file operations, Git version control, tool instances, and workspace lifecycle management.
## parent
index: apps/api/src/api/.pi-map.index.md
map: apps/api/src/api/.pi-map.md
+7 -7
View File
@@ -4,15 +4,15 @@ dir: apps/api/src/api/workspace
index: apps/api/src/api/workspace/.pi-map.index.md
## role
Provides FastAPI REST API endpoints for workspace management, including file operations, git version control, and tool instance orchestration within user-scoped development environments.
Provides REST API endpoints for managing user workspaces, including file operations, Git version control, tool instances, and workspace lifecycle management.
## files
- __init__.py | Aggregates and re-exports workspace API router modules for centralized access | dep: src.api.workspace.workspace_files, src.api.workspace.workspace_git, src.api.workspace.workspace_instances, src.api.workspace.workspaces
- workspace_files.py | Provides FastAPI endpoints for listing, reading, and writing files within user workspaces with optional git commit integration. | exp: func:_get_workspace(session: AsyncSession, workspace_id: uuid.UUID, user_id: uuid.UUID) → Workspace, call:session.execute, call:select(Workspace).where, call:result.scalar_one_or_none, raise:HTTPException, func:list_files(workspace_id: uuid.UUID, path, user_id, session) → dict, call:_get_workspace, call:FileService, call:service.list_directory, raise:HTTPException, func:get_file_content(workspace_id: uuid.UUID, path: str, user_id, session) → dict, call:_get_workspace, call:FileService, call:service.read_file, raise:HTTPException, func:write_file(workspace_id: uuid.UUID, data: dict, user_id, session) → dict, call:_get_workspace, call:FileService, call:data.get("path", "").strip, call:data.get("message", "").strip, call:service.write_file, call:GitOperations, call:git.commit, raise:HTTPException | dep: uuid, fastapi, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.services.shared.file_service, sqlalchemy, src.services.git.git_operations
- workspace_git.py | Provides FastAPI REST endpoints for git operations (status, branches, commit, push, pull, fetch, checkout, history) scoped to user workspaces. | exp: func:_get_workspace(session: AsyncSession, workspace_id: uuid.UUID, user_id: uuid.UUID) → Workspace, call:session.execute, call:select(Workspace).where, call:result.scalar_one_or_none, raise:HTTPException, func:git_status(workspace_id: uuid.UUID, user_id, session) → dict, call:_get_workspace, call:GitOperations, call:git.status, raise:HTTPException, func:git_branches(workspace_id: uuid.UUID, user_id, session) → dict, call:_get_workspace, call:GitOperations, call:git.branches, raise:HTTPException, func:git_commit(workspace_id: uuid.UUID, data: dict, user_id, session) → dict, call:_get_workspace, call:data.get("message", "").strip, call:GitOperations, call:git.commit, raise:HTTPException, func:git_push(workspace_id: uuid.UUID, user_id, session) → dict, call:_get_workspace, call:GitOperations, call:git.push, raise:HTTPException, func:git_pull(workspace_id: uuid.UUID, user_id, session) → dict, call:_get_workspace, call:GitOperations, call:git.pull, raise:HTTPException, func:git_fetch(workspace_id: uuid.UUID, user_id, session) → dict, call:_get_workspace, call:GitOperations, call:git.fetch, raise:HTTPException, func:git_checkout(workspace_id: uuid.UUID, data: dict, user_id, session) → dict, call:_get_workspace, call:data.get("branch", "").strip, call:GitOperations, call:git.checkout, call:session.commit, raise:HTTPException, func:git_history(workspace_id: uuid.UUID, path, limit, user_id, session) → dict, call:_get_workspace, call:GitOperations, call:git.history, raise:HTTPException | dep: uuid, fastapi, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.services.git.git_operations, sqlalchemy
- workspace_instances.py | FastAPI router providing endpoints to create and list tool instances associated with a specific workspace. | exp: func:_get_workspace(session: AsyncSession, workspace_id: uuid.UUID, user_id: uuid.UUID) → Workspace, call:session.execute, call:select(Workspace).where, call:result.scalar_one_or_none, raise:HTTPException, func:create_workspace_instance(workspace_id: uuid.UUID, data: CreateWorkspaceInstanceRequest, user_id, session) → dict, call:_get_workspace, call:session.get, call:CreateInstanceRequest, call:str, call:create_tool_instance, call:instance.created_at.isoformat, raise:HTTPException, func:list_workspace_instances(workspace_id: uuid.UUID, user_id, session) → list[dict], call:_get_workspace, call:session.execute, call:select(ToolInstance) .where(ToolInstance.workspace_id == workspace_id) .order_by, call:ToolInstance.created_at.desc, call:result.scalars().all, call:str, call:i.created_at.isoformat | dep: uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.schemas.tool, src.services.tool.instance_service
- workspaces.py | FastAPI router providing CRUD endpoints for managing Git repository workspaces with nested and top-level URL structures. | exp: func:list_all_workspaces(user_id, session) → list[dict], call:select(func.count(ToolInstance.id)) .where(ToolInstance.workspace_id == Workspace.id) .correlate(Workspace) .scalar_subquery, call:func.count, call:session.execute, call:select( Workspace, GitRepository, instance_count.label("instance_count"), ) .join(GitRepository, Workspace.repo_id == GitRepository.id) .options(selectinload(GitRepository.project)) .where(Workspace.user_id == user_id) .order_by, call:instance_count.label, call:selectinload, call:Workspace.created_at.desc, call:result.all, call:str, call:ws.last_sync_at.isoformat, call:ws.created_at.isoformat, call:ws.updated_at.isoformat, func:delete_workspace_top_level(workspace_id: uuid.UUID, force, user_id, session) → dict, call:session.get, call:WorkspaceManager, call:manager.delete, call:session.commit, call:session.rollback, call:logger.error, raise:HTTPException, func:create_workspace_top_level(data: dict, user_id, session) → dict, call:data.get("repo_id", "").strip, call:uuid.UUID, call:session.get, call:data.get("name", "").strip, call:data.get("branch", "main").strip, call:WorkspaceManager, call:manager.create, call:session.add, call:session.commit, call:session.rollback, call:logger.error, call:session.refresh, call:str, call:workspace.created_at.isoformat, raise:HTTPException, func:list_workspaces(project_id: uuid.UUID, repo_id: uuid.UUID, user_id, session) → list[dict], call:_get_repo, call:select(func.count(ToolInstance.id)) .where(ToolInstance.workspace_id == Workspace.id) .correlate(Workspace) .scalar_subquery, call:func.count, call:session.execute, call:select( Workspace, instance_count.label("instance_count"), ) .where(Workspace.repo_id == repo_id) .order_by, call:instance_count.label, call:Workspace.created_at.desc, call:result.all, call:str, call:ws.last_sync_at.isoformat, call:ws.created_at.isoformat, call:ws.updated_at.isoformat, func:create_workspace(project_id: uuid.UUID, repo_id: uuid.UUID, data: dict, user_id, session) → dict, call:_get_repo, call:data.get("name", "").strip, call:data.get("branch", "main").strip, call:WorkspaceManager, call:manager.create, call:session.add, call:session.commit, call:session.rollback, call:logger.error, call:session.refresh, call:str, call:workspace.created_at.isoformat, raise:HTTPException, func:get_workspace_detail(project_id: uuid.UUID, repo_id: uuid.UUID, workspace_id: uuid.UUID, user_id, session) → dict, call:_get_repo, call:_get_workspace, call:session.execute, call:select(func.count(ToolInstance.id)).where, call:func.count, call:result.scalar, call:str, call:workspace.last_sync_at.isoformat, call:workspace.created_at.isoformat, call:workspace.updated_at.isoformat, func:update_workspace(project_id: uuid.UUID, repo_id: uuid.UUID, workspace_id: uuid.UUID, data: dict, user_id, session) → dict, call:_get_repo, call:_get_workspace, call:data.get("name", "").strip, call:data.get("branch", "").strip, call:session.commit, call:session.rollback, call:logger.error, call:str, raise:HTTPException, func:delete_workspace(project_id: uuid.UUID, repo_id: uuid.UUID, workspace_id: uuid.UUID, force, user_id, session) → dict, call:_get_repo, call:_get_workspace, call:WorkspaceManager, call:manager.delete, call:session.commit, call:session.rollback, call:logger.error, raise:HTTPException, func:sync_workspace(project_id: uuid.UUID, repo_id: uuid.UUID, workspace_id: uuid.UUID, user_id, session) → dict, call:_get_repo, call:_get_workspace, call:WorkspaceManager, call:manager.sync, call:session.commit, call:workspace.last_sync_at.isoformat, raise:HTTPException, func:_get_repo(session: AsyncSession, repo_id: uuid.UUID, project_id: uuid.UUID, user_id: uuid.UUID) → GitRepository, call:session.execute, call:select(GitRepository) .where( GitRepository.id == repo_id, GitRepository.project_id == project_id, ) .options, call:selectinload, call:result.scalar_one_or_none, raise:HTTPException, func:_get_workspace(session: AsyncSession, workspace_id: uuid.UUID, repo_id: uuid.UUID) → Workspace, call:session.execute, call:select(Workspace).where, call:result.scalar_one_or_none, raise:HTTPException | dep: logging, uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, sqlalchemy.orm, src.auth.dependencies, src.models, src.services.shared.workspace_manager
- __init__.py | Aggregates and re-exports workspace-related API routers from submodules for centralized access. | dep: src.api.workspace.workspace_files, src.api.workspace.workspace_git, src.api.workspace.workspace_instances, src.api.workspace.workspaces
- workspace_files.py | Provides FastAPI endpoints for listing, reading, and writing files within user-owned workspaces with optional Git commit integration. | exp: func:_get_workspace(session: AsyncSession, workspace_id: uuid.UUID, user_id: uuid.UUID) → Workspace, call:session.execute, call:select(Workspace).where, call:result.scalar_one_or_none, raise:HTTPException, func:list_files(workspace_id: uuid.UUID, path, user_id, session) → dict, call:_get_workspace, call:FileService, call:service.list_directory, raise:HTTPException, func:get_file_content(workspace_id: uuid.UUID, path: str, user_id, session) → dict, call:_get_workspace, call:FileService, call:service.read_file, raise:HTTPException, func:write_file(workspace_id: uuid.UUID, data: dict, user_id, session) → dict, call:_get_workspace, call:FileService, call:data.get("path", "").strip, call:data.get("message", "").strip, call:service.write_file, call:GitOperations, call:git.commit, raise:HTTPException | dep: uuid, fastapi, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.services.shared.file_service, sqlalchemy, src.services.git.git_operations
- workspace_git.py | Provides FastAPI REST endpoints for executing git operations (status, branches, commit, push, pull, fetch, checkout, history) on user workspaces with authentication and database persistence. | exp: func:_get_workspace(session: AsyncSession, workspace_id: uuid.UUID, user_id: uuid.UUID) → Workspace, call:session.execute, call:select(Workspace).where, call:result.scalar_one_or_none, raise:HTTPException, func:git_status(workspace_id: uuid.UUID, user_id, session) → dict, call:_get_workspace, call:GitOperations, call:git.status, raise:HTTPException, func:git_branches(workspace_id: uuid.UUID, user_id, session) → dict, call:_get_workspace, call:GitOperations, call:git.branches, raise:HTTPException, func:git_commit(workspace_id: uuid.UUID, data: dict, user_id, session) → dict, call:_get_workspace, call:data.get("message", "").strip, call:GitOperations, call:git.commit, raise:HTTPException, func:git_push(workspace_id: uuid.UUID, user_id, session) → dict, call:_get_workspace, call:GitOperations, call:git.push, raise:HTTPException, func:git_pull(workspace_id: uuid.UUID, user_id, session) → dict, call:_get_workspace, call:GitOperations, call:git.pull, raise:HTTPException, func:git_fetch(workspace_id: uuid.UUID, user_id, session) → dict, call:_get_workspace, call:GitOperations, call:git.fetch, raise:HTTPException, func:git_checkout(workspace_id: uuid.UUID, data: dict, user_id, session) → dict, call:_get_workspace, call:data.get("branch", "").strip, call:GitOperations, call:git.checkout, call:session.commit, raise:HTTPException, func:git_history(workspace_id: uuid.UUID, path, limit, user_id, session) → dict, call:_get_workspace, call:GitOperations, call:git.history, raise:HTTPException | dep: uuid, fastapi, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.services.git.git_operations, sqlalchemy
- workspace_instances.py | Defines FastAPI endpoints for creating and listing tool instances associated with a specific workspace. | exp: func:_get_workspace(session: AsyncSession, workspace_id: uuid.UUID, user_id: uuid.UUID) → Workspace, call:session.execute, call:select(Workspace).where, call:result.scalar_one_or_none, raise:HTTPException, func:create_workspace_instance(workspace_id: uuid.UUID, data: CreateWorkspaceInstanceRequest, user_id, session) → dict, call:_get_workspace, call:session.get, call:CreateInstanceRequest, call:str, call:create_tool_instance, call:instance.created_at.isoformat, raise:HTTPException, func:list_workspace_instances(workspace_id: uuid.UUID, user_id, session) → list[dict], call:_get_workspace, call:session.execute, call:select(ToolInstance) .where(ToolInstance.workspace_id == workspace_id) .order_by, call:ToolInstance.created_at.desc, call:result.scalars().all, call:str, call:i.created_at.isoformat | dep: uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.auth.dependencies, src.models, src.schemas.tool, src.services.tool.instance_service
- workspaces.py | FastAPI router providing CRUD endpoints for managing Git workspaces with repository integration, instance tracking, and sync capabilities. | exp: func:list_all_workspaces(user_id, session) → list[dict], call:select(func.count(ToolInstance.id)) .where(ToolInstance.workspace_id == Workspace.id) .correlate(Workspace) .scalar_subquery, call:func.count, call:session.execute, call:select( Workspace, GitRepository, instance_count.label("instance_count"), ) .join(GitRepository, Workspace.repo_id == GitRepository.id) .options(selectinload(GitRepository.project)) .where(Workspace.user_id == user_id) .order_by, call:instance_count.label, call:selectinload, call:Workspace.created_at.desc, call:result.all, call:str, call:ws.last_sync_at.isoformat, call:ws.created_at.isoformat, call:ws.updated_at.isoformat, func:delete_workspace_top_level(workspace_id: uuid.UUID, force, user_id, session) → dict, call:session.get, call:WorkspaceManager, call:manager.delete, call:session.commit, call:session.rollback, call:logger.error, raise:HTTPException, func:create_workspace_top_level(data: dict, user_id, session) → dict, call:data.get("repo_id", "").strip, call:uuid.UUID, call:session.get, call:data.get("name", "").strip, call:data.get("branch", "main").strip, call:WorkspaceManager, call:manager.create, call:session.add, call:session.commit, call:session.rollback, call:logger.error, call:session.refresh, call:str, call:workspace.created_at.isoformat, raise:HTTPException, func:list_workspaces(project_id: uuid.UUID, repo_id: uuid.UUID, user_id, session) → list[dict], call:_get_repo, call:select(func.count(ToolInstance.id)) .where(ToolInstance.workspace_id == Workspace.id) .correlate(Workspace) .scalar_subquery, call:func.count, call:session.execute, call:select( Workspace, instance_count.label("instance_count"), ) .where(Workspace.repo_id == repo_id) .order_by, call:instance_count.label, call:Workspace.created_at.desc, call:result.all, call:str, call:ws.last_sync_at.isoformat, call:ws.created_at.isoformat, call:ws.updated_at.isoformat, func:create_workspace(project_id: uuid.UUID, repo_id: uuid.UUID, data: dict, user_id, session) → dict, call:_get_repo, call:data.get("name", "").strip, call:data.get("branch", "main").strip, call:WorkspaceManager, call:manager.create, call:session.add, call:session.commit, call:session.rollback, call:logger.error, call:session.refresh, call:str, call:workspace.created_at.isoformat, raise:HTTPException, func:get_workspace_detail(project_id: uuid.UUID, repo_id: uuid.UUID, workspace_id: uuid.UUID, user_id, session) → dict, call:_get_repo, call:_get_workspace, call:session.execute, call:select(func.count(ToolInstance.id)).where, call:func.count, call:result.scalar, call:str, call:workspace.last_sync_at.isoformat, call:workspace.created_at.isoformat, call:workspace.updated_at.isoformat, func:update_workspace(project_id: uuid.UUID, repo_id: uuid.UUID, workspace_id: uuid.UUID, data: dict, user_id, session) → dict, call:_get_repo, call:_get_workspace, call:data.get("name", "").strip, call:data.get("branch", "").strip, call:session.commit, call:session.rollback, call:logger.error, call:str, raise:HTTPException, func:delete_workspace(project_id: uuid.UUID, repo_id: uuid.UUID, workspace_id: uuid.UUID, force, user_id, session) → dict, call:_get_repo, call:_get_workspace, call:WorkspaceManager, call:manager.delete, call:session.commit, call:session.rollback, call:logger.error, raise:HTTPException, func:sync_workspace(project_id: uuid.UUID, repo_id: uuid.UUID, workspace_id: uuid.UUID, user_id, session) → dict, call:_get_repo, call:_get_workspace, call:WorkspaceManager, call:manager.sync, call:session.commit, call:workspace.last_sync_at.isoformat, raise:HTTPException, func:_get_repo(session: AsyncSession, repo_id: uuid.UUID, project_id: uuid.UUID, user_id: uuid.UUID) → GitRepository, call:session.execute, call:select(GitRepository) .where( GitRepository.id == repo_id, GitRepository.project_id == project_id, ) .options, call:selectinload, call:result.scalar_one_or_none, raise:HTTPException, func:_get_workspace(session: AsyncSession, workspace_id: uuid.UUID, repo_id: uuid.UUID) → Workspace, call:session.execute, call:select(Workspace).where, call:result.scalar_one_or_none, raise:HTTPException | dep: logging, uuid, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, sqlalchemy.orm, src.auth.dependencies, src.models, src.services.shared.workspace_manager
## arch
Modular router-based FastAPI architecture with domain-driven separation of concerns (files, git, instances, workspaces) using nested URL routing patterns and explicit dependency injection for cross-cutting workspace context.
Modular FastAPI router decomposition with domain-driven vertical slicing (files/git/instances/workspaces as separate modules), aggregated through __init__.py barrel exports, combining database persistence with external Git repository integration.
## tags
workspace, get, raise:httpexception, call:, at.isoformat, git, call:select, call:data.get
## symbols
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/auth
## role
Provides authentication and authorization infrastructure for the API using OIDC/OAuth2 with Authentik, session cookies, and FastAPI dependencies.
Provides authentication and authorization infrastructure for the API, including OIDC login, session management, and dependency injection for protected routes.
## parent
index: apps/api/src/.pi-map.index.md
map: apps/api/src/.pi-map.md
+7 -7
View File
@@ -4,15 +4,15 @@ dir: apps/api/src/auth
index: apps/api/src/auth/.pi-map.index.md
## role
Provides authentication and authorization infrastructure for the API using OIDC/OAuth2 with Authentik, session cookies, and FastAPI dependencies.
Provides authentication and authorization infrastructure for the API, including OIDC login, session management, and dependency injection for protected routes.
## files
- __init__.py | Re-exports authentication utility functions from submodules to provide a unified public API for the auth package | dep: src.auth.cookies, src.auth.oidc, src.auth.session
- cookies.py | Builds a dictionary of HTTP cookie options from application settings for secure cookie configuration. | exp: func:build_cookie_options(settings: Settings) → dict[str, str | bool | None] | dep: src.config, src.config.Settings
- dependencies.py | Provides FastAPI dependency functions for database sessions, user authentication, and project authorization. | exp: func:get_db_session(), call:SessionLocal, func:get_current_user_id(session_cookie) → uuid.UUID, call:Settings, call:decode_session_cookie, call:uuid.UUID, call:str, raise:HTTPException, func:get_current_user(session_cookie, db_session) → User, call:Settings, call:decode_session_cookie, call:uuid.UUID, call:str, call:db_session.get, raise:HTTPException, func:_get_user(session: AsyncSession, user_id: uuid.UUID) → User, call:session.get, raise:HTTPException, func:_get_owned_project(project_id: uuid.UUID, user_id: uuid.UUID, session: AsyncSession) → "Project", call:session.get, raise:HTTPException | dep: uuid, typing, fastapi, sqlalchemy.ext.asyncio, src.auth.session, src.config, src.database, src.models.project, src.models.user, sqlalchemy
- oidc.py | Implements OIDC/OAuth2 authentication flow with Authentik, including login URL construction, authorization code exchange for tokens, and user info retrieval. | exp: func:build_login_redirect_url(settings: Settings, redirect_uri: str, state: str) → str, call:urlencode, func:exchange_code_for_tokens(settings: Settings, code: str, redirect_uri: str, client: httpx.AsyncClient) → dict[str, str], call:client.post, call:response.raise_for_status, call:response.json, call:payload.get, func:fetch_user_info(settings: Settings, access_token: str, client: httpx.AsyncClient) → dict[str, Any], call:client.get, call:response.raise_for_status, call:response.json | dep: typing, urllib.parse, httpx, src.config
- session.py | Implements creation and verification of signed session cookies using HMAC-SHA256 in a JWS-like format. | exp: func:_base64url_encode(data: bytes) → str, call:base64.urlsafe_b64encode(data).rstrip(b"=").decode, func:_base64url_decode(data: str) → bytes, call:len, call:base64.urlsafe_b64decode, func:create_session_cookie(settings: Settings, user_id: str) → str, call:int, call:(datetime.now(timezone.utc) + timedelta(hours=settings.session_ttl_hours)).timestamp, call:datetime.now, call:timedelta, call:_base64url_encode, call:json.dumps({"alg": "HS256", "typ": "session"}).encode, call:json.dumps(payload).encode, call:hmac.new( settings.session_secret.encode(), message.encode(), hashlib.sha256, ).digest, call:settings.session_secret.encode, call:message.encode, func:decode_session_cookie(settings: Settings, cookie_value: str) → dict[str, Any], call:cookie_value.split, call:len, call:hmac.new( settings.session_secret.encode(), message.encode(), hashlib.sha256, ).digest, call:settings.session_secret.encode, call:message.encode, call:_base64url_encode, call:hmac.compare_digest, call:_base64url_decode, call:json.loads, call:payload.get, call:int, call:datetime.now(timezone.utc).timestamp, raise:ValueError | dep: hmac, hashlib, json, base64, datetime, typing, src.config, src.config.Settings
- __init__.py | Exposes authentication utility functions as a public API through module-level imports | dep: src.auth.cookies, src.auth.oidc, src.auth.session
- cookies.py | Builds a dictionary of HTTP cookie options from application settings | exp: func:build_cookie_options(settings: Settings) → dict[str, str | bool | None] | dep: src.config, src.config.Settings
- dependencies.py | Provides FastAPI dependency injection functions for database sessions, user authentication, and project ownership verification. | exp: func:get_db_session(), call:SessionLocal, func:get_current_user_id(session_cookie) → uuid.UUID, call:Settings, call:decode_session_cookie, call:uuid.UUID, call:str, raise:HTTPException, func:get_current_user(session_cookie, db_session) → User, call:Settings, call:decode_session_cookie, call:uuid.UUID, call:str, call:db_session.get, raise:HTTPException, func:_get_user(session: AsyncSession, user_id: uuid.UUID) → User, call:session.get, raise:HTTPException, func:_get_owned_project(project_id: uuid.UUID, user_id: uuid.UUID, session: AsyncSession) → "Project", call:session.get, raise:HTTPException | dep: uuid, typing, fastapi, sqlalchemy.ext.asyncio, src.auth.session, src.config, src.database, src.models.project, src.models.user, sqlalchemy
- oidc.py | Implements OIDC authentication flow with Authentik for login redirect URL construction, authorization code exchange, and user info retrieval. | exp: func:build_login_redirect_url(settings: Settings, redirect_uri: str, state: str) → str, call:urlencode, func:exchange_code_for_tokens(settings: Settings, code: str, redirect_uri: str, client: httpx.AsyncClient) → dict[str, str], call:client.post, call:response.raise_for_status, call:response.json, call:payload.get, func:fetch_user_info(settings: Settings, access_token: str, client: httpx.AsyncClient) → dict[str, Any], call:client.get, call:response.raise_for_status, call:response.json | dep: typing, urllib.parse, httpx, src.config
- session.py | Creates and verifies signed JWT-like session cookies with HMAC-SHA256 signatures and expiration checks. | exp: func:_base64url_encode(data: bytes) → str, call:base64.urlsafe_b64encode(data).rstrip(b"=").decode, func:_base64url_decode(data: str) → bytes, call:len, call:base64.urlsafe_b64decode, func:create_session_cookie(settings: Settings, user_id: str) → str, call:int, call:(datetime.now(timezone.utc) + timedelta(hours=settings.session_ttl_hours)).timestamp, call:datetime.now, call:timedelta, call:_base64url_encode, call:json.dumps({"alg": "HS256", "typ": "session"}).encode, call:json.dumps(payload).encode, call:hmac.new( settings.session_secret.encode(), message.encode(), hashlib.sha256, ).digest, call:settings.session_secret.encode, call:message.encode, func:decode_session_cookie(settings: Settings, cookie_value: str) → dict[str, Any], call:cookie_value.split, call:len, call:hmac.new( settings.session_secret.encode(), message.encode(), hashlib.sha256, ).digest, call:settings.session_secret.encode, call:message.encode, call:_base64url_encode, call:hmac.compare_digest, call:_base64url_decode, call:json.loads, call:payload.get, call:int, call:datetime.now(timezone.utc).timestamp, raise:ValueError | dep: hmac, hashlib, json, base64, datetime, typing, src.config, src.config.Settings
## arch
Modular security layer with separation of concerns: protocol handling (OIDC), transport security (cookies/sessions), framework integration (dependencies), and clean public API (re-exports).
Modular security layer using FastAPI dependency injection pattern, with separation of concerns across cookie handling, OIDC flow, session state, and reusable auth dependencies.
## tags
session, src, cookie, user, get, base64url, raise:httpexception, call:
## symbols
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/models
## role
Provides the SQLAlchemy ORM data models and database schema definitions for the API application.
Provides the foundational database model layer and unified public API for all SQLAlchemy ORM entities in the API application.
## parent
index: apps/api/src/.pi-map.index.md
map: apps/api/src/.pi-map.md
+3 -3
View File
@@ -4,12 +4,12 @@ dir: apps/api/src/models
index: apps/api/src/models/.pi-map.index.md
## role
Provides the SQLAlchemy ORM data models and database schema definitions for the API application.
Provides the foundational database model layer and unified public API for all SQLAlchemy ORM entities in the API application.
## files
- __init__.py | Re-exports model classes from submodules to provide a centralized public API for the src.models package | dep: src.models.base, src.models.config.config_profile, src.models.project.git_repository, src.models.project.project, src.models.project.workspace, src.models.system.health_check, src.models.system.instance_event, src.models.system.notification, src.models.system.terminal_session, src.models.tool.tool_definition_manifest, src.models.tool.tool_instance, src.models.tool.tool_type, src.models.user.ssh_key, src.models.user.user, src.models.user.user_config
- __init__.py | Re-exports database models from submodules to provide a unified public API for the models package | dep: src.models.base, src.models.config.config_profile, src.models.project.git_repository, src.models.project.project, src.models.project.workspace, src.models.system.health_check, src.models.system.instance_event, src.models.system.notification, src.models.system.terminal_session, src.models.tool.tool_definition_manifest, src.models.tool.tool_instance, src.models.tool.tool_type, src.models.user.ssh_key, src.models.user.user, src.models.user.user_config
- base.py | Defines SQLAlchemy base model and reusable mixins for UUID primary keys and automatic timestamp tracking in database models. | exp: class:Base, class:UUIDPrimaryKeyMixin, class:TimestampMixin | dep: uuid, datetime, sqlalchemy, sqlalchemy.orm
## arch
Layered repository pattern with declarative SQLAlchemy base, UUID/timestamp mixins for reusable model traits, and package-level facade pattern via __init__.py re-exports to centralize model access.
Implements a layered model architecture using SQLAlchemy declarative base with reusable mixins (UUID primary keys, timestamp tracking) and a facade pattern via `__init__.py` to centralize model imports.
## tags
models, src, base, project, system, user, mixin, tool
## symbols
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/models/config
## role
Provides SQLAlchemy ORM models for configuration profiles that manage environment variables, mounts, files, and git mounts with support for profile inheritance and user/project/tool associations.
Provides SQLAlchemy ORM models for configuration profiles that store deployment settings like environment variables, mounts, and runtime hints.
## parent
index: apps/api/src/models/.pi-map.index.md
map: apps/api/src/models/.pi-map.md
+4 -4
View File
@@ -4,14 +4,14 @@ dir: apps/api/src/models/config
index: apps/api/src/models/config/.pi-map.index.md
## role
Provides SQLAlchemy ORM models for configuration profiles that manage environment variables, mounts, files, and git mounts with support for profile inheritance and user/project/tool associations.
Provides SQLAlchemy ORM models for configuration profiles that store deployment settings like environment variables, mounts, and runtime hints.
## files
- __init__.py | Exports config model classes from a subpackage for simplified importing | dep: src.models.config.config_profile
- config_profile.py | Defines SQLAlchemy ORM models for configuration profiles and their includes, storing environment variables, runtime hints, mounts, files, and git mounts with user/project/tool associations and self-referential inclusion relationships. | exp: class:ConfigProfile, class:ConfigProfileInclude | dep: uuid, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.project, src.models, src.models.user, src.models (ToolType)
- config_profile.py | Defines SQLAlchemy ORM models for configuration profiles and their include relationships, storing deployment settings like environment variables, mounts, and runtime hints. | exp: class:ConfigProfile, class:ConfigProfileInclude | dep: uuid, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.project, src.models, src.models.user, src.models.ToolType
## arch
Uses SQLAlchemy ORM with declarative base pattern, implementing self-referential many-to-many relationships for profile inclusion, association tables for user/project/tool ownership, and polymorphic-like configuration through profile inheritance rather than class inheritance.
Package-level facade pattern with __init__.py exposing subpackage classes; domain model using SQLAlchemy ORM with relationship-based composition for profile includes.
## tags
config, src, models, profile, sqlalchemy, init, orm, mounts
config, models, src, profile, sqlalchemy, include, init, orm
## symbols
- ConfigProfile
- ConfigProfileInclude
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/models/project
## role
Defines the core domain data models for project management, representing Git repositories, projects, and workspaces as SQLAlchemy ORM entities with their relationships.
Provides SQLAlchemy ORM models for core project-related domain entities (GitRepository, Project, Workspace) with their relationships.
## parent
index: apps/api/src/models/.pi-map.index.md
map: apps/api/src/models/.pi-map.md
+7 -7
View File
@@ -4,16 +4,16 @@ dir: apps/api/src/models/project
index: apps/api/src/models/project/.pi-map.index.md
## role
Defines the core domain data models for project management, representing Git repositories, projects, and workspaces as SQLAlchemy ORM entities with their relationships.
Provides SQLAlchemy ORM models for core project-related domain entities (GitRepository, Project, Workspace) with their relationships.
## files
- __init__.py | Exports the three main project model classes (GitRepository, Project, Workspace) as the public API for the models.project package. | dep: src.models.project.git_repository, src.models.project.project, src.models.project.workspace
- git_repository.py | Defines a SQLAlchemy ORM model for Git repositories with relationships to projects, users, and SSH keys. | exp: class:GitRepository | dep: uuid, datetime, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.project, src.models, src.models.user, src.models.ssh_key
- project.py | Defines a SQLAlchemy ORM model for a Project entity with relationships to users, Git repositories, and SSH keys. | exp: class:Project | dep: uuid, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models, src.models.user, src.models.GitRepository, src.models.SSHKey, src.models.user.User
- workspace.py | Defines a SQLAlchemy ORM model for persistent writable Git repository clones associated with users. | exp: class:Workspace | dep: uuid, datetime, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models, src.models.user, src.models.GitRepository, src.models.user.User
- __init__.py | Exports the core project model classes (GitRepository, Project, Workspace) for the models package | dep: src.models.project.git_repository, src.models.project.project, src.models.project.workspace
- git_repository.py | Defines a SQLAlchemy ORM model for Git repositories with relationships to projects, users, and SSH keys. | exp: class:GitRepository | dep: uuid, datetime, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.project, src.models, src.models.user, src.models.SSHKey
- project.py | Defines a SQLAlchemy ORM model for projects with relationships to users, Git repositories, and SSH keys. | exp: class:Project | dep: uuid, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models, src.models.user, src.models.GitRepository, src.models.SSHKey, src.models.user.User
- workspace.py | Defines a SQLAlchemy ORM model for persistent writable Git repository clones associated with users | exp: class:Workspace | dep: uuid, datetime, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models, src.models.user, src.models.GitRepository
## arch
Standard SQLAlchemy ORM model layer with declarative base pattern, using __init__.py as a public API facade to expose the three main entity classes while keeping implementation details in separate modules.
Data access layer using SQLAlchemy ORM with declarative models, explicit table relationships (many-to-many and foreign keys), and package-level facade pattern via __init__.py exports.
## tags
models, src, project, sqlalchemy, git, user, workspace, orm
models, src, project, sqlalchemy, git, workspace, orm, repository
## symbols
- GitRepository
- Project
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/models/system
## role
Provides database persistence models for system-level operational concerns including health monitoring, audit logging, user notifications, and terminal session management.
Provides system-level SQLAlchemy ORM models for operational concerns including health monitoring, audit logging, notifications, and terminal session management.
## parent
index: apps/api/src/models/.pi-map.index.md
map: apps/api/src/models/.pi-map.md
+6 -6
View File
@@ -4,17 +4,17 @@ dir: apps/api/src/models/system
index: apps/api/src/models/system/.pi-map.index.md
## role
Provides database persistence models for system-level operational concerns including health monitoring, audit logging, user notifications, and terminal session management.
Provides system-level SQLAlchemy ORM models for operational concerns including health monitoring, audit logging, notifications, and terminal session management.
## files
- __init__.py | Exports system-related model classes from a package for convenient importing. | dep: src.models.system.health_check, src.models.system.instance_event, src.models.system.notification, src.models.system.terminal_session
- __init__.py | Package initialization file that exports system-related model classes for the models.system module | dep: src.models.system.health_check, src.models.system.instance_event, src.models.system.notification, src.models.system.terminal_session
- health_check.py | Defines a SQLAlchemy ORM model for storing health check snapshots of tool instances with various status and probe fields. | exp: class:HealthCheck | dep: uuid, datetime, sqlalchemy, sqlalchemy.orm, src.models.base
- instance_event.py | Defines a SQLAlchemy ORM model for auditing instance lifecycle events with metadata, status tracking, and user attribution. | exp: class:InstanceEvent | dep: uuid, datetime, typing, sqlalchemy, sqlalchemy.orm, src.models.base
- notification.py | Defines a SQLAlchemy ORM model for storing user notifications with metadata, read/dismissed tracking, and polymorphic source references. | exp: class:Notification | dep: datetime, typing, uuid, sqlalchemy, sqlalchemy.orm, sqlalchemy.sql, src.models.base
- instance_event.py | Defines a SQLAlchemy model for auditing instance lifecycle events with metadata, status tracking, and user attribution. | exp: class:InstanceEvent | dep: uuid, datetime, typing, sqlalchemy, sqlalchemy.orm, src.models.base
- notification.py | Defines a SQLAlchemy ORM model for storing user notifications with support for categorization, severity levels, read/dismissed tracking, and polymorphic source references. | exp: class:Notification | dep: datetime, typing, uuid, sqlalchemy, sqlalchemy.orm, sqlalchemy.sql, src.models.base
- terminal_session.py | Defines a SQLAlchemy database model for storing terminal session metadata with lifecycle tracking. | exp: class:TerminalSessionModel | dep: uuid, datetime, sqlalchemy, sqlalchemy.orm, src.models.base
## arch
Uses SQLAlchemy ORM declarative models with consistent patterns including timestamp tracking, JSON metadata columns, enum-based status fields, and polymorphic relationships for extensible source attribution.
Standard SQLAlchemy declarative model pattern with polymorphic associations (notification sources), lifecycle state tracking, and timestamped audit fields across all models.
## tags
sqlalchemy, src, models, model, orm, system, notification, health
sqlalchemy, models, src, model, system, orm, notification, health
## symbols
- HealthCheck
- InstanceEvent
+6 -6
View File
@@ -6,14 +6,14 @@ index: apps/api/src/models/tool/.pi-map.index.md
## role
Provides SQLAlchemy ORM models for managing containerized tool definitions, types, and deployed instances in the API.
## files
- __init__.py | Exports the public API for the tool models module by re-exporting three key classes. | dep: src.models.tool.tool_definition_manifest, src.models.tool.tool_instance, src.models.tool.tool_type
- tool_definition_manifest.py | Defines a SQLAlchemy ORM model for storing tool definition manifests that compile to Dockerfiles and Compose files, supporting both base definitions and tool-specific definitions with inheritance. | exp: class:ToolDefinitionManifest | dep: uuid, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.user
- tool_instance.py | Defines a SQLAlchemy ORM model for tool instances that represent deployed tools with container metadata, status tracking, and relationships to users, projects, workspaces, and other entities. | exp: class:ToolInstance | dep: uuid, datetime, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models, src.models.project, src.models.user, src.models (ConfigProfile, GitRepository, Project, ToolType, User, Workspace)
- tool_type.py | Defines a SQLAlchemy ORM model for tool types that specify configuration templates and metadata for deployable tools in a containerized environment. | exp: class:ToolType | dep: uuid, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.tool.tool_definition_manifest, src.models.user
- __init__.py | Package initialization file that exports the public API for the tool models module. | dep: src.models.tool.tool_definition_manifest, src.models.tool.tool_instance, src.models.tool.tool_type
- tool_definition_manifest.py | Defines a SQLAlchemy model for tool definition manifests that can represent either base Docker images or tool definitions that inherit from bases, storing manifest JSON and cached Dockerfile/Compose outputs. | exp: class:ToolDefinitionManifest | dep: uuid, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.user
- tool_instance.py | Defines a SQLAlchemy ORM model representing a deployed tool instance with container/runtime metadata and relationships to users, projects, and workspaces. | exp: class:ToolInstance | dep: uuid, datetime, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models, src.models.project, src.models.user, src.models (ConfigProfile, GitRepository, Project, ToolType, User, Workspace)
- tool_type.py | Defines a SQLAlchemy ORM model for tool types that specify metadata, configuration, and deployment templates for containerized tools. | exp: class:ToolType | dep: uuid, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.tool.tool_definition_manifest, src.models.user
## arch
Domain-driven data models using SQLAlchemy ORM with declarative base pattern, entity relationships, and inheritance support for tool manifest definitions.
Uses SQLAlchemy ORM with declarative models, inheritance patterns (base vs. derived tool definitions), and relational associations linking tools to users, projects, and workspaces.
## tags
tool, models, src, sqlalchemy, orm, definition, base, manifest
tool, models, src, sqlalchemy, definition, manifest, orm, instance
## symbols
- ToolDefinitionManifest
- ToolInstance
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/models/user
## role
Provides SQLAlchemy ORM data models for user authentication, SSH key storage, and per-user configuration management.
Database models package defining user-related entities including users, SSH keys, and user configuration with their relationships.
## parent
index: apps/api/src/models/.pi-map.index.md
map: apps/api/src/models/.pi-map.md
+6 -6
View File
@@ -4,16 +4,16 @@ dir: apps/api/src/models/user
index: apps/api/src/models/user/.pi-map.index.md
## role
Provides SQLAlchemy ORM data models for user authentication, SSH key storage, and per-user configuration management.
Database models package defining user-related entities including users, SSH keys, and user configuration with their relationships.
## files
- __init__.py | Exports the user-related model classes (SSHKey, User, UserConfig) from a package for convenient importing. | dep: src.models.user.ssh_key, src.models.user.user, src.models.user.user_config
- ssh_key.py | Defines an SSHKey SQLAlchemy ORM model for storing encrypted SSH key pairs with user and optional project associations. | exp: class:SSHKey | dep: uuid, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.project, src.models.user
- __init__.py | Exports user-related model classes from a package for clean external imports. | dep: src.models.user.ssh_key, src.models.user.user, src.models.user.user_config
- ssh_key.py | Defines an SSHKey database model for storing encrypted SSH key pairs with associations to users and optional projects. | exp: class:SSHKey | dep: uuid, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.project, src.models.user
- user.py | Defines a SQLAlchemy ORM model for a User entity with authentication fields and relationships to projects, SSH keys, and user configuration. | exp: class:User | dep: typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.project, src.models, src.models.SSHKey, src.models.UserConfig
- user_config.py | Defines a SQLAlchemy model for storing per-user JSON configuration with typed property accessors for default profile IDs. | exp: class:UserConfig | dep: uuid, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.user
- user_config.py | Defines a SQLAlchemy model for storing per-user JSON configuration data with typed property accessors for profile IDs. | exp: class:UserConfig | dep: uuid, typing, sqlalchemy, sqlalchemy.orm, src.models.base, src.models.user
## arch
Classic SQLAlchemy ORM model package pattern with declarative models, explicit table relationships, and a package-level __init__.py facade for clean imports.
SQLAlchemy ORM with declarative models, one-to-many relationships (User→SSHKey, User→Project, User→UserConfig), encrypted field storage for SSH keys, and JSON-typed configuration with property accessors for schema flexibility.
## tags
user, src, models, sqlalchemy, sshkey, orm, model, ssh
user, src, models, sqlalchemy, model, sshkey, ssh, orm
## symbols
- SSHKey
- User
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/schemas
## role
Defines Pydantic schemas for data validation and serialization in the API layer.
Provides data validation schemas for the API application
## parent
index: apps/api/src/.pi-map.index.md
map: apps/api/src/.pi-map.md
+4 -4
View File
@@ -4,13 +4,13 @@ dir: apps/api/src/schemas
index: apps/api/src/schemas/.pi-map.index.md
## role
Defines Pydantic schemas for data validation and serialization in the API layer.
Provides data validation schemas for the API application
## files
- __init__.py | Empty file with no functionality
- __init__.py | Swaps two tmux panes between windows, preserving active pane state and layout | dep: tmux
## arch
Standard Python package structure using __init__.py to mark the directory as an importable package, likely intended for request/response models following FastAPI/Pydantic patterns.
Package initialization with modular schema definitions using Pydantic or similar validation framework
## tags
init, empty, functionality
tmux, init, swaps, two, panes, windows, preserving, active
## symbols
-
## workflows
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/schemas/config
## role
Defines Pydantic validation schemas for configuration profile API request/response models with strict input validation.
Provides Pydantic schemas for configuration profile API operations with validated request/response models.
## parent
index: apps/api/src/schemas/.pi-map.index.md
map: apps/api/src/schemas/.pi-map.md
+5 -5
View File
@@ -4,14 +4,14 @@ dir: apps/api/src/schemas/config
index: apps/api/src/schemas/config/.pi-map.index.md
## role
Defines Pydantic validation schemas for configuration profile API request/response models with strict input validation.
Provides Pydantic schemas for configuration profile API operations with validated request/response models.
## files
- __init__.py | Re-exports Pydantic schemas for configuration profile operations from a submodule to provide a clean public API. | dep: src.schemas.config.config_profile
- config_profile.py | Defines Pydantic request/response schemas for config profile API operations with validation for mounts, git URLs, UUIDs, and file paths. | exp: class:GitMountMapping, class:GitMountItem, class:MountItem, class:ConfigProfileCreate, class:ConfigProfileUpdate, class:ConfigProfileIncludeUpdate, class:ConfigProfileResponse, class:DefaultProfilesUpdate, class:ValidateGitUrlRequest, class:ValidateGitUrlResponse, func:_validate_uuid(v: str | None) → str | None, call:uuid.UUID, raise:ValueError | dep: uuid, pydantic, src.api.shared_validators
- __init__.py | Re-exports config profile schema classes from a submodule to provide a unified public interface for the config schemas module. | dep: src.schemas.config.config_profile
- config_profile.py | Defines Pydantic request/response schemas for configuration profile API operations with comprehensive input validation. | exp: class:GitMountMapping, class:GitMountItem, class:MountItem, class:ConfigProfileCreate, class:ConfigProfileUpdate, class:ConfigProfileIncludeUpdate, class:ConfigProfileResponse, class:DefaultProfilesUpdate, class:ValidateGitUrlRequest, class:ValidateGitUrlResponse, func:_validate_uuid(v: str | None) → str | None, call:uuid.UUID, raise:ValueError | dep: uuid, pydantic, src.api.shared_validators
## arch
Standard Python package pattern using `__init__.py` re-exports to expose a clean public API from internal modules, with Pydantic-based schema-per-resource organization.
Layered schema module using submodule organization with clean public interface via __init__.py re-exports, following Pydantic-based validation pattern for API contract definitions.
## tags
profile, config, git, mount, update, validate, response, item
config, profile, git, mount, update, validate, response, item
## symbols
- GitMountMapping
- GitMountItem
@@ -2,7 +2,7 @@
dir: apps/api/src/schemas/project
## role
Defines Pydantic data validation schemas for project-related API endpoints, serving as the contract layer between HTTP requests/responses and internal business logic.
Provides Pydantic data validation schemas for project-related API endpoints, serving as the contract layer between API requests/responses and internal business logic.
## parent
index: apps/api/src/schemas/.pi-map.index.md
map: apps/api/src/schemas/.pi-map.md
+6 -6
View File
@@ -4,16 +4,16 @@ dir: apps/api/src/schemas/project
index: apps/api/src/schemas/project/.pi-map.index.md
## role
Defines Pydantic data validation schemas for project-related API endpoints, serving as the contract layer between HTTP requests/responses and internal business logic.
Provides Pydantic data validation schemas for project-related API endpoints, serving as the contract layer between API requests/responses and internal business logic.
## files
- __init__.py | Re-exports Pydantic schema classes from submodules to provide a unified public API for the project schemas module | dep: src.schemas.project.git_repository, src.schemas.project.project, src.schemas.project.ssh_key
- __init__.py | Re-exports Pydantic schema classes from submodules to provide a unified public API for project-related data models. | dep: src.schemas.project.git_repository, src.schemas.project.project, src.schemas.project.ssh_key
- git_repository.py | Defines Pydantic request/response schemas for Git repository operations in an API. | exp: class:GitRepositoryCreate, class:URLParseRequest, class:URLParseResponse, class:GitRepositoryResponse, class:UpdateSSHKeyRequest, class:FileListResponse, class:FileContentResponse, class:BranchesResponse, class:FileUpdateRequest, class:FileUpdateResponse, class:StatusResponse, class:BranchCreateRequest, class:CheckoutRequest, class:CommitRequest, class:CommitResponse, class:FetchResponse, class:PullResponse, class:PushResponse, class:MergeRequest, class:MergeResponse | dep: uuid, datetime, pydantic
- project.py | Defines Pydantic request/response schemas for project-related API operations. | exp: class:ProjectCreate, class:ProjectUpdate, class:ProjectResponse, class:SetDefaultSSHKeyRequest | dep: uuid, pydantic
- ssh_key.py | Defines Pydantic schemas for SSH key creation, response, signing, and signature verification in an API. | exp: class:SSHKeyCreate, class:SSHKeyResponse, class:SignPayloadRequest, class:SignatureResponse, class:VerifySignatureRequest, class:VerifySignatureResponse | dep: uuid, datetime, pydantic
- project.py | Defines Pydantic request/response schemas for project-related API operations including creation, updates, responses, and default SSH key assignment. | exp: class:ProjectCreate, class:ProjectUpdate, class:ProjectResponse, class:SetDefaultSSHKeyRequest | dep: uuid, pydantic
- ssh_key.py | Defines Pydantic request/response schemas for SSH key management and signature operations in an API. | exp: class:SSHKeyCreate, class:SSHKeyResponse, class:SignPayloadRequest, class:SignatureResponse, class:VerifySignatureRequest, class:VerifySignatureResponse | dep: uuid, datetime, pydantic
## arch
Modular schema decomposition with submodule-per-domain pattern (project, git_repository, ssh_key) aggregated through __init__.py barrel exports, using Pydantic models for declarative validation and serialization.
Modular schema-per-domain pattern with clean separation of concerns (git repositories, projects, SSH keys) and centralized public API via `__init__.py` re-exports, following standard Pydantic model hierarchy with explicit request/response bifurcation.
## tags
response, request, project, create, update, sshkey, pydantic, schemas
response, request, project, create, update, sshkey, pydantic, git
## symbols
- GitRepositoryCreate
- URLParseRequest
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/schemas/system
## role
Provides Pydantic schema definitions for system health monitoring API responses.
Provides Pydantic data models for system health monitoring API responses, enabling standardized health check serialization across the API.
## parent
index: apps/api/src/schemas/.pi-map.index.md
map: apps/api/src/schemas/.pi-map.md
+5 -5
View File
@@ -4,14 +4,14 @@ dir: apps/api/src/schemas/system
index: apps/api/src/schemas/system/.pi-map.index.md
## role
Provides Pydantic schema definitions for system health monitoring API responses.
Provides Pydantic data models for system health monitoring API responses, enabling standardized health check serialization across the API.
## files
- __init__.py | Re-exports health check schema classes from a submodule to provide a unified interface for the system schemas module. | dep: src.schemas.system.health
- health.py | Defines Pydantic data models for health check API responses including database, disk, and overall system health status. | exp: class:DatabaseHealth, class:DiskHealth, class:HealthChecks, class:HealthResponse, class:DatabaseHealthResponse | dep: pydantic
- __init__.py | Re-exports health-related schema classes from a submodule to provide a unified interface for the system schemas module. | dep: src.schemas.system.health
- health.py | Defines Pydantic data models for health check API responses including database, disk, and overall system health metrics. | exp: class:DatabaseHealth, class:DiskHealth, class:HealthChecks, class:HealthResponse, class:DatabaseHealthResponse | dep: pydantic
## arch
Simple modular schema layer with submodule organization and re-export pattern for clean API surface.
Simple submodule-based schema organization with explicit re-exports in __init__.py following a flat namespace pattern for cleaner imports.
## tags
health, database, response, system, disk, check, schemas, init
health, database, response, system, disk, schemas, init, pydantic
## symbols
- DatabaseHealth
- DiskHealth
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/schemas/tool
## role
Defines Pydantic data validation schemas for tool instance and tool type API operations in the API layer.
Provides Pydantic data validation schemas for tool-related API request/response models.
## parent
index: apps/api/src/schemas/.pi-map.index.md
map: apps/api/src/schemas/.pi-map.md
+4 -4
View File
@@ -4,13 +4,13 @@ dir: apps/api/src/schemas/tool
index: apps/api/src/schemas/tool/.pi-map.index.md
## role
Defines Pydantic data validation schemas for tool instance and tool type API operations in the API layer.
Provides Pydantic data validation schemas for tool-related API request/response models.
## files
- __init__.py | Package initialization file that exposes tool-related schema classes for import convenience. | dep: src.schemas.tool.tool_instance, src.schemas.tool.tool_type
- __init__.py | Re-exports tool-related Pydantic schemas from submodules to provide a unified public interface for the schemas.tool package. | dep: src.schemas.tool.tool_instance, src.schemas.tool.tool_type
- tool_instance.py | Defines Pydantic request/response schemas for tool instance lifecycle operations (create, create-on-workspace, start). | exp: class:CreateInstanceRequest, class:CreateWorkspaceInstanceRequest, class:StartInstanceRequest | dep: pydantic
- tool_type.py | Defines Pydantic request/response schemas for tool type CRUD operations with conditional validation logic based on definition type (compose/dockerfile/manifest). | exp: class:ToolTypeCreate, class:ToolTypeUpdate, class:ToolTypeResponse, class:ToolTypeValidateRequest | dep: uuid, datetime, pydantic, src.api.tool.tool_types_validation
- tool_type.py | Defines Pydantic request/response schemas for tool type CRUD operations with conditional validation logic based on definition type | exp: class:ToolTypeCreate, class:ToolTypeUpdate, class:ToolTypeResponse, class:ToolTypeValidateRequest | dep: uuid, datetime, pydantic, src.api.tool.tool_types_validation
## arch
Standard Pydantic schema package pattern with type-specific conditional validation using discriminated unions or field validators based on definition type.
Modular schema organization with submodule-per-entity pattern, re-exported through __init__.py for clean imports; uses conditional Pydantic validators for polymorphic definition type handling.
## tags
tool, type, request, instance, create, schemas, pydantic, response
## symbols
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/schemas/user
## role
Provides Pydantic data validation schemas for user-related API requests and responses.
Defines Pydantic schemas for user-related request/response data serialization and validation in the API layer.
## parent
index: apps/api/src/schemas/.pi-map.index.md
map: apps/api/src/schemas/.pi-map.md
+6 -6
View File
@@ -4,15 +4,15 @@ dir: apps/api/src/schemas/user
index: apps/api/src/schemas/user/.pi-map.index.md
## role
Provides Pydantic data validation schemas for user-related API requests and responses.
Defines Pydantic schemas for user-related request/response data serialization and validation in the API layer.
## files
- __init__.py | Re-exports user-related Pydantic schemas from submodules to provide a unified public API for the user schemas package. | dep: src.schemas.user.user, src.schemas.user.user_config
- user.py | Defines Pydantic response and update schemas for user profile data | exp: class:UserProfileResponse, class:UserProfileUpdate | dep: uuid, pydantic
- user_config.py | Defines Pydantic models for user configuration data transfer objects (response and update schemas). | exp: class:UserConfigResponse, class:UserConfigUpdate | dep: pydantic
- __init__.py | Exports user-related Pydantic schemas from submodules to provide a clean public API for the user schemas package. | dep: src.schemas.user.user, src.schemas.user.user_config
- user.py | Defines Pydantic request/response schemas for user profile data in an API | exp: class:UserProfileResponse, class:UserProfileUpdate | dep: uuid, pydantic
- user_config.py | Defines Pydantic request/response schemas for user configuration data in an API. | exp: class:UserConfigResponse, class:UserConfigUpdate | dep: pydantic
## arch
Modular schema organization with submodule separation of concerns and unified package-level re-exports for clean imports.
Modular package pattern with clean public API via __init__.py exports, separating domain concerns (user profile vs. user configuration) into distinct schema modules.
## tags
user, schemas, response, update, config, pydantic, profile, src
user, schemas, response, config, pydantic, profile, update, api
## symbols
- UserProfileResponse
- UserProfileUpdate
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/scripts
## role
Provides utility scripts for administrative and setup tasks for the API application, specifically database seeding.
Provides utility scripts for database initialization and maintenance tasks for the API.
## parent
index: apps/api/src/.pi-map.index.md
map: apps/api/src/.pi-map.md
+5 -5
View File
@@ -4,14 +4,14 @@ dir: apps/api/src/scripts
index: apps/api/src/scripts/.pi-map.index.md
## role
Provides utility scripts for administrative and setup tasks for the API application, specifically database seeding.
Provides utility scripts for database initialization and maintenance tasks for the API.
## files
- __init__.py | Marks the directory as a Python package and provides a docstring describing it as utility scripts for the API package.
- seed.py | Seeds a development user into the database using SQLAlchemy async operations, with idempotency check to avoid duplicates. | exp: func:build_seed_user() → Mapping[str, str | None], func:seed_database(session: AsyncSession) → User, call:build_seed_user, call:session.scalar, call:select(User).where, call:User, call:session.add, call:session.commit, call:session.refresh, func:run() → None, call:SessionLocal, call:seed_database, call:print, call:str, func:main() → None, call:asyncio.run, call:run | dep: collections.abc, sqlalchemy, sqlalchemy.ext.asyncio, src.database, src.models.user, asyncio
- __init__.py | Marks the directory as a Python package and provides a module docstring for API utility scripts.
- seed.py | Seeds a development user into the database, creating it if it doesn't already exist based on email. | exp: func:build_seed_user() → Mapping[str, str | None], func:seed_database(session: AsyncSession) → User, call:build_seed_user, call:session.scalar, call:select(User).where, call:User, call:session.add, call:session.commit, call:session.refresh, func:run() → None, call:SessionLocal, call:seed_database, call:print, call:str, func:main() → None, call:asyncio.run, call:run | dep: collections.abc, sqlalchemy, sqlalchemy.ext.asyncio, src.database, src.models.user, asyncio
## arch
Simple procedural script architecture with async SQLAlchemy database operations and idempotent initialization patterns.
Simple procedural script pattern with direct database access via SQLAlchemy models, no service layer abstraction.
## tags
seed, user, database, sqlalchemy, package, init, call:build, call:session.scalar
seed, user, database, init, call:build, call:session.scalar, call:select, call:user
## symbols
- build_seed_user
- seed_database
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/seeds
## role
Provides database seeding utilities for initializing and synchronizing built-in data records in the API application.
Provides database seeding utilities to populate initial built-in tool type configurations for the API application.
## parent
index: apps/api/src/.pi-map.index.md
map: apps/api/src/.pi-map.md
+4 -4
View File
@@ -4,12 +4,12 @@ dir: apps/api/src/seeds
index: apps/api/src/seeds/.pi-map.index.md
## role
Provides database seeding utilities for initializing and synchronizing built-in data records in the API application.
Provides database seeding utilities to populate initial built-in tool type configurations for the API application.
## files
- __init__.py | Marks the directory as a Python package for database seeding utilities.
- builtin_tool_types.py | Seeds predefined built-in tool types (code-server, jupyter-notebook, opencode) into a database with upsert logic, creating them if missing or updating existing ones to match code changes. | exp: func:_table_exists(session, table_name: str) → bool, call:session.execute, call:text, call:result.scalar, func:seed_builtin_tool_types(), call:SessionLocal, call:_table_exists, call:logger.warning, call:session.scalar, call:select(ToolType).where, call:ToolType, call:tool_data.get, call:session.add, call:logger.info, call:session.commit | dep: logging, sqlalchemy, src.database, src.models
- __init__.py | Marks directory as Python package for database seeding utilities
- builtin_tool_types.py | Seeds built-in tool types (code-server, jupyter-notebook, opencode) into the database with Docker Compose templates, creating or updating records as needed. | exp: func:_table_exists(session, table_name: str) → bool, call:session.execute, call:text, call:result.scalar, func:seed_builtin_tool_types(), call:SessionLocal, call:_table_exists, call:logger.warning, call:session.scalar, call:select(ToolType).where, call:ToolType, call:tool_data.get, call:session.add, call:logger.info, call:session.commit | dep: logging, sqlalchemy, src.database, src.models
## arch
Simple imperative seeding scripts with upsert pattern for idempotent data initialization, using direct database operations without abstraction layers.
Simple procedural seeding pattern with idempotent upsert operations, directly importing and executing database model creation logic with embedded Docker Compose template definitions.
## tags
tool, types, table, exists, builtin, call:tool, database, init
## symbols
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/services
## role
Service layer package for the API application, intended to contain business logic implementations.
Provides utility services for the API application, including tmux window management functionality.
## parent
index: apps/api/src/.pi-map.index.md
map: apps/api/src/.pi-map.md
+4 -4
View File
@@ -4,13 +4,13 @@ dir: apps/api/src/services
index: apps/api/src/services/.pi-map.index.md
## role
Service layer package for the API application, intended to contain business logic implementations.
Provides utility services for the API application, including tmux window management functionality.
## files
- __init__.py | Empty file with no functionality
- __init__.py | Swaps two tmux panes between windows, preserving active pane state and layout | dep: tmux
## arch
Standard Python package structure with an empty initializer, awaiting service module implementations following a layered architecture pattern.
Simple module-based architecture with service functions organized in a flat directory structure.
## tags
init, empty, functionality
tmux, init, swaps, two, panes, windows, preserving, active
## symbols
-
## workflows
@@ -2,7 +2,7 @@
dir: apps/api/src/services/config
## role
Provides configuration profile management with recursive resolution, validation, and access control for container environment setup.
Provides configuration profile resolution, validation, and CRUD operations with recursive includes and cycle detection for the API layer.
## parent
index: apps/api/src/services/.pi-map.index.md
map: apps/api/src/services/.pi-map.md
+6 -6
View File
@@ -4,14 +4,14 @@ dir: apps/api/src/services/config
index: apps/api/src/services/config/.pi-map.index.md
## role
Provides configuration profile management with recursive resolution, validation, and access control for container environment setup.
Provides configuration profile resolution, validation, and CRUD operations with recursive includes and cycle detection for the API layer.
## files
- __init__.py | Re-exports configuration profile resolution components from a subpackage to provide a unified public API. | dep: src.services.config.config_profile_resolver
- config_profile_resolver.py | Resolves configuration profiles recursively with ordered includes, deterministic merge rules, and cycle protection for container environment setup. | exp: class:ConfigProfileCycleError, class:ConfigProfileNotFoundError, class:ResolvedMount, class:ResolvedProfile, func:_detect_cycle(profile_id: uuid.UUID, visited: set[uuid.UUID], path: list[uuid.UUID]) → bool, func:_merge_env_vars(base: dict[str, str], overlay: dict[str, str], overrides: dict[str, str], source_name: str) → dict[str, str], call:dict, call:overlay.items, func:_merge_runtime_hints(base: dict[str, Any], overlay: dict[str, Any], overrides: dict[str, str], source_name: str) → dict[str, Any], call:dict, call:overlay.items, func:_merge_files(base: dict[str, str], overlay: dict[str, str], overrides: dict[str, str], source_name: str) → dict[str, str], call:dict, call:overlay.items, func:_merge_mounts(base: dict[str, ResolvedMount], overlay: list[dict[str, Any]], overrides: dict[str, str], source_name: str) → dict[str, ResolvedMount], call:dict, call:mount_data.get, call:files.items, call:ResolvedMount, func:_merge_git_mounts(base: list[dict[str, Any]], overlay: list[dict[str, Any]], source_name: str) → list[dict[str, Any]], call:list, call:enumerate, call:_normalize_git_mount_entry, call:dict, call:m.get, call:mount.get, call:existing.get, call:existing["mappings"].append, call:existing_sources.add, call:len, call:result.append, func:_normalize_git_mount_entry(entry: dict[str, Any]) → dict[str, Any], call:dict, call:entry.get, call:entry.pop, func:_resolve_profile_recursive(session: AsyncSession, profile_id: uuid.UUID, visited: set[uuid.UUID], path: list[uuid.UUID]) → ResolvedProfile, call:_detect_cycle, call:" -> ".join, call:str, call:session.get, call:ResolvedProfile, call:select(ConfigProfileInclude) .where(ConfigProfileInclude.profile_id == profile_id) .order_by, call:session.execute, call:include_result.scalars().all, call:_resolve_profile_recursive, call:result.included_profiles.append, call:_merge_env_vars, call:_merge_runtime_hints, call:_merge_files, call:_merge_mounts, call:included.mounts.values, call:_merge_git_mounts, raise:ConfigProfileCycleError, raise:ConfigProfileNotFoundError, func:resolve_profile(session: AsyncSession, profile_id: uuid.UUID) → ResolvedProfile, call:_resolve_profile_recursive, call:set, func:check_include_cycle(session: AsyncSession, profile_id: uuid.UUID, new_include_id) → list[uuid.UUID] | None, call:select(ConfigProfileInclude) .where(ConfigProfileInclude.profile_id == current_id) .order_by, call:session.execute, call:include_result.scalars().all, call:_check_from, call:set, call:len, func:_check_from(current_id: uuid.UUID, target_id: uuid.UUID, visited: set[uuid.UUID], path: list[uuid.UUID]) → list[uuid.UUID] | None, call:select(ConfigProfileInclude) .where(ConfigProfileInclude.profile_id == current_id) .order_by, call:session.execute, call:include_result.scalars().all, call:_check_from, func:apply_resolved_profile(instance_dir: str, resolved: ResolvedProfile, home_dir) → tuple[dict[str, str], dict[str, str], list[dict], dict[str, Any]], call:Path, call:dict, call:files.items, call:full_path.resolve().relative_to, call:instance_path.resolve, call:logger.warning, call:full_path.parent.mkdir, call:full_path.write_text, call:resolved.mounts.values, call:os.path.normpath, call:expand_container_path, call:expanded_target.lstrip("/").replace, call:mount_dir.mkdir, call:mount.files.items, call:mount_dir.resolve, call:volume_mounts.append, call:str, func:expand_container_path(path: str, home_dir: str) → str, call:path.startswith, call:os.path.join, func:resolved_profile_to_dict(resolved: ResolvedProfile) → dict[str, Any], call:str, call:resolved.mounts.values | dep: logging, os, uuid, dataclasses, typing, sqlalchemy, sqlalchemy.ext.asyncio, src.models, pathlib
- crud_service.py | Provides CRUD operations for configuration profiles including validation, access control, size limits, and include cycle detection. | exp: func:calculate_profile_size(data: dict) → int, call:data.get("env_vars", {}).items, call:len, call:key.encode, call:str(value).encode, call:data.get("runtime_hints", {}).items, call:str(mount.get("target", "")).encode, call:str(mount.get("mode", "")).encode, call:mount.get("files", {}).items, call:path.encode, call:content.encode, call:data.get("files", {}).items, func:get_profile_with_includes(session: AsyncSession, profile_id: uuid.UUID) → ConfigProfile | None, call:session.execute, call:select(ConfigProfile) .where(ConfigProfile.id == profile_id) .options, call:selectinload, call:result.scalar_one_or_none, func:check_access(session: AsyncSession, user_id: uuid.UUID, project_id, tool_type_id) → None, call:session.get, raise:HTTPException, func:validate_git_mounts(session: AsyncSession, user_id: uuid.UUID, git_mounts: list[Any], project_id) → None, call:mount.get, call:remote_url.startswith, raise:HTTPException, func:profile_to_response(profile: ConfigProfile, includes) → dict, call:str, call:profile.created_at.isoformat, call:profile.updated_at.isoformat, func:get_or_create_user_config(session: AsyncSession, user_id: uuid.UUID) → UserConfig, call:session.execute, call:select(UserConfig).where, call:result.scalar_one_or_none, call:UserConfig, call:session.add, func:validate_default_profiles(session: AsyncSession, user_id: uuid.UUID, default_profiles: dict[str, str]) → None, call:default_profiles.items, call:uuid.UUID, call:session.get, raise:HTTPException, func:create_profile(session: AsyncSession, user_id: uuid.UUID, data: Any) → ConfigProfile, call:session.execute, call:select(ConfigProfile) .where( ConfigProfile.user_id == user_id, ConfigProfile.name == data.name, ) .options, call:selectinload, call:existing.scalar_one_or_none, call:uuid.UUID, call:check_access, call:m.model_dump, call:hasattr, call:validate_git_mounts, call:calculate_profile_size, call:data.model_dump, call:ConfigProfile, call:session.add, call:session.commit, call:select(ConfigProfile) .where(ConfigProfile.id == profile.id) .options, call:result.scalar_one, raise:HTTPException, func:update_profile(session: AsyncSession, profile: ConfigProfile, data: Any) → ConfigProfile, call:data.model_dump, call:session.execute, call:select(ConfigProfile).where, call:existing.scalar_one_or_none, call:uuid.UUID, call:check_access, call:m.model_dump, call:hasattr, call:validate_git_mounts, call:profile_to_response, call:calculate_profile_size, call:update_data.items, call:isinstance, call:setattr, call:session.commit, call:select(ConfigProfile) .where(ConfigProfile.id == profile.id) .options, call:selectinload, call:result.scalar_one, raise:HTTPException, func:update_includes(session: AsyncSession, profile: ConfigProfile, included_ids: list[uuid.UUID], user_id: uuid.UUID) → ConfigProfile, call:session.get, call:check_include_cycle, call:" -> ".join, call:str, call:session.execute, call:select(ConfigProfileInclude).where, call:result.scalars().all, call:session.delete, call:session.flush, call:enumerate, call:ConfigProfileInclude, call:session.add, call:session.commit, call:select(ConfigProfile).where, call:result.scalar_one, raise:HTTPException | dep: uuid, typing, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, sqlalchemy.orm, src.models, src.models.project, src.services.config.config_profile_resolver
- resolver_service.py | Resolves default configuration profiles for users/projects/tools and validates Git URLs with SSH key support. | exp: func:resolve_default_profile(session: AsyncSession, user_id: uuid.UUID, project_id: uuid.UUID, tool_type_id: uuid.UUID) → dict, call:select(ConfigProfile) .where(ConfigProfile.user_id == user_id) .where( (ConfigProfile.project_id.is_(None) & ConfigProfile.tool_type_id.is_(None)) | (ConfigProfile.project_id == project_id) | (ConfigProfile.tool_type_id == tool_type_id) | ( (ConfigProfile.project_id == project_id) & (ConfigProfile.tool_type_id == tool_type_id) ) ) .order_by, call:ConfigProfile.project_id.is_, call:ConfigProfile.tool_type_id.is_, call:session.execute, call:result.scalars().all, call:str, func:validate_git_url(session: AsyncSession, current_user_id: uuid.UUID, url: str, ssh_key_id: str | None) → ValidateGitUrlResponse, call:parse_git_url, call:url.strip, call:parse_result.get, call:ValidateGitUrlResponse, call:uuid.UUID, call:session.get, call:_get_fernet, call:fernet.decrypt(ssh_key.private_key_encrypted.encode()).decode, call:ssh_key.private_key_encrypted.encode, call:tempfile.mkstemp, call:os.write, call:private_key.encode, call:os.close, call:os.chmod, call:subprocess.run, call:os.path.exists, call:os.unlink, call:result.stderr.strip, call:stderr.lower, call:result.stdout.strip().split, call:line.strip, call:line.split, call:len, call:ref.startswith, call:branches.append | dep: logging, os, subprocess, uuid, typing, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.models, src.services.shared.ssh_keys, src.utils.git_url_parser, src.schemas.config, tempfile
- __init__.py | Re-exports configuration profile resolution components to make them accessible as a unified module interface. | dep: src.services.config.config_profile_resolver
- config_profile_resolver.py | Resolves configuration profiles recursively with ordered includes, deterministic merge rules, and cycle detection. | exp: class:ConfigProfileCycleError, class:ConfigProfileNotFoundError, class:ResolvedMount, class:ResolvedProfile, func:_detect_cycle(profile_id: uuid.UUID, visited: set[uuid.UUID], path: list[uuid.UUID]) → bool, func:_merge_env_vars(base: dict[str, str], overlay: dict[str, str], overrides: dict[str, str], source_name: str) → dict[str, str], call:dict, call:overlay.items, func:_merge_runtime_hints(base: dict[str, Any], overlay: dict[str, Any], overrides: dict[str, str], source_name: str) → dict[str, Any], call:dict, call:overlay.items, func:_merge_files(base: dict[str, str], overlay: dict[str, str], overrides: dict[str, str], source_name: str) → dict[str, str], call:dict, call:overlay.items, func:_merge_mounts(base: dict[str, ResolvedMount], overlay: list[dict[str, Any]], overrides: dict[str, str], source_name: str) → dict[str, ResolvedMount], call:dict, call:mount_data.get, call:files.items, call:ResolvedMount, func:_find_mount_conflicts(profile: ConfigProfile, resolved: ResolvedProfile) → list[dict[str, Any]], call:m.get("files", {}).keys, call:resolved.mounts.values, call:conflicts.append, func:_merge_git_mounts(base: list[dict[str, Any]], overlay: list[dict[str, Any]], source_name: str) → list[dict[str, Any]], call:list, call:enumerate, call:_normalize_git_mount_entry, call:dict, call:m.get, call:mount.get, call:existing.get, call:existing["mappings"].append, call:existing_sources.add, call:len, call:result.append, func:_normalize_git_mount_entry(entry: dict[str, Any]) → dict[str, Any], call:dict, call:entry.get, call:entry.pop, func:_resolve_profile_recursive(session: AsyncSession, profile_id: uuid.UUID, visited: set[uuid.UUID], path: list[uuid.UUID]) → ResolvedProfile, call:_detect_cycle, call:" -> ".join, call:str, call:session.get, call:ResolvedProfile, call:select(ConfigProfileInclude) .where(ConfigProfileInclude.profile_id == profile_id) .order_by, call:session.execute, call:include_result.scalars().all, call:_resolve_profile_recursive, call:result.included_profiles.append, call:_merge_env_vars, call:_merge_runtime_hints, call:_merge_files, call:_merge_mounts, call:included.mounts.values, call:_merge_git_mounts, raise:ConfigProfileCycleError, raise:ConfigProfileNotFoundError, func:resolve_profile(session: AsyncSession, profile_id: uuid.UUID) → ResolvedProfile, call:_resolve_profile_recursive, call:set, func:check_include_cycle(session: AsyncSession, profile_id: uuid.UUID, new_include_id) → list[uuid.UUID] | None, call:select(ConfigProfileInclude) .where(ConfigProfileInclude.profile_id == current_id) .order_by, call:session.execute, call:include_result.scalars().all, call:_check_from, call:set, call:len, func:_check_from(current_id: uuid.UUID, target_id: uuid.UUID, visited: set[uuid.UUID], path: list[uuid.UUID]) → list[uuid.UUID] | None, call:select(ConfigProfileInclude) .where(ConfigProfileInclude.profile_id == current_id) .order_by, call:session.execute, call:include_result.scalars().all, call:_check_from, func:apply_resolved_profile(instance_dir: str, resolved: ResolvedProfile, home_dir) → tuple[dict[str, str], dict[str, str], list[dict], dict[str, Any]], call:Path, call:dict, call:files.items, call:full_path.resolve().relative_to, call:instance_path.resolve, call:logger.warning, call:full_path.parent.mkdir, call:full_path.write_text, call:resolved.mounts.values, call:os.path.normpath, call:expand_container_path, call:expanded_target.lstrip("/").replace, call:mount_dir.mkdir, call:mount.files.items, call:mount_dir.resolve, call:volume_mounts.append, call:str, func:expand_container_path(path: str, home_dir: str) → str, call:path.startswith, call:os.path.join, func:resolved_profile_to_dict(resolved: ResolvedProfile) → dict[str, Any], call:str, call:resolved.mounts.values | dep: logging, os, uuid, dataclasses, typing, sqlalchemy, sqlalchemy.ext.asyncio, src.models, pathlib
- crud_service.py | Provides CRUD operations and validation logic for configuration profiles, including size limits, access control, and include cycle detection. | exp: func:calculate_profile_size(data: dict) → int, call:data.get("env_vars", {}).items, call:len, call:key.encode, call:str(value).encode, call:data.get("runtime_hints", {}).items, call:str(mount.get("target", "")).encode, call:str(mount.get("mode", "")).encode, call:mount.get("files", {}).items, call:path.encode, call:content.encode, call:data.get("files", {}).items, func:get_profile_with_includes(session: AsyncSession, profile_id: uuid.UUID) → ConfigProfile | None, call:session.execute, call:select(ConfigProfile) .where(ConfigProfile.id == profile_id) .options, call:selectinload, call:result.scalar_one_or_none, func:check_access(session: AsyncSession, user_id: uuid.UUID, project_id, tool_type_id) → None, call:session.get, raise:HTTPException, func:validate_git_mounts(session: AsyncSession, user_id: uuid.UUID, git_mounts: list[Any], project_id) → None, call:mount.get, call:remote_url.startswith, raise:HTTPException, func:profile_to_response(profile: ConfigProfile, includes) → dict, call:str, call:profile.created_at.isoformat, call:profile.updated_at.isoformat, func:get_or_create_user_config(session: AsyncSession, user_id: uuid.UUID) → UserConfig, call:session.execute, call:select(UserConfig).where, call:result.scalar_one_or_none, call:UserConfig, call:session.add, func:validate_default_profiles(session: AsyncSession, user_id: uuid.UUID, default_profiles: dict[str, str]) → None, call:default_profiles.items, call:uuid.UUID, call:session.get, raise:HTTPException, func:create_profile(session: AsyncSession, user_id: uuid.UUID, data: Any) → ConfigProfile, call:session.execute, call:select(ConfigProfile) .where( ConfigProfile.user_id == user_id, ConfigProfile.name == data.name, ) .options, call:selectinload, call:existing.scalar_one_or_none, call:uuid.UUID, call:check_access, call:m.model_dump, call:hasattr, call:validate_git_mounts, call:calculate_profile_size, call:data.model_dump, call:ConfigProfile, call:session.add, call:session.commit, call:select(ConfigProfile) .where(ConfigProfile.id == profile.id) .options, call:result.scalar_one, raise:HTTPException, func:update_profile(session: AsyncSession, profile: ConfigProfile, data: Any) → ConfigProfile, call:data.model_dump, call:session.execute, call:select(ConfigProfile).where, call:existing.scalar_one_or_none, call:uuid.UUID, call:check_access, call:m.model_dump, call:hasattr, call:validate_git_mounts, call:profile_to_response, call:calculate_profile_size, call:update_data.items, call:isinstance, call:setattr, call:session.commit, call:select(ConfigProfile) .where(ConfigProfile.id == profile.id) .options, call:selectinload, call:result.scalar_one, raise:HTTPException, func:update_includes(session: AsyncSession, profile: ConfigProfile, included_ids: list[uuid.UUID], user_id: uuid.UUID) → ConfigProfile, call:session.get, call:check_include_cycle, call:" -> ".join, call:str, call:session.execute, call:select(ConfigProfileInclude).where, call:result.scalars().all, call:session.delete, call:session.flush, call:enumerate, call:ConfigProfileInclude, call:session.add, call:session.commit, call:select(ConfigProfile).where, call:result.scalar_one, raise:HTTPException | dep: uuid, typing, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, sqlalchemy.orm, src.models, src.models.project, src.services.config.config_profile_resolver
- resolver_service.py | Resolves default configuration profiles for users/projects/tools and validates Git URLs by checking remote repository accessibility and listing branches, optionally using SSH key authentication. | exp: func:resolve_default_profile(session: AsyncSession, user_id: uuid.UUID, project_id: uuid.UUID, tool_type_id: uuid.UUID) → dict, call:select(ConfigProfile) .where(ConfigProfile.user_id == user_id) .where( (ConfigProfile.project_id.is_(None) & ConfigProfile.tool_type_id.is_(None)) | (ConfigProfile.project_id == project_id) | (ConfigProfile.tool_type_id == tool_type_id) | ( (ConfigProfile.project_id == project_id) & (ConfigProfile.tool_type_id == tool_type_id) ) ) .order_by, call:ConfigProfile.project_id.is_, call:ConfigProfile.tool_type_id.is_, call:session.execute, call:result.scalars().all, call:str, func:validate_git_url(session: AsyncSession, current_user_id: uuid.UUID, url: str, ssh_key_id: str | None) → ValidateGitUrlResponse, call:parse_git_url, call:url.strip, call:parse_result.get, call:ValidateGitUrlResponse, call:uuid.UUID, call:session.get, call:_get_fernet, call:fernet.decrypt(ssh_key.private_key_encrypted.encode()).decode, call:ssh_key.private_key_encrypted.encode, call:tempfile.mkstemp, call:os.write, call:private_key.encode, call:os.close, call:os.chmod, call:subprocess.run, call:os.path.exists, call:os.unlink, call:result.stderr.strip, call:stderr.lower, call:result.stdout.strip().split, call:line.strip, call:line.split, call:len, call:ref.startswith, call:branches.append | dep: logging, os, subprocess, uuid, typing, fastapi, sqlalchemy, sqlalchemy.ext.asyncio, src.models, src.services.shared.ssh_keys, src.utils.git_url_parser, src.schemas.config, tempfile
## arch
Layered service architecture with separation between resolution logic (recursive merge with cycle detection), CRUD operations (validation, access control, size limits), and default resolution (Git/SSH integration), exposed through a unified facade pattern via __init__.py.
Service-layer pattern with separation between resolution logic (recursive merge with cycle detection), CRUD operations (validation, access control, size limits), and external integration (Git URL validation with SSH support), exposed through a unified module facade.
## tags
profile, call:, call:select, merge, git, call:str, call:session.execute, cycle
## symbols
@@ -2,7 +2,7 @@
dir: apps/api/src/services/docker
## role
Provides Docker infrastructure automation for container lifecycle management, service composition, secure configuration deployment, and external network tunneling.
Provides Docker infrastructure automation for container lifecycle management, service composition, configuration deployment, and secure public tunneling.
## parent
index: apps/api/src/services/.pi-map.index.md
map: apps/api/src/services/.pi-map.md
+6 -6
View File
@@ -4,15 +4,15 @@ dir: apps/api/src/services/docker
index: apps/api/src/services/docker/.pi-map.index.md
## role
Provides Docker infrastructure automation for container lifecycle management, service composition, secure configuration deployment, and external network tunneling.
Provides Docker infrastructure automation for container lifecycle management, service composition, configuration deployment, and secure public tunneling.
## files
- __init__.py | Package initialization file that exposes Docker-related service functions for container operations, compose management, configuration staging, and tunnel management. | dep: src.services.docker.compose, src.services.docker.config_staging, src.services.docker.container, src.services.docker.tunnel
- __init__.py | Exports Docker service functions for container, compose, config staging, and tunnel operations as a unified package interface. | dep: src.services.docker.compose, src.services.docker.config_staging, src.services.docker.container, src.services.docker.tunnel
- compose.py | Generates, renders, and executes Docker Compose files with volume sorting and template variable substitution. | exp: func:sort_volumes_by_specificity(volumes: list[str]) → list[str], call:vol.split, call:len, call:parts[1].rstrip, call:target.count, call:targets.append, call:Counter(targets).items, call:logger.warning, call:sorted, func:_target_depth(vol: str) → int, call:vol.split, call:len, call:parts[1].rstrip, call:target.count, func:render_compose_template(template: str, variables: dict[str, Any]) → str, call:variables.items, call:result.replace, call:str, call:aliases.items, call:variables.get, func:write_compose_file(instance_dir: str, content: str) → str, call:Path, call:compose_path.write_text, call:str, func:execute_compose_command(compose_path: str, action: str, timeout, env_file) → tuple[int, str, str], call:Path, call:cmd.extend, call:cmd.append, call:subprocess.run, call:str, raise:ValueError | dep: logging, subprocess, collections, pathlib, typing, collections.Counter, pathlib.Path, typing.Any
- config_staging.py | Stages configuration files into instance directories with security checks for path traversal. | exp: func:ensure_instance_directory(instance_id: str, base_path) → str, call:Settings, call:Path, call:instance_dir.mkdir, call:str, call:instance_dir.absolute, func:write_env_file(instance_dir: str, env_vars: dict[str, str]) → str, call:Path, call:env_vars.items, call:env_path.write_text, call:"\n".join, call:str, func:write_config_files(instance_dir: str, files: dict[str, str]) → None, call:Path, call:files.items, call:full_path.resolve().relative_to, call:instance_path.resolve, call:full_path.parent.mkdir, call:full_path.write_text, raise:ValueError | dep: logging, pathlib, src.config, src.config.Settings
- container.py | Provides utility functions for querying Docker container runtime state, managing container network connections, and finding free TCP ports via subprocess calls to the Docker CLI. | exp: func:get_container_id(instance_name: str) → str | None, call:instance_name.lower, call:subprocess.run, call:result.stdout.strip, call:ps_result.stdout.strip().splitlines, call:line.split, call:len, call:name.lower, func:get_container_name(instance_name: str) → str | None, call:subprocess.run, call:instance_name.lower, call:result.stdout.strip().lstrip, func:get_backend_network_name() → str, call:subprocess.run, call:result.stdout.strip().split, call:net.lower, func:connect_container_to_network(container_name: str, network_name) → bool, call:get_backend_network_name, call:subprocess.run, func:get_container_ip_on_network(container_id: str, network_name) → str | None, call:get_backend_network_name, call:subprocess.run, call:result.stdout.strip, func:is_container_on_network(container_id: str, network_name) → bool, call:get_backend_network_name, call:subprocess.run, func:get_container_status(container_id: str) → dict[str, Any], call:subprocess.run, call:result.stdout.strip().split, call:int, call:len, call:parts[1].isdigit, func:wait_for_container_running(container_id: str, timeout, interval) → dict[str, Any], call:time.time, call:get_container_status, call:time.sleep, func:get_container_logs(container_id: str, tail) → str, call:subprocess.run, call:str, func:find_free_port(start, end) → int, call:range, call:socket.socket, call:s.connect_ex, raise:RuntimeError | dep: logging, subprocess, time, typing, socket
- tunnel.py | Manages Cloudflare tunnels by orchestrating cloudflared Docker containers to expose internal services via temporary public URLs. | exp: func:_tunnel_container_name(instance_name: str) → str, call:instance_name.lower, func:_ensure_image() → None, call:subprocess.run, call:result.stdout.strip, call:logger.info, call:logger.warning, func:_cleanup_stale_tunnel(tunnel_name: str) → None, call:subprocess.run, func:_get_tunnel_logs(tunnel_name: str) → tuple[str, str], call:subprocess.run, func:_get_tunnel_exit_code(tunnel_name: str) → int | None, call:subprocess.run, call:int, call:result.stdout.strip, func:start_tunnel(instance_name: str, container_port: int, timeout, target_url) → dict[str, str], call:_ensure_image, call:_tunnel_container_name, call:_cleanup_stale_tunnel, call:instance_name.lower, call:get_backend_network_name, call:logger.debug, call:" ".join, call:subprocess.run, call:proc.stdout.strip, call:re.compile, call:__import__("time").time, call:_get_tunnel_logs, call:url_pattern.search, call:match.group, call:_get_tunnel_exit_code, call:__import__("time").sleep, call:logger.info, raise:RuntimeError, func:stop_tunnel(instance_name: str) → None, call:_tunnel_container_name, call:_cleanup_stale_tunnel, call:logger.debug, func:recreate_tunnel(instance_name: str, container_port: int, target_url) → dict[str, str], call:stop_tunnel, call:start_tunnel, func:check_tunnel_health(url: str, timeout) → dict[str, Any], call:subprocess.run, call:int, call:result.stdout.strip, call:str(exc).lower, call:any | dep: logging, re, subprocess, typing, src.services.docker.container
- config_staging.py | Stages configuration files into instance directories with path security validation and environment file generation. | exp: func:ensure_instance_directory(instance_id: str, base_path) → str, call:Settings, call:Path, call:instance_dir.mkdir, call:str, call:instance_dir.absolute, func:write_env_file(instance_dir: str, env_vars: dict[str, str]) → str, call:Path, call:env_vars.items, call:env_path.write_text, call:"\n".join, call:str, func:write_config_files(instance_dir: str, files: dict[str, str]) → None, call:Path, call:files.items, call:full_path.resolve().relative_to, call:instance_path.resolve, call:full_path.parent.mkdir, call:full_path.write_text, raise:ValueError | dep: logging, pathlib, src.config, src.config.Settings
- container.py | Provides utility functions for querying Docker container runtime state, managing network connections, and finding free ports via subprocess calls to the Docker CLI. | exp: func:get_container_id(instance_name: str) → str | None, call:instance_name.lower, call:subprocess.run, call:result.stdout.strip, call:ps_result.stdout.strip().splitlines, call:line.split, call:len, call:name.lower, func:get_container_name(instance_name: str) → str | None, call:subprocess.run, call:instance_name.lower, call:result.stdout.strip().lstrip, func:get_backend_network_name() → str, call:subprocess.run, call:result.stdout.strip().split, call:net.lower, func:connect_container_to_network(container_name: str, network_name) → bool, call:get_backend_network_name, call:subprocess.run, func:get_container_ip_on_network(container_id: str, network_name) → str | None, call:get_backend_network_name, call:subprocess.run, call:result.stdout.strip, func:is_container_on_network(container_id: str, network_name) → bool, call:get_backend_network_name, call:subprocess.run, func:get_container_status(container_id: str) → dict[str, Any], call:subprocess.run, call:result.stdout.strip().split, call:int, call:len, call:parts[1].isdigit, func:wait_for_container_running(container_id: str, timeout, interval) → dict[str, Any], call:time.time, call:get_container_status, call:time.sleep, func:get_container_logs(container_id: str, tail) → str, call:subprocess.run, call:str, func:find_free_port(start, end) → int, call:range, call:socket.socket, call:s.connect_ex, raise:RuntimeError | dep: logging, subprocess, time, typing, socket
- tunnel.py | Manages Cloudflare tunnels by orchestrating cloudflared Docker containers to expose internal services via temporary public URLs. | exp: func:_tunnel_container_name(instance_name: str) → str, call:instance_name.lower, func:_ensure_image() → None, call:subprocess.run, call:result.stdout.strip, call:logger.info, call:logger.warning, func:_cleanup_stale_tunnel(tunnel_name: str) → None, call:subprocess.run, func:_get_tunnel_logs(tunnel_name: str) → tuple[str, str], call:subprocess.run, func:_get_tunnel_exit_code(tunnel_name: str) → int | None, call:subprocess.run, call:int, call:result.stdout.strip, func:start_tunnel(instance_name: str, container_port: int, timeout, target_url) → dict[str, str], call:_ensure_image, call:_tunnel_container_name, call:_cleanup_stale_tunnel, call:instance_name.lower, call:get_backend_network_name, call:logger.debug, call:" ".join, call:subprocess.run, call:proc.stdout.strip, call:re.compile, call:__import__("time").time, call:_get_tunnel_logs, call:url_pattern.search, call:match.group, call:_get_tunnel_exit_code, call:__import__("time").sleep, call:logger.info, raise:RuntimeError, func:stop_tunnel(instance_name: str) → None, call:_tunnel_container_name, call:_cleanup_stale_tunnel, call:logger.debug, func:recreate_tunnel(instance_name: str, container_port: int, target_url) → dict[str, str], call:stop_tunnel, call:start_tunnel, func:check_tunnel_health(url: str, timeout) → dict[str, Any], call:subprocess.run, call:int, call:result.stdout.strip, call:str(exc).lower, call:any | dep: logging, re, subprocess, typing, src.services.docker.container, time
## arch
Subprocess-based CLI wrapper architecture with template-driven file generation, security-validated file staging, and container-orchestrated tunnel proxying.
Modular service-oriented architecture with CLI-wrapper pattern for Docker operations, template-based file generation, and subprocess-based external tool orchestration.
## tags
tunnel, container, call:subprocess.run, get, name, call:, network, call:result.stdout.strip
## symbols
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/services/git
## role
Encapsulates all Git version control operations for workspace management, providing both synchronous and asynchronous interfaces for repository cloning, commit history, branch management, and remote operations with SSH authentication support.
Provides Git repository operations for the API, including cloning, fetching, pulling, and branch management with SSH authentication support for workspace management.
## parent
index: apps/api/src/services/.pi-map.index.md
map: apps/api/src/services/.pi-map.md
+8 -8
View File
@@ -4,17 +4,17 @@ dir: apps/api/src/services/git
index: apps/api/src/services/git/.pi-map.index.md
## role
Encapsulates all Git version control operations for workspace management, providing both synchronous and asynchronous interfaces for repository cloning, commit history, branch management, and remote operations with SSH authentication support.
Provides Git repository operations for the API, including cloning, fetching, pulling, and branch management with SSH authentication support for workspace management.
## files
- __init__.py | Exports the public API for the git services module by re-exporting key classes and functions from submodules. | dep: src.services.git.clone, src.services.git.git_operations, src.services.git.git_service
- clone.py | Provides git repository cloning with optional SSH authentication, dirty state checking, and cleanup utilities | exp: func:clone_repository(remote_url: str, ssh_key_path: str | None, instance_dir: str, branch) → str, call:Path, call:clone_path.mkdir, call:os.environ.copy, call:str, call:logger.debug, call:subprocess.run, call:logger.error, raise:RuntimeError, func:check_dirty_state(clone_path: str) → tuple[bool, list[str]], call:subprocess.run, call:logger.warning, call:line.strip, call:result.stdout.split, call:len, func:remove_clone_directory(instance_dir: str) → None, call:Path, call:clone_path.exists, call:shutil.rmtree, call:logger.debug | dep: logging, os, subprocess, pathlib, shutil
- git_operations.py | Provides asynchronous git operations (status, commit, push, pull, fetch, checkout, history, branches) scoped to a workspace directory by wrapping git CLI commands. | exp: class:GitStatus, class:Commit, class:GitOperations, method:__init__(self, workspace: Workspace) → None, method:_run(self, *cmd: str) → tuple[int, str, str], call:asyncio.create_subprocess_exec, call:proc.communicate, call:stdout.decode, call:stderr.decode, method:status(self) → GitStatus, call:self._run, call:stdout.splitlines, call:line.startswith, call:line[3:].strip, call:branch_info.split("[ahead ")[1].split, call:int, call:ahead_str.split, call:branch_info.split("[behind ")[1].split, call:behind_str.split, call:len, call:untracked.append, call:deleted.append, call:added.append, call:modified.append, call:GitStatus, method:commit(self, message: str) → None, call:self._run, call:logger.info, raise:RuntimeError, method:push(self) → None, call:self._run, call:logger.info, raise:RuntimeError, method:pull(self) → None, call:self._run, call:logger.info, raise:RuntimeError, method:fetch(self) → None, call:self._run, call:logger.info, raise:RuntimeError, method:checkout(self, branch: str) → None, call:self._run, call:logger.info, raise:RuntimeError, method:history(self, path, limit) → list[Commit], call:cmd.extend, call:self._run, call:stdout.strip().splitlines, call:line.split, call:len, call:commits.append, call:Commit, raise:RuntimeError, method:branches(self) → tuple[list[str], str], call:self._run, call:stdout.strip().splitlines, call:line.strip, call:line.startswith, call:line.endswith, call:line.replace, call:branches.append, raise:RuntimeError | dep: asyncio, logging, dataclasses, src.models, src.models.Workspace
- git_service.py | Provides asynchronous and synchronous git operations (clone, fetch, pull, branch check) with SSH key support for workspace management. | exp: class:GitService | dep: asyncio, logging, os, subprocess, tempfile
- operations.py | Provides git repository operations including cloning, initialization, remote validation, and branch listing with SSH key authentication support. | exp: func:get_repo_path(user_id: uuid.UUID, project_id: uuid.UUID, name: str) → str, call:Settings, call:os.path.join, call:str, func:build_provider_clone_url(owner: str, repo: str) → str, func:prepare_ssh_env(ssh_key: SSHKey | None) → tuple[dict, str] | None, call:_get_fernet, call:fernet.decrypt(ssh_key.private_key_encrypted.encode()).decode, call:ssh_key.private_key_encrypted.encode, call:tempfile.mkstemp, call:os.write, call:private_key.encode, call:os.close, call:os.chmod, func:preflight_remote_repository(remote_url: str, ssh_key) → None, call:prepare_ssh_env, call:subprocess.run, call:os.path.exists, call:os.unlink, call:logger.error, raise:HTTPException, func:clone_working_repository(remote_url: str, repo_path: str, ssh_key) → None, call:prepare_ssh_env, call:subprocess.run, call:os.path.exists, call:os.unlink, call:logger.error, raise:HTTPException, func:init_working_repository(repo_path: str) → None, call:subprocess.run, raise:HTTPException, func:list_remote_branches(remote_url: str, ssh_key) → tuple[list[str], str], call:prepare_ssh_env, call:subprocess.run, call:logger.warning, call:result.stdout.strip().split, call:line.split, call:len, call:ref.startswith, call:branches.append, call:str, call:os.path.exists, call:os.unlink, raise:RuntimeError | dep: logging, os, subprocess, uuid, fastapi, src.config, src.models, src.services.shared.ssh_keys, tempfile
- __init__.py | Exports the public API for the git services module by re-exporting functions and classes from submodules. | dep: src.services.git.clone, src.services.git.git_operations, src.services.git.git_service
- clone.py | Provides a service for cloning Git repositories, checking for uncommitted changes, and cleaning up clone directories. | exp: func:clone_repository(remote_url: str, ssh_key_path: str | None, instance_dir: str, branch) → str, call:Path, call:clone_path.mkdir, call:os.environ.copy, call:str, call:logger.debug, call:subprocess.run, call:logger.error, raise:RuntimeError, func:check_dirty_state(clone_path: str) → tuple[bool, list[str]], call:subprocess.run, call:logger.warning, call:line.strip, call:result.stdout.split, call:len, func:remove_clone_directory(instance_dir: str) → None, call:Path, call:clone_path.exists, call:shutil.rmtree, call:logger.debug | dep: logging, os, subprocess, pathlib, shutil
- git_operations.py | Provides an async Python interface for executing git commands within a workspace directory, parsing output into structured data types. | exp: class:GitStatus, class:Commit, class:GitOperations, method:__init__(self, workspace: Workspace) → None, method:_run(self, *cmd: str) → tuple[int, str, str], call:asyncio.create_subprocess_exec, call:proc.communicate, call:stdout.decode, call:stderr.decode, method:status(self) → GitStatus, call:self._run, call:stdout.splitlines, call:line.startswith, call:line[3:].strip, call:branch_info.split("[ahead ")[1].split, call:int, call:ahead_str.split, call:branch_info.split("[behind ")[1].split, call:behind_str.split, call:len, call:untracked.append, call:deleted.append, call:added.append, call:modified.append, call:GitStatus, method:commit(self, message: str) → None, call:self._run, call:logger.info, raise:RuntimeError, method:push(self) → None, call:self._run, call:logger.info, raise:RuntimeError, method:pull(self) → None, call:self._run, call:logger.info, raise:RuntimeError, method:fetch(self) → None, call:self._run, call:logger.info, raise:RuntimeError, method:checkout(self, branch: str) → None, call:self._run, call:logger.info, raise:RuntimeError, method:history(self, path, limit) → list[Commit], call:cmd.extend, call:self._run, call:stdout.strip().splitlines, call:line.split, call:len, call:commits.append, call:Commit, raise:RuntimeError, method:branches(self) → tuple[list[str], str], call:self._run, call:stdout.strip().splitlines, call:line.strip, call:line.startswith, call:line.endswith, call:line.replace, call:branches.append, raise:RuntimeError | dep: asyncio, logging, dataclasses, src.models, src.models.Workspace
- git_service.py | Provides asynchronous and synchronous git operations (clone, fetch, pull, branch checking) with SSH key authentication support for workspace management. | exp: class:GitService | dep: asyncio, logging, os, subprocess, tempfile
- operations.py | Provides git repository operations including clone, init, preflight checks, and branch listing with SSH key authentication support. | exp: func:get_repo_path(user_id: uuid.UUID, project_id: uuid.UUID, name: str) → str, call:Settings, call:os.path.join, call:str, func:build_provider_clone_url(owner: str, repo: str) → str, func:prepare_ssh_env(ssh_key: SSHKey | None) → tuple[dict, str] | None, call:_get_fernet, call:fernet.decrypt(ssh_key.private_key_encrypted.encode()).decode, call:ssh_key.private_key_encrypted.encode, call:tempfile.mkstemp, call:os.write, call:private_key.encode, call:os.close, call:os.chmod, func:preflight_remote_repository(remote_url: str, ssh_key) → None, call:prepare_ssh_env, call:subprocess.run, call:os.path.exists, call:os.unlink, call:logger.error, raise:HTTPException, func:clone_working_repository(remote_url: str, repo_path: str, ssh_key) → None, call:prepare_ssh_env, call:subprocess.run, call:os.path.exists, call:os.unlink, call:logger.error, raise:HTTPException, func:init_working_repository(repo_path: str) → None, call:subprocess.run, raise:HTTPException, func:list_remote_branches(remote_url: str, ssh_key) → tuple[list[str], str], call:prepare_ssh_env, call:subprocess.run, call:logger.warning, call:result.stdout.strip().split, call:line.split, call:len, call:ref.startswith, call:branches.append, call:str, call:os.path.exists, call:os.unlink, raise:RuntimeError | dep: logging, os, subprocess, uuid, fastapi, src.config, src.models, src.services.shared.ssh_keys, tempfile
## arch
Layered abstraction pattern with three implementation tiers: low-level CLI wrappers (git_operations.py, operations.py), mid-level service coordinators (git_service.py), and high-level specialized utilities (clone.py), unified through __init__.py re-exports to present a single public API surface.
Layered service architecture with separation between async command execution (git_operations.py), high-level async/sync service orchestration (git_service.py), and specific operation implementations (clone.py, operations.py), using re-export pattern (__init__.py) for clean public API surfacing.
## tags
git, raise:runtime, error, run, call:self., clone, call:subprocess.run, ssh
git, raise:runtime, error, run, call:self., clone, call:subprocess.run, call:logger.info
## symbols
- GitStatus
- Commit
@@ -2,7 +2,7 @@
dir: apps/api/src/services/instance
## role
Coordinates tool instance lifecycle events, health monitoring, and notifications across the API service.
Provides infrastructure for managing tool instance lifecycles, health monitoring, and event-driven communication within the API service.
## parent
index: apps/api/src/services/.pi-map.index.md
map: apps/api/src/services/.pi-map.md
+5 -5
View File
@@ -4,14 +4,14 @@ dir: apps/api/src/services/instance
index: apps/api/src/services/instance/.pi-map.index.md
## role
Coordinates tool instance lifecycle events, health monitoring, and notifications across the API service.
Provides infrastructure for managing tool instance lifecycles, health monitoring, and event-driven communication within the API service.
## files
- __init__.py | Exports public API for instance lifecycle services module | dep: src.services.instance.event_bus, src.services.instance.health_monitor, src.services.instance.lifecycle_hooks
- __init__.py | Exports the public API for the instance lifecycle services module. | dep: src.services.instance.event_bus, src.services.instance.health_monitor, src.services.instance.lifecycle_hooks
- event_bus.py | Implements a singleton in-memory typed event bus with publish/subscribe pattern for instance lifecycle and health events, supporting both sync and async callbacks with exception isolation. | exp: class:InstanceEventBus, method:__init__(self) → None, method:__new__(cls) → "InstanceEventBus", call:super().__new__, method:_reset_for_testing(self) → None, call:self._subscribers.clear, method:subscribe(self, event_type: str, callback: EventCallback) → Callable[[], None], call:str, call:uuid.uuid4, call:self._subscribers[event_type].append, call:self.unsubscribe, method:unsubscribe(self, event_type: str, callback_id: str) → None, method:unsubscribe_all(self, event_type: str) → None, call:self._subscribers.pop, method:publish(self, event_type: str, payload: InstanceEventPayload) → None, call:callbacks.extend, call:self._subscribers.get, call:inspect.iscoroutinefunction, call:callback, call:payload.get, call:logger.exception | dep: asyncio, inspect, logging, uuid, collections.abc, typing
- health_monitor.py | Background health monitor that polls Docker container and tunnel health for tool instances, publishes state change events, and creates notifications for errors/unhealthy states. | exp: class:HealthSnapshot, class:HealthMonitor, method:__init__(self, event_bus: InstanceEventBus) → None, method:start(self) → None, call:self._task.done, call:asyncio.get_running_loop, call:loop.create_task, call:self._poll_loop, method:stop(self) → None, call:self._task.done, call:self._task.cancel, call:self._last_known_state.clear, method:_poll_loop(self) → None, call:asyncio.sleep, call:self._run_check_cycle, call:logger.exception, method:_run_check_cycle(self) → None, call:SessionLocal, call:session.execute, call:select(ToolInstance).where, call:ToolInstance.status.in_, call:result.scalars().all, call:self._check_instance, method:_check_instance(self, session: AsyncSession, instance: ToolInstance) → None, call:logger.debug, call:get_container_status, call:logger.exception, call:str, call:get_correlation_id, call:check_tunnel_health, call:tunnel_result.get, call:HealthSnapshot, call:self._last_known_state.get, call:self._derive_status, call:self._snapshots_equal, call:self._handle_state_change, method:_derive_status(self, snapshot: HealthSnapshot, previous: HealthSnapshot | None, current_status: str | None) → str, method:_snapshots_equal(self, a: HealthSnapshot, b: HealthSnapshot) → bool, method:_handle_state_change(self, session: AsyncSession, instance: ToolInstance, previous: HealthSnapshot | None, snapshot: HealthSnapshot, new_status: str) → None, call:HealthCheck, call:session.add, call:session.commit, call:get_correlation_id, call:str, call:datetime.now(timezone.utc).isoformat, call:self._event_bus.publish, call:notification_service.create_notification, call:logger.exception | dep: asyncio, logging, uuid, dataclasses, datetime, sqlalchemy, sqlalchemy.ext.asyncio, src.database, src.models, src.services.shared.correlation, src.services.docker, src.services.shared.tunnel, src.services.instance.event_bus, src.services.shared.notification_service
- lifecycle_hooks.py | Provides helpers to publish tool instance lifecycle events, persist audit records, and conditionally send user notifications. | exp: func:_derive_title(event_type: str) → str, call:mapping.get, call:event_type.replace("instance.", "").replace("_", " ").title, func:_should_notify(event_type: str, status: str | None) → bool, func:_build_payload(event_type: str, instance: ToolInstance, status, message, metadata) → InstanceEventPayload, call:str, call:datetime.now(timezone.utc).isoformat, call:get_correlation_id, func:_write_audit_row(session: AsyncSession, instance: ToolInstance, event_type: str, created_by, status, message, metadata) → InstanceEvent, call:InstanceEvent, call:event_type.replace, call:session.add, call:session.commit, func:publish_lifecycle_event(event_bus: InstanceEventBus, session: AsyncSession, instance: ToolInstance, event_type: str, created_by, status, message, metadata) → None, call:_build_payload, call:_write_audit_row, call:event_bus.publish, call:_should_notify, call:_derive_title, call:notification_service.create_notification, call:logger.exception, call:payload.get | dep: logging, uuid, datetime, sqlalchemy.ext.asyncio, src.models, src.services.shared.correlation, src.services.instance.event_bus, src.services.shared.notification_service
- health_monitor.py | Background health monitor that polls Docker container and tunnel health for tool instances, updating database state and publishing events on status changes. | exp: class:HealthSnapshot, class:HealthMonitor, method:__init__(self, event_bus: InstanceEventBus) → None, method:start(self) → None, call:self._task.done, call:asyncio.get_running_loop, call:loop.create_task, call:self._poll_loop, method:stop(self) → None, call:self._task.done, call:self._task.cancel, call:self._last_known_state.clear, method:_poll_loop(self) → None, call:asyncio.sleep, call:self._run_check_cycle, call:logger.exception, method:_run_check_cycle(self) → None, call:SessionLocal, call:session.execute, call:select(ToolInstance).where, call:ToolInstance.status.in_, call:result.scalars().all, call:self._check_instance, method:_check_instance(self, session: AsyncSession, instance: ToolInstance) → None, call:logger.debug, call:get_container_status, call:logger.exception, call:str, call:get_correlation_id, call:check_tunnel_health, call:tunnel_result.get, call:HealthSnapshot, call:self._last_known_state.get, call:self._derive_status, call:self._snapshots_equal, call:self._handle_state_change, method:_derive_status(self, snapshot: HealthSnapshot, previous: HealthSnapshot | None, current_status: str | None) → str, method:_snapshots_equal(self, a: HealthSnapshot, b: HealthSnapshot) → bool, method:_handle_state_change(self, session: AsyncSession, instance: ToolInstance, previous: HealthSnapshot | None, snapshot: HealthSnapshot, new_status: str) → None, call:HealthCheck, call:session.add, call:session.commit, call:get_correlation_id, call:str, call:datetime.now(timezone.utc).isoformat, call:self._event_bus.publish, call:notification_service.create_notification, call:logger.exception | dep: asyncio, logging, uuid, dataclasses, datetime, sqlalchemy, sqlalchemy.ext.asyncio, src.database, src.models, src.services.shared.correlation, src.services.docker, src.services.shared.tunnel, src.services.instance.event_bus, src.services.shared.notification_service
- lifecycle_hooks.py | Publishes tool instance lifecycle events to an event bus, writes audit rows to the database, and conditionally sends notifications for errors and ready-state transitions. | exp: func:_derive_title(event_type: str) → str, call:mapping.get, call:event_type.replace("instance.", "").replace("_", " ").title, func:_should_notify(event_type: str, status: str | None) → bool, func:_build_payload(event_type: str, instance: ToolInstance, status, message, metadata) → InstanceEventPayload, call:str, call:datetime.now(timezone.utc).isoformat, call:get_correlation_id, func:_write_audit_row(session: AsyncSession, instance: ToolInstance, event_type: str, created_by, status, message, metadata) → InstanceEvent, call:InstanceEvent, call:event_type.replace, call:session.add, call:session.commit, func:publish_lifecycle_event(event_bus: InstanceEventBus, session: AsyncSession, instance: ToolInstance, event_type: str, created_by, status, message, metadata) → None, call:_build_payload, call:_write_audit_row, call:event_bus.publish, call:_should_notify, call:_derive_title, call:notification_service.create_notification, call:logger.exception, call:payload.get | dep: logging, uuid, datetime, sqlalchemy.ext.asyncio, src.models, src.services.shared.correlation, src.services.instance.event_bus, src.services.shared.notification_service
## arch
Observer pattern via typed singleton event bus with async/sync subscribers, background polling loops, and side-effect hooks for persistence and notifications.
Event-driven architecture using a singleton in-memory pub/sub event bus with typed events, background polling workers, and lifecycle hooks that coordinate database updates, audit logging, and notifications through exception-isolated sync/async callbacks.
## tags
call:self., instance, src, services, event, health, call:logger.exception, check
## symbols
@@ -2,14 +2,12 @@
dir: apps/api/src/services/shared
## role
Provides common, cross-cutting backend services used by multiple API components for security, infrastructure, and user-facing operations.
Provides common cross-cutting infrastructure services used by multiple API domains including security, I/O, container orchestration, and workspace management.
## parent
index: apps/api/src/services/.pi-map.index.md
map: apps/api/src/services/.pi-map.md
## children
- apps/api/src/services/shared/.ruff_cache
index: apps/api/src/services/shared/.ruff_cache/.pi-map.index.md
map: apps/api/src/services/shared/.ruff_cache/.pi-map.md
-
## files
- __init__.py
- correlation.py
@@ -26,7 +24,5 @@ map: apps/api/src/services/shared/.pi-map.md
## workflows
- change shared behavior
read: __init__.py, correlation.py, file_service.py
- explore shared subdirectories
index: apps/api/src/services/shared/.ruff_cache/.pi-map.index.md
## dirty
-
+10 -12
View File
@@ -4,21 +4,21 @@ dir: apps/api/src/services/shared
index: apps/api/src/services/shared/.pi-map.index.md
## role
Provides common, cross-cutting backend services used by multiple API components for security, infrastructure, and user-facing operations.
Provides common cross-cutting infrastructure services used by multiple API domains including security, I/O, container orchestration, and workspace management.
## files
- __init__.py | Re-exports shared service classes and functions from a services package to provide a unified public API | dep: src.services.shared.correlation, src.services.shared.file_service, src.services.shared.notification_service, src.services.shared.permission_fixer, src.services.shared.readiness_probe, src.services.shared.ssh_keys, src.services.shared.tunnel, src.services.shared.workspace_manager, correlation, file_service, notification_service, permission_fixer, readiness_probe, ssh_keys, tunnel, workspace_manager
- __init__.py | Re-exports shared service components from submodules to provide a unified public API for the shared services module. | dep: src.services.shared.correlation, src.services.shared.file_service, src.services.shared.notification_service, src.services.shared.permission_fixer, src.services.shared.readiness_probe, src.services.shared.ssh_keys, src.services.shared.tunnel, src.services.shared.workspace_manager
- correlation.py | Provides async correlation ID tracking via context variables and FastAPI middleware for request tracing. | exp: class:CorrelationIdMiddleware, method:dispatch(self, request: Request, call_next), call:request.headers.get, call:str, call:uuid.uuid4, call:CORRELATION_ID.set, call:call_next, call:CORRELATION_ID.reset, func:get_correlation_id() → str, call:CORRELATION_ID.get, call:str, call:uuid.uuid4 | dep: contextvars, uuid, fastapi, starlette.middleware.base, fastapi.Request, starlette.middleware.base.BaseHTTPMiddleware
- file_service.py | Provides safe file operations (list, read, write) scoped within a workspace directory with path traversal protection. | exp: class:FileEntry, class:FileService, method:list_directory(self, workspace: Workspace, relative_path) → list[FileEntry], call:os.path.join, call:os.path.normpath, call:abs_path.startswith, call:os.path.exists, call:sorted, call:os.listdir, call:os.path.isdir, call:os.path.getsize, call:os.path.isfile, call:entries.append, call:FileEntry, call:rel.replace, call:entries.sort, call:e.name.lower, raise:ValueError, method:read_file(self, workspace: Workspace, relative_path: str) → str, call:self._resolve_path, call:os.path.isfile, call:open, call:f.read, raise:FileNotFoundError, raise:ValueError, method:write_file(self, workspace: Workspace, relative_path: str, content: str) → None, call:self._resolve_path, call:os.makedirs, call:os.path.dirname, call:open, call:f.write, call:logger.info, method:_resolve_path(self, workspace: Workspace, relative_path: str) → str, call:os.path.normpath, call:os.path.join, call:abs_path.startswith, raise:ValueError | dep: logging, os, dataclasses, src.models, src.models.Workspace
- notification_service.py | Provides an async singleton service for creating, listing, reading, and dismissing user-owned notifications with strict ownership isolation. | exp: class:NotificationService, method:create_notification(self, session: AsyncSession, user_id: uuid.UUID, category: str, severity: str, title: str, message, source_type, source_id, metadata) → Notification, call:Notification, call:session.add, call:session.commit, call:session.refresh, method:list_notifications(self, session: AsyncSession, user_id: uuid.UUID, limit, offset, unread_only, mute_categories) → tuple[list[Notification], int], call:Notification.dismissed_at.is_, call:where_clauses.append, call:Notification.read_at.is_, call:Notification.category.not_in, call:select(func.count()).select_from(Notification).where, call:func.count, call:session.execute, call:total_result.scalar_one, call:select(Notification) .where(*where_clauses) .order_by(Notification.created_at.desc()) .limit(limit) .offset, call:Notification.created_at.desc, call:list, call:items_result.scalars().all, method:get_unread_count(self, session: AsyncSession, user_id: uuid.UUID) → int, call:select(func.count()) .select_from(Notification) .where, call:func.count, call:Notification.read_at.is_, call:Notification.dismissed_at.is_, call:session.execute, call:result.scalar_one, method:mark_read(self, session: AsyncSession, notification_id: uuid.UUID, user_id: uuid.UUID) → Notification, call:self._get_owned_notification, call:datetime.now, call:session.commit, call:session.refresh, method:mark_all_read(self, session: AsyncSession, user_id: uuid.UUID) → int, call:update(Notification) .where( Notification.user_id == user_id, Notification.read_at.is_(None), Notification.dismissed_at.is_(None), ) .values, call:Notification.read_at.is_, call:Notification.dismissed_at.is_, call:datetime.now, call:session.execute, call:session.commit, method:dismiss_all(self, session: AsyncSession, user_id: uuid.UUID) → int, call:update(Notification) .where( Notification.user_id == user_id, Notification.dismissed_at.is_(None), ) .values, call:Notification.dismissed_at.is_, call:datetime.now, call:session.execute, call:session.commit, method:dismiss(self, session: AsyncSession, notification_id: uuid.UUID, user_id: uuid.UUID) → None, call:self._get_owned_notification, call:datetime.now, call:session.commit, method:_get_owned_notification(self, session: AsyncSession, notification_id: uuid.UUID, user_id: uuid.UUID) → Notification, call:session.get, raise:ValueError | dep: uuid, datetime, typing, sqlalchemy, sqlalchemy.engine, sqlalchemy.ext.asyncio, src.models, src.models.Notification
- file_service.py | Provides secure file operations (list, read, write) scoped within a workspace directory with path traversal protection. | exp: class:FileEntry, class:FileService, method:list_directory(self, workspace: Workspace, relative_path) → list[FileEntry], call:os.path.join, call:os.path.normpath, call:abs_path.startswith, call:os.path.exists, call:sorted, call:os.listdir, call:os.path.isdir, call:os.path.getsize, call:os.path.isfile, call:entries.append, call:FileEntry, call:rel.replace, call:entries.sort, call:e.name.lower, raise:ValueError, method:read_file(self, workspace: Workspace, relative_path: str) → str, call:self._resolve_path, call:os.path.isfile, call:open, call:f.read, raise:FileNotFoundError, raise:ValueError, method:write_file(self, workspace: Workspace, relative_path: str, content: str) → None, call:self._resolve_path, call:os.makedirs, call:os.path.dirname, call:open, call:f.write, call:logger.info, method:_resolve_path(self, workspace: Workspace, relative_path: str) → str, call:os.path.normpath, call:os.path.join, call:abs_path.startswith, raise:ValueError | dep: logging, os, dataclasses, src.models, src.models.Workspace
- notification_service.py | Provides a singleton service for creating, listing, reading, and dismissing user-owned notifications with strict ownership isolation via SQLAlchemy async operations. | exp: class:NotificationService, method:create_notification(self, session: AsyncSession, user_id: uuid.UUID, category: str, severity: str, title: str, message, source_type, source_id, metadata) → Notification, call:Notification, call:session.add, call:session.commit, call:session.refresh, method:list_notifications(self, session: AsyncSession, user_id: uuid.UUID, limit, offset, unread_only, mute_categories) → tuple[list[Notification], int], call:Notification.dismissed_at.is_, call:where_clauses.append, call:Notification.read_at.is_, call:Notification.category.not_in, call:select(func.count()).select_from(Notification).where, call:func.count, call:session.execute, call:total_result.scalar_one, call:select(Notification) .where(*where_clauses) .order_by(Notification.created_at.desc()) .limit(limit) .offset, call:Notification.created_at.desc, call:list, call:items_result.scalars().all, method:get_unread_count(self, session: AsyncSession, user_id: uuid.UUID) → int, call:select(func.count()) .select_from(Notification) .where, call:func.count, call:Notification.read_at.is_, call:Notification.dismissed_at.is_, call:session.execute, call:result.scalar_one, method:mark_read(self, session: AsyncSession, notification_id: uuid.UUID, user_id: uuid.UUID) → Notification, call:self._get_owned_notification, call:datetime.now, call:session.commit, call:session.refresh, method:mark_all_read(self, session: AsyncSession, user_id: uuid.UUID) → int, call:update(Notification) .where( Notification.user_id == user_id, Notification.read_at.is_(None), Notification.dismissed_at.is_(None), ) .values, call:Notification.read_at.is_, call:Notification.dismissed_at.is_, call:datetime.now, call:session.execute, call:session.commit, method:dismiss_all(self, session: AsyncSession, user_id: uuid.UUID) → int, call:update(Notification) .where( Notification.user_id == user_id, Notification.dismissed_at.is_(None), ) .values, call:Notification.dismissed_at.is_, call:datetime.now, call:session.execute, call:session.commit, method:dismiss(self, session: AsyncSession, notification_id: uuid.UUID, user_id: uuid.UUID) → None, call:self._get_owned_notification, call:datetime.now, call:session.commit, method:_get_owned_notification(self, session: AsyncSession, notification_id: uuid.UUID, user_id: uuid.UUID) → Notification, call:session.get, raise:ValueError | dep: uuid, datetime, typing, sqlalchemy, sqlalchemy.engine, sqlalchemy.ext.asyncio, src.models, src.models.Notification
- permission_fixer.py | Applies mount and SSH permission policies inside running Docker containers by executing chown/chmod commands via docker exec as root. | exp: class:PermissionFixError, func:apply_mount_permissions(container_id: str, mounts: list[dict], timeout) → list[dict[str, Any]], call:mount.get, call:logger.debug, call:results.append, call:_run_in_container, call:str, call:logger.warning, func:_exec_and_log(container_id: str, command: list[str], timeout: int, description: str) → str, call:logger.debug, call:" ".join, call:subprocess.run, call:result.stdout.strip, call:result.stderr.strip, raise:PermissionFixError, func:apply_ssh_permissions(container_id: str, ssh_target: str, container_user: str, timeout) → dict[str, Any], call:_exec_and_log, call:logger.info, call:str, call:logger.warning, func:_run_in_container(container_id: str, command: list[str], timeout: int) → None, call:subprocess.run, raise:PermissionFixError, func:check_root_user_available(container_id: str, timeout) → bool, call:_run_in_container | dep: logging, subprocess, typing
- readiness_probe.py | Executes a retryable readiness probe command inside a Docker container with configurable timeout and interval | exp: func:execute_probe(container_id: str, command: str, timeout, interval) → tuple[bool, list[str]], call:asyncio.get_event_loop().time, call:logs.append, call:logger.debug, call:subprocess.run, call:result.stdout.strip, call:result.stderr.strip, call:asyncio.sleep | dep: asyncio, logging, subprocess
- ssh_keys.py | Decrypts and writes SSH key files to instance directories for container mounting, with optional ownership configuration and SSH config generation. | exp: func:_get_fernet() → Fernet, call:Settings, call:hashlib.sha256(settings.session_secret.encode()).digest, call:settings.session_secret.encode, call:base64.urlsafe_b64encode, call:Fernet, func:_sanitize_filename(name: str) → str, call:re.sub, call:sanitized.strip, func:prepare_ssh_key_files(instance_dir: str, ssh_key, subdir, uid, gid, key_filename, write_config) → str, call:Path, call:ssh_dir.mkdir, call:_get_fernet, call:fernet.decrypt(ssh_key.private_key_encrypted.encode()).decode, call:ssh_key.private_key_encrypted.encode, call:private_key_path.write_text, call:os.chmod, call:public_key_path.write_text, call:config_path.write_text, call:os.chown, call:logger.debug, call:logger.warning, call:os.getuid, call:str, func:write_ssh_config(ssh_dir: str, key_filenames: list[str], uid, gid) → None, call:Path, call:ssh_dir_path.mkdir, call:lines.append, call:"\n".join, call:config_path.write_text, call:os.chmod, call:os.chown, func:cleanup_ssh_key_files(instance_dir: str) → None, call:Path, call:ssh_dir.exists, call:ssh_dir.iterdir, call:file_path.unlink, call:ssh_dir.rmdir | dep: logging, os, re, pathlib, cryptography.fernet, src.config, base64, hashlib
- tunnel.py | Re-exports Docker tunnel functions from a nested module for backward compatibility. | dep: src.services.docker.tunnel
- workspace_manager.py | Manages workspace lifecycle operations including creation, deletion, synchronization, and migration of legacy tool instances into workspace-based repositories. | exp: class:SyncResult, class:WorkspaceHasInstancesError, method:__init__(self, instances: list[dict]) → None, call:super().__init__, call:len, class:WorkspaceManager, method:_workspace_path(self, workspace_id: uuid.UUID, repo: "GitRepository") → str, call:os.path.join, call:str, call:self._repo_directory_name, method:create(self, repo: GitRepository, user_id: uuid.UUID, name: str, branch, session) → Workspace, call:self._repo_directory_name, call:uuid.uuid4, call:os.path.join, call:str, call:logger.info, call:os.path.exists, call:logger.warning, call:shutil.rmtree, call:os.makedirs, call:contextlib.suppress, call:os.chmod, call:getattr, call:session.execute, call:select(SSHKey).where, call:result.scalar_one_or_none, call:_get_fernet, call:fernet.decrypt( ssh_key_obj.private_key_encrypted.encode() ).decode, call:ssh_key_obj.private_key_encrypted.encode, call:GitService.clone, call:logger.error, call:self._make_world_writable, call:Workspace, call:datetime.now, raise:ValueError, method:delete(self, workspace: Workspace, force, session) → None, call:self._get_instances, call:self._stop_and_delete_instance, call:os.path.exists, call:shutil.rmtree, call:logger.info, call:session.delete, raise:ValueError, raise:WorkspaceHasInstancesError, method:sync(self, workspace: Workspace, session) → SyncResult, call:logger.info, call:session.get, call:getattr, call:session.execute, call:select(SSHKey).where, call:result.scalar_one_or_none, call:_get_fernet, call:fernet.decrypt( ssh_key_obj.private_key_encrypted.encode() ).decode, call:ssh_key_obj.private_key_encrypted.encode, call:GitService.fetch, call:GitService.branch_exists_remotely, call:SyncResult, call:GitService.pull, call:self._make_world_writable, call:datetime.now, method:_make_world_writable(self, path: str) → None, call:contextlib.suppress, call:os.chmod, call:os.walk, call:os.path.join, call:os.stat, method:_get_instances(self, workspace: Workspace, session: AsyncSession) → list[ToolInstance], call:session.execute, call:select(ToolInstance).where, call:list, call:result.scalars().all, method:_stop_and_delete_instance(self, instance: ToolInstance, session: AsyncSession) → None, call:delete_tool_instance, call:logger.info, call:logger.error, method:ensure_instance_workspace(self, instance: ToolInstance, session: AsyncSession) → Workspace, call:session.get, call:self._workspace_name_exists, call:self._migrate_clone_into_workspace, call:self.create, call:session.add, call:session.commit, call:session.refresh, call:logger.info, raise:RuntimeError, method:_workspace_name_exists(self, session: AsyncSession, repo_id: uuid.UUID, name: str) → bool, call:session.execute, call:select(Workspace).where, call:result.scalar_one_or_none, method:_migrate_clone_into_workspace(self, instance: ToolInstance, repo: "GitRepository", session: AsyncSession, name: str) → Workspace, call:os.path.dirname, call:os.path.join, call:os.path.exists, call:uuid.uuid4, call:str, call:self._repo_directory_name, call:os.makedirs, call:contextlib.suppress, call:os.chmod, call:shutil.rmtree, call:shutil.move, call:self._make_world_writable, call:Workspace, call:datetime.now, call:session.add, call:session.flush, raise:RuntimeError | dep: contextlib, logging, os, shutil, stat, uuid, dataclasses, datetime, typing, sqlalchemy, src.models, src.services.git.git_service, src.services.shared.ssh_keys, src.utils.git_url_parser, sqlalchemy.ext.asyncio, src.services.tool.instance_service
- readiness_probe.py | Executes retryable readiness probe commands inside Docker containers with configurable timeout and interval. | exp: func:execute_probe(container_id: str, command: str, timeout, interval) → tuple[bool, list[str]], call:asyncio.get_event_loop().time, call:logs.append, call:logger.debug, call:subprocess.run, call:result.stdout.strip, call:result.stderr.strip, call:asyncio.sleep | dep: asyncio, logging, subprocess
- ssh_keys.py | Decrypts encrypted SSH keys and writes them to instance directories with proper permissions and SSH config files for container use. | exp: func:_get_fernet() → Fernet, call:Settings, call:hashlib.sha256(settings.session_secret.encode()).digest, call:settings.session_secret.encode, call:base64.urlsafe_b64encode, call:Fernet, func:_sanitize_filename(name: str) → str, call:re.sub, call:sanitized.strip, func:prepare_ssh_key_files(instance_dir: str, ssh_key, subdir, uid, gid, key_filename, write_config) → str, call:Path, call:ssh_dir.mkdir, call:_get_fernet, call:fernet.decrypt(ssh_key.private_key_encrypted.encode()).decode, call:ssh_key.private_key_encrypted.encode, call:private_key_path.write_text, call:os.chmod, call:public_key_path.write_text, call:config_path.write_text, call:os.chown, call:logger.debug, call:logger.warning, call:os.getuid, call:str, func:write_ssh_config(ssh_dir: str, key_filenames: list[str], uid, gid) → None, call:Path, call:ssh_dir_path.mkdir, call:lines.append, call:"\n".join, call:config_path.write_text, call:os.chmod, call:os.chown, func:cleanup_ssh_key_files(instance_dir: str) → None, call:Path, call:ssh_dir.exists, call:ssh_dir.iterdir, call:file_path.unlink, call:ssh_dir.rmdir | dep: logging, os, re, pathlib, cryptography.fernet, src.config, base64, hashlib, pathlib.Path, cryptography.fernet.Fernet, src.config.Settings
- tunnel.py | Re-exports docker tunnel functions for backward compatibility | dep: src.services.docker.tunnel
- workspace_manager.py | Manages the lifecycle of git-backed workspaces including creation, deletion, synchronization, and migration of legacy tool instances. | exp: class:SyncResult, class:WorkspaceHasInstancesError, method:__init__(self, instances: list[dict]) → None, call:super().__init__, call:len, class:WorkspaceManager, method:_workspace_path(self, workspace_id: uuid.UUID, repo: "GitRepository") → str, call:os.path.join, call:str, call:self._repo_directory_name, method:create(self, repo: GitRepository, user_id: uuid.UUID, name: str, branch, session) → Workspace, call:self._repo_directory_name, call:uuid.uuid4, call:os.path.join, call:str, call:logger.info, call:os.path.exists, call:logger.warning, call:shutil.rmtree, call:os.makedirs, call:contextlib.suppress, call:os.chmod, call:getattr, call:session.execute, call:select(SSHKey).where, call:result.scalar_one_or_none, call:_get_fernet, call:fernet.decrypt( ssh_key_obj.private_key_encrypted.encode() ).decode, call:ssh_key_obj.private_key_encrypted.encode, call:GitService.clone, call:logger.error, call:self._make_world_writable, call:Workspace, call:datetime.now, raise:ValueError, method:delete(self, workspace: Workspace, force, session) → None, call:self._get_instances, call:self._stop_and_delete_instance, call:os.path.exists, call:shutil.rmtree, call:logger.info, call:session.delete, raise:ValueError, raise:WorkspaceHasInstancesError, method:sync(self, workspace: Workspace, session) → SyncResult, call:logger.info, call:session.get, call:getattr, call:session.execute, call:select(SSHKey).where, call:result.scalar_one_or_none, call:_get_fernet, call:fernet.decrypt( ssh_key_obj.private_key_encrypted.encode() ).decode, call:ssh_key_obj.private_key_encrypted.encode, call:GitService.fetch, call:GitService.branch_exists_remotely, call:SyncResult, call:GitService.pull, call:self._make_world_writable, call:datetime.now, method:_make_world_writable(self, path: str) → None, call:contextlib.suppress, call:os.chmod, call:os.walk, call:os.path.join, call:os.stat, method:_get_instances(self, workspace: Workspace, session: AsyncSession) → list[ToolInstance], call:session.execute, call:select(ToolInstance).where, call:list, call:result.scalars().all, method:_stop_and_delete_instance(self, instance: ToolInstance, session: AsyncSession) → None, call:delete_tool_instance, call:logger.info, call:logger.error, method:ensure_instance_workspace(self, instance: ToolInstance, session: AsyncSession) → Workspace, call:session.get, call:self._workspace_name_exists, call:self._migrate_clone_into_workspace, call:self.create, call:session.add, call:session.commit, call:session.refresh, call:logger.info, raise:RuntimeError, method:_workspace_name_exists(self, session: AsyncSession, repo_id: uuid.UUID, name: str) → bool, call:session.execute, call:select(Workspace).where, call:result.scalar_one_or_none, method:_migrate_clone_into_workspace(self, instance: ToolInstance, repo: "GitRepository", session: AsyncSession, name: str) → Workspace, call:os.path.dirname, call:os.path.join, call:os.path.exists, call:uuid.uuid4, call:str, call:self._repo_directory_name, call:os.makedirs, call:contextlib.suppress, call:os.chmod, call:shutil.rmtree, call:shutil.move, call:self._make_world_writable, call:Workspace, call:datetime.now, call:session.add, call:session.flush, raise:RuntimeError | dep: contextlib, logging, os, shutil, stat, uuid, dataclasses, datetime, typing, sqlalchemy, src.models, src.services.git.git_service, src.services.shared.ssh_keys, src.utils.git_url_parser, sqlalchemy.ext.asyncio, src.services.tool.instance_service
## arch
Modular utility services following singleton and async patterns, with Docker/container integration, filesystem sandboxing, context-based request tracing, and strict resource ownership isolation.
Modular utility services with singleton patterns, async/await throughout, context variable propagation for request tracing, file-system sandboxing, and container-exec delegation for privileged operations.
## tags
error, call:self., get, workspace, src, key, call:str, call:session.execute
error, call:self., get, src, workspace, key, call:str, call:session.execute
## symbols
- CorrelationIdMiddleware
- FileEntry
@@ -31,7 +31,5 @@ error, call:self., get, workspace, src, key, call:str, call:session.execute
## workflows
- change shared behavior
read: __init__.py, correlation.py, file_service.py
- explore shared subdirectories
index: apps/api/src/services/shared/.ruff_cache/.pi-map.index.md
## dirty
-
@@ -2,7 +2,7 @@
dir: apps/api/src/services/terminal
## role
Provides WebSocket-connected terminal session management with PTY-based I/O for remote terminal access in the API server.
Provides backend infrastructure for managing interactive WebSocket-based terminal sessions within Docker containers, including session lifecycle, PTY I/O handling, and resource cleanup.
## parent
index: apps/api/src/services/.pi-map.index.md
map: apps/api/src/services/.pi-map.md
+5 -5
View File
@@ -4,13 +4,13 @@ dir: apps/api/src/services/terminal
index: apps/api/src/services/terminal/.pi-map.index.md
## role
Provides WebSocket-connected terminal session management with PTY-based I/O for remote terminal access in the API server.
Provides backend infrastructure for managing interactive WebSocket-based terminal sessions within Docker containers, including session lifecycle, PTY I/O handling, and resource cleanup.
## files
- __init__.py | Package initialization file that exports the public API for a terminal services module | dep: src.services.terminal.terminal_manager, src.services.terminal.terminal_session
- terminal_manager.py | Manages WebSocket-connected terminal sessions with lifecycle control, idle cleanup, database persistence, and per-instance session limits. | exp: class:MaxSessionsExceededError, method:__init__(self, instance_id: str, max_sessions) → None, call:super().__init__, class:TerminalManager, method:__init__(self) → None, call:self._start_idle_check, method:_start_idle_check(self) → None, call:self._idle_check_task.done, call:asyncio.get_running_loop, call:loop.create_task, call:self._idle_check_loop, method:_idle_check_loop(self) → None, call:asyncio.sleep, call:self._cleanup_idle_sessions, call:logger.error, method:_cleanup_idle_sessions(self) → None, call:list, call:self._sessions.items, call:session.is_idle, call:idle_keys.append, call:logger.info, call:self._sessions.pop, call:session.close, call:asyncio.create_task, call:self._mark_closed_in_db, method:_insert_db_session_row(self, session_id: str, instance_id: uuid.UUID, name: str) → None, call:SessionLocal, call:pg_insert(TerminalSessionModel) .values( id=uuid.UUID(session_id), instance_id=instance_id, name=name, status="active", created_at=datetime.now(timezone.utc), last_activity_at=datetime.now(timezone.utc), ) .on_conflict_do_nothing, call:uuid.UUID, call:datetime.now, call:db_session.execute, call:db_session.commit, call:logger.debug, call:logger.error, method:_mark_closed_in_db(self, session_id: str) → None, call:SessionLocal, call:db_session.get, call:uuid.UUID, call:datetime.now, call:db_session.commit, call:logger.debug, call:logger.error, method:_count_sessions_for_instance(self, instance_id_str: str) → int, call:sum, method:create_session(self, instance_id: uuid.UUID, container_id: str, startup_command, name, session_id) → TerminalSession, call:str, call:self._count_sessions_for_instance, call:uuid.uuid4, call:TerminalSession, call:session.start, call:asyncio.create_task, call:self._insert_db_session_row, call:logger.info, raise:MaxSessionsExceededError, method:get_or_create_session(self, instance_id: uuid.UUID, container_id: str, startup_command) → TerminalSession, call:self._start_idle_check, call:str, call:session.is_alive, call:logger.debug, call:session.close, call:logger.info, call:uuid.uuid4, call:TerminalSession, call:session.start, call:asyncio.create_task, call:self._insert_db_session_row, method:get_session(self, instance_id: str, session_id: str) → TerminalSession | None, call:self._sessions.get, call:self._sessions.items, method:_find_key_by_internal_id(self, instance_id: str, internal_session_id: str) → tuple[str, str] | None, call:self._sessions.items, method:get_sessions_for_instance(self, instance_id: str) → list[TerminalSession], call:self._sessions.items, method:close_session(self, instance_id: str, session_id: str) → None, call:self._sessions.pop, call:session.close, call:asyncio.create_task, call:self._mark_closed_in_db, call:logger.info, method:attach_websocket(self, session: TerminalSession, websocket: WebSocket) → None, call:session.has_websockets, call:logger.debug, call:list, call:ws.close, call:session._websockets.clear, call:session.attach_websocket, call:session.get_buffer, call:websocket.send_bytes, method:detach_websocket(self, session: TerminalSession, websocket: WebSocket) → None, call:session.detach_websocket, method:reset_session(self, instance_id: uuid.UUID, container_id: str, startup_command, session_id, name) → TerminalSession, call:str, call:logger.debug, call:self._sessions.pop, call:old_session.close, call:asyncio.create_task, call:self._mark_closed_in_db, call:uuid.uuid4, call:TerminalSession, call:new_session.start, call:self._insert_db_session_row, method:close_all(self) → None, call:list, call:self._sessions.values, call:self._sessions.clear, call:session.close, call:self._idle_check_task.done, call:self._idle_check_task.cancel | dep: asyncio, logging, uuid, datetime, fastapi, sqlalchemy.dialects.postgresql, src.database, src.models, src.services.terminal.terminal_session, fastapi.WebSocket
- terminal_session.py | Manages a high-performance asyncio-native terminal session using PTY I/O with event-driven reads, output batching, and flow control for WebSocket delivery. | exp: class:TerminalSession, method:__init__(self, session_id: str, instance_id: uuid.UUID, container_id: str, startup_command, name) → None, call:deque, call:set, call:time.time, call:self._generate_name, call:str, call:bytearray, call:asyncio.Lock, method:start(self, startup_command) → None, call:pty.openpty, call:self._set_terminal_size, call:logger.debug, call:asyncio.create_subprocess_exec, call:os.close, call:time.time, call:self._start_reading, method:_start_reading(self) → None, call:asyncio.get_event_loop, call:loop.add_reader, call:logger.debug, call:logger.error, method:_stop_reading(self) → None, call:asyncio.get_event_loop, call:loop.remove_reader, method:_on_fd_readable(self) → None, call:os.read, call:logger.debug, call:self._handle_eof, call:self._add_to_buffer, call:time.time, call:self._queue_output, method:_add_to_buffer(self, data: bytes) → None, call:self._output_buffer.append, call:len, call:self._output_buffer.popleft, method:_queue_output(self, data: bytes) → None, call:self._batch_buffer.extend, call:len, call:self._pause_output, call:asyncio.get_event_loop, call:loop.call_later, method:_flush_batch_sync(self) → None, call:self._batch_buffer.clear, call:bytes, call:set, call:list, call:asyncio.create_task, call:self._send_bytes, call:dead_sockets.add, method:_send_bytes(self, ws: Any, payload: bytes) → None, call:ws.send_bytes, call:self._websockets.discard, method:acknowledge_data(self, char_count: int) → None, call:max, call:self._resume_output, call:self._ack_timeout_handle.cancel, call:asyncio.get_event_loop, call:loop.call_later, method:_ack_timeout_fallback(self) → None, call:logger.warning, call:self._resume_output, method:_pause_output(self) → None, call:self._stop_reading, call:logger.debug, method:_resume_output(self) → None, call:self._start_reading, call:logger.debug, method:get_buffer(self) → bytes, call:b"".join, method:_handle_eof(self) → None, call:self._stop_reading, call:self.process._transport.close, call:set, call:self._websockets.clear, call:asyncio.create_task, call:ws.close, call:logger.info, method:write_input(self, data: bytes) → None, call:os.write, call:time.time, call:logger.debug, call:self._handle_eof, method:_set_terminal_size(self, cols: int, rows: int) → None, call:logger.warning, call:struct.pack, call:fcntl.ioctl, call:logger.debug, call:logger.error, method:resize(self, cols: int, rows: int) → None, call:logger.warning, call:logger.debug, call:self._set_terminal_size, call:os.kill, method:reset(self) → None, call:self.close, call:self._output_buffer.clear, call:self._websockets.clear, call:self._batch_buffer.clear, method:close(self) → None, call:self._stop_reading, call:self._batch_timer.cancel, call:self._ack_timeout_handle.cancel, call:os.close, call:self.process.kill, call:asyncio.wait_for, call:self.process.wait, method:is_alive(self) → bool, method:is_idle(self) → bool, call:time.time, method:attach_websocket(self, websocket: Any) → None, call:self._websockets.add, call:time.time, method:detach_websocket(self, websocket: Any) → None, call:self._websockets.discard, method:has_websockets(self) → bool, call:len, method:send_to_all(self, data: bytes) → None, call:set, call:ws.send_bytes, call:dead_sockets.add, call:self._websockets.discard, method:read_output(self) → bytes | dep: asyncio, logging, os, pty, signal, struct, fcntl, time, uuid, collections, typing, collections.deque
- __init__.py | Package initialization file that exports the public API for the terminal services module | dep: src.services.terminal.terminal_manager, src.services.terminal.terminal_session
- terminal_manager.py | Manages active terminal sessions with WebSocket support, idle cleanup, database persistence, and per-instance session limits. | exp: class:MaxSessionsExceededError, method:__init__(self, instance_id: str, max_sessions) → None, call:super().__init__, class:TerminalManager, method:__init__(self) → None, call:self._start_idle_check, method:_start_idle_check(self) → None, call:self._idle_check_task.done, call:asyncio.get_running_loop, call:loop.create_task, call:self._idle_check_loop, method:_idle_check_loop(self) → None, call:asyncio.sleep, call:self._cleanup_idle_sessions, call:logger.error, method:_cleanup_idle_sessions(self) → None, call:list, call:self._sessions.items, call:session.is_idle, call:idle_keys.append, call:logger.info, call:self._sessions.pop, call:session.close, call:asyncio.create_task, call:self._mark_closed_in_db, method:_insert_db_session_row(self, session_id: str, instance_id: uuid.UUID, name: str) → None, call:SessionLocal, call:pg_insert(TerminalSessionModel) .values( id=uuid.UUID(session_id), instance_id=instance_id, name=name, status="active", created_at=datetime.now(timezone.utc), last_activity_at=datetime.now(timezone.utc), ) .on_conflict_do_nothing, call:uuid.UUID, call:datetime.now, call:db_session.execute, call:db_session.commit, call:logger.debug, call:logger.error, method:_mark_closed_in_db(self, session_id: str) → None, call:SessionLocal, call:db_session.get, call:uuid.UUID, call:datetime.now, call:db_session.commit, call:logger.debug, call:logger.error, method:_count_sessions_for_instance(self, instance_id_str: str) → int, call:sum, method:create_session(self, instance_id: uuid.UUID, container_id: str, startup_command, name, session_id) → TerminalSession, call:str, call:self._count_sessions_for_instance, call:uuid.uuid4, call:TerminalSession, call:session.start, call:asyncio.create_task, call:self._insert_db_session_row, call:logger.info, raise:MaxSessionsExceededError, method:get_or_create_session(self, instance_id: uuid.UUID, container_id: str, startup_command) → TerminalSession, call:self._start_idle_check, call:str, call:session.is_alive, call:logger.debug, call:session.close, call:logger.info, call:uuid.uuid4, call:TerminalSession, call:session.start, call:asyncio.create_task, call:self._insert_db_session_row, method:get_session(self, instance_id: str, session_id: str) → TerminalSession | None, call:self._sessions.get, call:self._sessions.items, method:_find_key_by_internal_id(self, instance_id: str, internal_session_id: str) → tuple[str, str] | None, call:self._sessions.items, method:get_sessions_for_instance(self, instance_id: str) → list[TerminalSession], call:self._sessions.items, method:close_session(self, instance_id: str, session_id: str) → None, call:self._sessions.pop, call:session.close, call:asyncio.create_task, call:self._mark_closed_in_db, call:logger.info, method:attach_websocket(self, session: TerminalSession, websocket: WebSocket) → None, call:session.has_websockets, call:logger.debug, call:list, call:ws.close, call:session._websockets.clear, call:session.attach_websocket, call:session.get_buffer, call:websocket.send_bytes, method:detach_websocket(self, session: TerminalSession, websocket: WebSocket) → None, call:session.detach_websocket, method:reset_session(self, instance_id: uuid.UUID, container_id: str, startup_command, session_id, name) → TerminalSession, call:str, call:logger.debug, call:self._sessions.pop, call:old_session.close, call:asyncio.create_task, call:self._mark_closed_in_db, call:uuid.uuid4, call:TerminalSession, call:new_session.start, call:self._insert_db_session_row, method:close_all(self) → None, call:list, call:self._sessions.values, call:self._sessions.clear, call:session.close, call:self._idle_check_task.done, call:self._idle_check_task.cancel | dep: asyncio, logging, uuid, datetime, fastapi, sqlalchemy.dialects.postgresql, src.database, src.models, src.services.terminal.terminal_session, fastapi.WebSocket
- terminal_session.py | Manages a high-performance terminal session using asyncio-native event-driven I/O with PTY for docker exec processes, featuring output batching, flow control, and WebSocket broadcasting. | exp: class:TerminalSession, method:__init__(self, session_id: str, instance_id: uuid.UUID, container_id: str, startup_command, name) → None, call:deque, call:set, call:time.time, call:self._generate_name, call:str, call:bytearray, call:asyncio.Lock, method:start(self, startup_command) → None, call:pty.openpty, call:self._set_terminal_size, call:logger.debug, call:asyncio.create_subprocess_exec, call:os.close, call:time.time, call:self._start_reading, method:_start_reading(self) → None, call:asyncio.get_event_loop, call:loop.add_reader, call:logger.debug, call:logger.error, method:_stop_reading(self) → None, call:asyncio.get_event_loop, call:loop.remove_reader, method:_on_fd_readable(self) → None, call:os.read, call:logger.debug, call:self._handle_eof, call:self._add_to_buffer, call:time.time, call:self._queue_output, method:_add_to_buffer(self, data: bytes) → None, call:self._output_buffer.append, call:len, call:self._output_buffer.popleft, method:_queue_output(self, data: bytes) → None, call:self._batch_buffer.extend, call:len, call:self._pause_output, call:asyncio.get_event_loop, call:loop.call_later, method:_flush_batch_sync(self) → None, call:self._batch_buffer.clear, call:bytes, call:set, call:list, call:asyncio.create_task, call:self._send_bytes, call:dead_sockets.add, method:_send_bytes(self, ws: Any, payload: bytes) → None, call:ws.send_bytes, call:self._websockets.discard, method:acknowledge_data(self, char_count: int) → None, call:max, call:self._resume_output, call:self._ack_timeout_handle.cancel, call:asyncio.get_event_loop, call:loop.call_later, method:_ack_timeout_fallback(self) → None, call:logger.warning, call:self._resume_output, method:_pause_output(self) → None, call:self._stop_reading, call:logger.debug, method:_resume_output(self) → None, call:self._start_reading, call:logger.debug, method:get_buffer(self) → bytes, call:b"".join, method:_handle_eof(self) → None, call:self._stop_reading, call:self.process._transport.close, call:set, call:self._websockets.clear, call:asyncio.create_task, call:ws.close, call:logger.info, method:write_input(self, data: bytes) → None, call:os.write, call:time.time, call:logger.debug, call:self._handle_eof, method:_set_terminal_size(self, cols: int, rows: int) → None, call:logger.warning, call:struct.pack, call:fcntl.ioctl, call:logger.debug, call:logger.error, method:resize(self, cols: int, rows: int) → None, call:logger.warning, call:logger.debug, call:self._set_terminal_size, call:os.kill, method:reset(self) → None, call:self.close, call:self._output_buffer.clear, call:self._websockets.clear, call:self._batch_buffer.clear, method:close(self) → None, call:self._stop_reading, call:self._batch_timer.cancel, call:self._ack_timeout_handle.cancel, call:os.close, call:self.process.kill, call:asyncio.wait_for, call:self.process.wait, method:is_alive(self) → bool, method:is_idle(self) → bool, call:time.time, method:attach_websocket(self, websocket: Any) → None, call:self._websockets.add, call:time.time, method:detach_websocket(self, websocket: Any) → None, call:self._websockets.discard, method:has_websockets(self) → bool, call:len, method:send_to_all(self, data: bytes) → None, call:set, call:ws.send_bytes, call:dead_sockets.add, call:self._websockets.discard, method:read_output(self) → bytes | dep: asyncio, logging, os, pty, signal, struct, fcntl, time, uuid, collections, typing, collections.deque, typing.Any
## arch
Asyncio-native event-driven architecture with session lifecycle management, resource cleanup, output batching/flow control, and database persistence for scalable terminal multiplexing.
Asyncio-native event-driven architecture with producer-consumer pattern for terminal output batching, WebSocket pub/sub broadcasting, session state machine with idle timeout and database persistence, and per-instance resource limits enforced by a centralized manager.
## tags
call:self., session, call:logger.debug, idle, output, terminal, check, task
## symbols
+2 -6
View File
@@ -2,14 +2,12 @@
dir: apps/api/src/services/tool
## role
Provides infrastructure orchestration for isolated tool instances, managing their complete lifecycle from provisioning to teardown.
Orchestrates Docker container lifecycle for tool instances, enabling isolated execution environments with git repository access and configurable runtime profiles.
## parent
index: apps/api/src/services/.pi-map.index.md
map: apps/api/src/services/.pi-map.md
## children
- apps/api/src/services/tool/.ruff_cache
index: apps/api/src/services/tool/.ruff_cache/.pi-map.index.md
map: apps/api/src/services/tool/.ruff_cache/.pi-map.md
-
## files
- instance_service.py
## links
@@ -18,7 +16,5 @@ map: apps/api/src/services/tool/.pi-map.md
## workflows
- change tool behavior
read: instance_service.py
- explore tool subdirectories
index: apps/api/src/services/tool/.ruff_cache/.pi-map.index.md
## dirty
-
File diff suppressed because one or more lines are too long
+1 -1
View File
@@ -2,7 +2,7 @@
dir: apps/api/src/utils
## role
Provides Git repository interaction utilities that wrap subprocess commands for URL parsing, file browsing, history extraction, and repository control operations.
Provides Git repository interaction utilities and URL parsing helpers for the API backend, enabling programmatic access to version control operations, file browsing, commit history analysis, and remote repository URL resolution.
## parent
index: apps/api/src/.pi-map.index.md
map: apps/api/src/.pi-map.md
+6 -6
View File
@@ -4,15 +4,15 @@ dir: apps/api/src/utils
index: apps/api/src/utils/.pi-map.index.md
## role
Provides Git repository interaction utilities that wrap subprocess commands for URL parsing, file browsing, history extraction, and repository control operations.
Provides Git repository interaction utilities and URL parsing helpers for the API backend, enabling programmatic access to version control operations, file browsing, commit history analysis, and remote repository URL resolution.
## files
- __init__.py | Empty file with no functionality
- __init__.py | Swaps two tmux panes between windows, preserving active pane state and layout | dep: tmux
- git_control.py | Provides a Python wrapper for common Git repository operations using subprocess calls | exp: class:GitStatus, func:_run_git_command(repo_path: str, *args: str) → str, call:subprocess.run, raise:RuntimeError, func:get_status(repo_path: str) → GitStatus, call:_run_git_command(repo_path, "rev-parse", "--abbrev-ref", "HEAD").strip, call:_run_git_command(repo_path, "symbolic-ref", "--short", "HEAD").strip, call:GitStatus, call:output.strip().split, call:line.startswith, call:branch_info.split("[ahead ")[1].split, call:int, call:ahead_str.split, call:branch_info.split("[behind ")[1].split, call:behind_str.split, call:len, call:status.untracked.append, call:status.added.append, call:status.deleted.append, call:status.renamed.append, call:status.modified.append, func:create_branch(repo_path: str, name: str, base_branch) → None, call:_run_git_command, call:str(e).lower, func:delete_branch(repo_path: str, name: str, force) → None, call:_run_git_command, func:checkout_branch(repo_path: str, name: str) → None, call:_run_git_command, call:str(e).lower, func:commit_changes(repo_path: str, message: str, author_name: str, author_email: str, files) → str, call:_run_git_command(repo_path, "rev-parse", "HEAD").strip, func:fetch(repo_path: str) → None, call:_run_git_command, func:pull(repo_path: str, branch) → None, call:args.append, call:_run_git_command, func:push(repo_path: str, branch) → None, call:args.extend, call:_run_git_command, func:merge(repo_path: str, source_branch: str, target_branch, message) → str, call:checkout_branch, call:args.extend, call:_run_git_command(repo_path, "rev-parse", "HEAD").strip, func:get_current_branch(repo_path: str) → str, call:_run_git_command(repo_path, "rev-parse", "--abbrev-ref", "HEAD").strip, call:_run_git_command(repo_path, "symbolic-ref", "--short", "HEAD").strip | dep: subprocess, dataclasses
- git_files.py | Provides utilities for browsing and manipulating Git repository contents including file trees, branches, file contents, and commits via subprocess git commands. | exp: class:FileTreeEntry, class:BranchInfo, class:FileContent, func:_run_git_command(repo_path: str, *args: str) → str, call:subprocess.run, call:stderr.lower, call:logger.warning, raise:RuntimeError, func:list_tree(repo_path: str, branch, path) → list[FileTreeEntry], call:_run_git_command, call:logger.warning, call:logger.error, call:str(e).lower, call:output.strip().split, call:line.split, call:len, call:meta.split, call:int, call:_get_last_commit_for_path, call:entries.append, call:FileTreeEntry, func:_get_last_commit_for_path(repo_path: str, branch: str, path: str) → dict[str, Any] | None, call:_run_git_command, call:output.strip().split, call:len, func:get_file_content(repo_path: str, branch: str, path: str) → FileContent, call:_run_git_command, call:int, call:size_output.strip, call:_is_binary_file, call:_detect_language, call:_get_last_commit_for_path, call:FileContent, raise:FileNotFoundError, func:_is_binary_file(repo_path: str, branch: str, path: str) → bool, call:subprocess.run, raise:RuntimeError, func:_detect_language(path: str) → str | None, call:Path(path).suffix.lower, call:language_map.get, func:list_branches(repo_path: str) → tuple[list[BranchInfo], str], call:_run_git_command, call:logger.error, call:str, call:r.strip, call:remote_output.strip().split, call:set, call:output.strip().split, call:line.strip, call:branch_name.split, call:branch_name.startswith, call:len, call:any, call:head_output.strip, call:_get_last_commit_for_path, call:branches.append, call:BranchInfo, func:commit_file(repo_path: str, branch: str, path: str, content: str, commit_message: str, author_name: str, author_email: str) → str, call:tempfile.TemporaryDirectory, call:os.path.join, call:os.makedirs, call:os.path.dirname, call:open, call:f.write, call:_run_git_command( worktree_path, "rev-parse", "HEAD", ).strip | dep: logging, subprocess, dataclasses, pathlib, typing, tempfile, os
- git_history.py | Extracts and structures git commit history, metadata, diffs, and graph visualization data from bare/mirror repositories using subprocess git commands. | exp: class:Commit, class:FileChange, class:CommitDetail, func:_run_git_command(repo_path: str, args: list[str]) → str, call:subprocess.run, raise:RuntimeError, func:get_commit_history(repo_path: str, branch, limit, offset) → dict[str, Any], call:_run_git_command, call:b.strip, call:branches_output.strip().split, call:log_args.append, call:_get_branch_map, call:_get_tag_map, call:log_output.strip().split, call:line.strip, call:line.split, call:len, call:parts[1].split, call:commits.append, call:Commit, call:int, call:branch_map.get, call:tag_map.get, call:count_output.strip, call:_build_graph_data, call:enumerate, call:min, call:commit_dicts.append, call:_commit_to_dict, func:get_commit_detail(repo_path: str, commit_hash: str) → dict[str, Any], call:_run_git_command, call:log_output.strip().split, call:len, call:parts[1].split, call:int, call:_parse_stats, call:_parse_diff, call:_get_branch_map, call:_get_tag_map, call:datetime.fromtimestamp(timestamp, tz=timezone.utc).isoformat, call:branch_map.get, call:tag_map.get, call:_file_change_to_dict, raise:ValueError, func:_get_branch_map(repo_path: str) → dict[str, list[str]], call:_run_git_command, call:branch_output.strip().split, call:line.split, call:result[commit_hash].append, func:_get_tag_map(repo_path: str) → dict[str, list[str]], call:_run_git_command, call:tag_output.strip().split, call:line.split, call:result[commit_hash].append, func:_build_graph_data(commits: list[Commit]) → dict[str, Any], call:enumerate, call:hash, call:nodes.append, call:edges.append, func:_parse_stats(stat_output: str) → dict[str, int], call:stat_output.strip().split, call:line.strip, call:line.split, call:part.strip, call:int, call:part.split, func:_parse_diff(diff_output: str) → list[FileChange], call:diff_output.split, call:line.startswith, call:"\n".join, call:files.append, call:FileChange, call:current_diff.append, func:_commit_to_dict(commit: Commit, graph_symbol, graph_depth) → dict[str, Any], call:refs.extend, call:datetime.fromtimestamp(commit.timestamp, tz=timezone.utc).isoformat, func:_file_change_to_dict(file_change: FileChange) → dict[str, Any] | dep: subprocess, dataclasses, datetime, typing
- git_url_parser.py | Parses various Git hosting service URLs (browser, SSH, HTTPS) to extract normalized base repository clone URLs with .git suffix. | exp: func:extract_base_repo_url(url: str) → str | None, call:url.startswith, call:url.endswith, call:urlparse, call:parsed.netloc.lower, call:parsed.path.split, call:_extract_github_url, call:_extract_gitlab_url, call:_extract_bitbucket_url, call:_extract_generic_url, func:_extract_github_url(url: str, path_parts: list[str]) → str | None, call:len, call:repo_name.endswith, func:_extract_gitlab_url(url: str, path_parts: list[str]) → str | None, call:len, call:repo_name.endswith, func:_extract_bitbucket_url(url: str, path_parts: list[str]) → str | None, call:len, call:repo_name.endswith, func:_extract_generic_url(url: str, path_parts: list[str]) → str | None, call:len, call:repo_name.endswith, call:urlparse, func:is_valid_clone_url(url: str) → bool, call:url.startswith, call:urlparse, call:path.endswith, func:parse_git_url(url: str) → dict, call:url.strip, call:urlparse, call:parsed.netloc.lower, call:url.startswith, call:url.split, call:len, call:parts[0].replace, call:is_valid_clone_url, call:extract_base_repo_url | dep: urllib.parse
- git_files.py | Provides utilities for browsing and manipulating Git repository contents including file trees, branches, file contents, and commits. | exp: class:FileTreeEntry, class:BranchInfo, class:FileContent, func:_run_git_command(repo_path: str, *args: str) → str, call:subprocess.run, call:stderr.lower, call:logger.warning, raise:RuntimeError, func:list_tree(repo_path: str, branch, path) → list[FileTreeEntry], call:_run_git_command, call:logger.warning, call:logger.error, call:str(e).lower, call:output.strip().split, call:line.split, call:len, call:meta.split, call:int, call:_get_last_commit_for_path, call:entries.append, call:FileTreeEntry, func:_get_last_commit_for_path(repo_path: str, branch: str, path: str) → dict[str, Any] | None, call:_run_git_command, call:output.strip().split, call:len, func:get_file_content(repo_path: str, branch: str, path: str) → FileContent, call:_run_git_command, call:int, call:size_output.strip, call:_is_binary_file, call:_detect_language, call:_get_last_commit_for_path, call:FileContent, raise:FileNotFoundError, func:_is_binary_file(repo_path: str, branch: str, path: str) → bool, call:subprocess.run, raise:RuntimeError, func:_detect_language(path: str) → str | None, call:Path(path).suffix.lower, call:language_map.get, func:list_branches(repo_path: str) → tuple[list[BranchInfo], str], call:_run_git_command, call:logger.error, call:str, call:r.strip, call:remote_output.strip().split, call:set, call:output.strip().split, call:line.strip, call:branch_name.split, call:branch_name.startswith, call:len, call:any, call:head_output.strip, call:_get_last_commit_for_path, call:branches.append, call:BranchInfo, func:commit_file(repo_path: str, branch: str, path: str, content: str, commit_message: str, author_name: str, author_email: str) → str, call:tempfile.TemporaryDirectory, call:os.path.join, call:os.makedirs, call:os.path.dirname, call:open, call:f.write, call:_run_git_command( worktree_path, "rev-parse", "HEAD", ).strip | dep: logging, subprocess, dataclasses, pathlib, typing, tempfile, os
- git_history.py | Extracts and parses Git commit history, diffs, and metadata from bare/mirror repositories into structured Python dataclasses/dictionaries. | exp: class:Commit, class:FileChange, class:CommitDetail, func:_run_git_command(repo_path: str, args: list[str]) → str, call:subprocess.run, raise:RuntimeError, func:get_commit_history(repo_path: str, branch, limit, offset) → dict[str, Any], call:_run_git_command, call:b.strip, call:branches_output.strip().split, call:log_args.append, call:_get_branch_map, call:_get_tag_map, call:log_output.strip().split, call:line.strip, call:line.split, call:len, call:parts[1].split, call:commits.append, call:Commit, call:int, call:branch_map.get, call:tag_map.get, call:count_output.strip, call:_build_graph_data, call:enumerate, call:min, call:commit_dicts.append, call:_commit_to_dict, func:get_commit_detail(repo_path: str, commit_hash: str) → dict[str, Any], call:_run_git_command, call:log_output.strip().split, call:len, call:parts[1].split, call:int, call:_parse_stats, call:_parse_diff, call:_get_branch_map, call:_get_tag_map, call:datetime.fromtimestamp(timestamp, tz=timezone.utc).isoformat, call:branch_map.get, call:tag_map.get, call:_file_change_to_dict, raise:ValueError, func:_get_branch_map(repo_path: str) → dict[str, list[str]], call:_run_git_command, call:branch_output.strip().split, call:line.split, call:result[commit_hash].append, func:_get_tag_map(repo_path: str) → dict[str, list[str]], call:_run_git_command, call:tag_output.strip().split, call:line.split, call:result[commit_hash].append, func:_build_graph_data(commits: list[Commit]) → dict[str, Any], call:enumerate, call:hash, call:nodes.append, call:edges.append, func:_parse_stats(stat_output: str) → dict[str, int], call:stat_output.strip().split, call:line.strip, call:line.split, call:part.strip, call:int, call:part.split, func:_parse_diff(diff_output: str) → list[FileChange], call:diff_output.split, call:line.startswith, call:"\n".join, call:files.append, call:FileChange, call:current_diff.append, func:_commit_to_dict(commit: Commit, graph_symbol, graph_depth) → dict[str, Any], call:refs.extend, call:datetime.fromtimestamp(commit.timestamp, tz=timezone.utc).isoformat, func:_file_change_to_dict(file_change: FileChange) → dict[str, Any] | dep: subprocess, dataclasses, datetime, typing
- git_url_parser.py | Parses browser URLs from GitHub, GitLab, and Bitbucket to extract canonical git clone URLs, with validation and detailed result reporting. | exp: func:extract_base_repo_url(url: str) → str | None, call:url.startswith, call:url.endswith, call:urlparse, call:parsed.netloc.lower, call:parsed.path.split, call:_extract_github_url, call:_extract_gitlab_url, call:_extract_bitbucket_url, call:_extract_generic_url, func:_extract_github_url(url: str, path_parts: list[str]) → str | None, call:len, call:repo_name.endswith, func:_extract_gitlab_url(url: str, path_parts: list[str]) → str | None, call:len, call:repo_name.endswith, func:_extract_bitbucket_url(url: str, path_parts: list[str]) → str | None, call:len, call:repo_name.endswith, func:_extract_generic_url(url: str, path_parts: list[str]) → str | None, call:len, call:repo_name.endswith, call:urlparse, func:is_valid_clone_url(url: str) → bool, call:url.startswith, call:urlparse, call:path.endswith, func:parse_git_url(url: str) → dict, call:url.strip, call:urlparse, call:parsed.netloc.lower, call:url.startswith, call:url.split, call:len, call:parts[0].replace, call:is_valid_clone_url, call:extract_base_repo_url | dep: urllib.parse
## arch
Facade pattern with subprocess-based adapters, where each module encapsulates a distinct Git domain (control, files, history, URLs) behind Pythonic function interfaces.
Collection of utility modules following a functional/service-oriented pattern with subprocess-based Git CLI wrappers, dataclass-based structured data extraction, and parser combinators for URL handling; each module specializes in a distinct Git operation domain (control, files, history, URLs) with no apparent shared abstractions or base classes.
## tags
call:, git, run, command, get, url, commit, call:len
## symbols