# tenchi
AppError (re-export of tenchi.errors.AppError)
Client (re-export of tenchi.client.Client)
ClientAttemptObserver = collections.abc.Callable[[tenchi.client.ClientAttemptOutcome], typing.Any]
ClientAttemptOutcome (re-export of tenchi.client.ClientAttemptOutcome)
ClientObserver = collections.abc.Callable[[tenchi.client.ClientOutcome], typing.Any]
ClientOutcome (re-export of tenchi.client.ClientOutcome)
ClientResponse (re-export of tenchi.client.ClientResponse)
ConfigurationError (re-export of tenchi.errors.ConfigurationError)
Contract (re-export of tenchi.contracts.Contract)
ErrorDef (re-export of tenchi.errors.ErrorDef)
ExecutionError (re-export of tenchi.execution.ExecutionError)
IDEMPOTENCY_CONFLICT = ErrorDef(code='IDEMPOTENCY_CONFLICT', status=409, message='The idempotency key was already used with different input', headers=())
IDEMPOTENCY_IN_PROGRESS = ErrorDef(code='IDEMPOTENCY_IN_PROGRESS', status=409, message='An operation with this idempotency key is already in progress', headers=('Retry-After',))
IdempotencyResultError (re-export of tenchi.idempotency.IdempotencyResultError)
IdempotencyStore (re-export of tenchi.idempotency.IdempotencyStore)
IdempotencyStoreError (re-export of tenchi.idempotency.IdempotencyStoreError)
Job (re-export of tenchi.jobs.Job)
JobBindingError (re-export of tenchi.jobs.JobBindingError)
JobDispatcher (re-export of tenchi.jobs.JobDispatcher)
JobGroup (re-export of tenchi.jobs.JobGroup)
JobHandler (re-export of tenchi.jobs.JobHandler)
JobMessage (re-export of tenchi.jobs.JobMessage)
JobNotFoundError (re-export of tenchi.jobs.JobNotFoundError)
JobResultError (re-export of tenchi.jobs.JobResultError)
MemoryIdempotencyStore (re-export of tenchi.idempotency.MemoryIdempotencyStore)
MemoryRateLimitStore (re-export of tenchi.rate_limits.MemoryRateLimitStore)
OutcomeObserver = collections.abc.Callable[[tenchi.server.RequestOutcome], typing.Any]
Page (re-export of tenchi.pagination.Page)
PageQuery (re-export of tenchi.pagination.PageQuery)
PreflightBindingError (re-export of tenchi.preflight.PreflightBindingError)
PreflightCheck (re-export of tenchi.preflight.PreflightCheck)
PreflightGroup (re-export of tenchi.preflight.PreflightGroup)
PreflightOutcome (re-export of tenchi.preflight.PreflightOutcome)
PreflightReport (re-export of tenchi.preflight.PreflightReport)
PreflightStatus = PreflightStatus
PresentedResponse (re-export of tenchi.responses.PresentedResponse)
RATE_LIMITED = ErrorDef(code='RATE_LIMITED', status=429, message='Too many requests', headers=('Retry-After',))
RateLimitExceeded (re-export of tenchi.rate_limits.RateLimitExceeded)
RateLimitPermit (re-export of tenchi.rate_limits.RateLimitPermit)
RateLimitStore (re-export of tenchi.rate_limits.RateLimitStore)
RateLimitStoreError (re-export of tenchi.rate_limits.RateLimitStoreError)
RequestInfo (re-export of tenchi.server.RequestInfo)
RequestOutcome (re-export of tenchi.server.RequestOutcome)
ResponseDef (re-export of tenchi.responses.ResponseDef)
RetryPolicy (re-export of tenchi.retries.RetryPolicy)
RetryTimeoutError (re-export of tenchi.retries.RetryTimeoutError)
Route (re-export of tenchi.routes.Route)
RouteGroup (re-export of tenchi.routes.RouteGroup)
TOOL_MANIFEST_VERSION = 1
Task (re-export of tenchi.tasks.Task)
TaskBindingError (re-export of tenchi.tasks.TaskBindingError)
TaskGroup (re-export of tenchi.tasks.TaskGroup)
TaskNotFoundError (re-export of tenchi.tasks.TaskNotFoundError)
TaskResultError (re-export of tenchi.tasks.TaskResultError)
TaskRunner (re-export of tenchi.tasks.TaskRunner)
TenchiError (re-export of tenchi.errors.TenchiError)
Tool (re-export of tenchi.tools.Tool)
ToolBinding (re-export of tenchi.tools.ToolBinding)
ToolBindingError (re-export of tenchi.tools.ToolBindingError)
ToolGroup (re-export of tenchi.tools.ToolGroup)
ToolInvocationError (re-export of tenchi.tools.ToolInvocationError)
ToolNotFoundError (re-export of tenchi.tools.ToolNotFoundError)
ToolResultError (re-export of tenchi.tools.ToolResultError)
ToolRunner (re-export of tenchi.tools.ToolRunner)
UnexpectedResponseError (re-export of tenchi.client.UnexpectedResponseError)
UseCaseObserver = collections.abc.Callable[[tenchi.execution.UseCaseOutcome], typing.Any]
UseCaseOutcome (re-export of tenchi.execution.UseCaseOutcome)
Webhook (re-export of tenchi.webhooks.Webhook)
WebhookBindingError (re-export of tenchi.webhooks.WebhookBindingError)
WebhookRequest (re-export of tenchi.webhooks.WebhookRequest)
WebhookVerifier = collections.abc.Callable[['WebhookRequest', typing.Any], typing.Any]
contract (re-export of tenchi.contracts.contract)
create_app (re-export of tenchi.server.create_app)
create_job_dispatcher (re-export of tenchi.jobs.create_job_dispatcher)
create_task_runner (re-export of tenchi.tasks.create_task_runner)
create_tool_runner (re-export of tenchi.tools.create_tool_runner)
enforce_rate_limit (re-export of tenchi.rate_limits.enforce_rate_limit)
execute (re-export of tenchi.execution.execute)
fingerprint (re-export of tenchi.idempotency.fingerprint)
health_route (re-export of tenchi.health.health_route)
job (re-export of tenchi.jobs.job)
job_group (re-export of tenchi.jobs.job_group)
job_handler (re-export of tenchi.jobs.job_handler)
job_message (re-export of tenchi.jobs.job_message)
openapi_route (re-export of tenchi.openapi.openapi_route)
openapi_schema (re-export of tenchi.openapi.openapi_schema)
page (re-export of tenchi.pagination.page)
preflight_check (re-export of tenchi.preflight.preflight_check)
preflight_group (re-export of tenchi.preflight.preflight_group)
present (re-export of tenchi.responses.present)
response (re-export of tenchi.responses.response)
retry_policy (re-export of tenchi.retries.retry_policy)
route (re-export of tenchi.routes.route)
route_group (re-export of tenchi.routes.route_group)
run_idempotently (re-export of tenchi.idempotency.run_idempotently)
run_preflight (re-export of tenchi.preflight.run_preflight)
swagger_ui_route (re-export of tenchi.openapi.swagger_ui_route)
task (re-export of tenchi.tasks.task)
task_group (re-export of tenchi.tasks.task_group)
tool (re-export of tenchi.tools.tool)
tool_group (re-export of tenchi.tools.tool_group)
tool_handler (re-export of tenchi.tools.tool_handler)
tool_manifest (re-export of tenchi.tools.tool_manifest)
webhook (re-export of tenchi.webhooks.webhook)

# tenchi.client
class Client
    def __init__(self, *, base_url: 'str | None' = None, headers: 'Mapping[str, str] | None' = None, transport: 'httpx.AsyncBaseTransport | None' = None, http: 'httpx.AsyncClient | None' = None, errors: 'Sequence[ErrorDef]' = (), observers: 'Sequence[ClientObserver]' = (), attempt_observers: 'Sequence[ClientAttemptObserver]' = ()) -> 'None'
    def aclose(self) -> 'None'
    def call(self, contract: 'Contract[ResponseT, ResponseHeadersT]', *, params: 'Any' = None, query: 'Any' = None, headers: 'Any' = None, request: 'Any' = UNSET, retry: 'RetryPolicy | None' = None) -> 'ResponseT'
    def call_with_response(self, contract: 'Contract[ResponseT, ResponseHeadersT]', *, params: 'Any' = None, query: 'Any' = None, headers: 'Any' = None, request: 'Any' = UNSET, retry: 'RetryPolicy | None' = None) -> 'ClientResponse[ResponseT, ResponseHeadersT]'
ClientAttemptObserver = collections.abc.Callable[[tenchi.client.ClientAttemptOutcome], typing.Any]
class ClientAttemptOutcome
    contract: Contract[Any, Any]
    attempt: int
    max_attempts: int
    status: Literal['succeeded', 'app_error', 'unexpected_response', 'transport_error', 'timed_out', 'failed', 'cancelled']
    status_code: int | None
    duration_seconds: float
    error_code: str | None = None
    will_retry: bool = False
    retry_delay_seconds: float | None = None
    completed_at: datetime = <factory>
    def __init__(self, contract: 'Contract[Any, Any]', attempt: 'int', max_attempts: 'int', status: "Literal['succeeded', 'app_error', 'unexpected_response', 'transport_error', 'timed_out', 'failed', 'cancelled']", status_code: 'int | None', duration_seconds: 'float', error_code: 'str | None' = None, will_retry: 'bool' = False, retry_delay_seconds: 'float | None' = None, completed_at: 'datetime' = <factory>) -> None
ClientObserver = collections.abc.Callable[[tenchi.client.ClientOutcome], typing.Any]
class ClientOutcome
    contract: Contract[Any, Any]
    status: Literal['succeeded', 'app_error', 'unexpected_response', 'transport_error', 'timed_out', 'failed', 'cancelled']
    status_code: int | None
    duration_seconds: float
    error_code: str | None = None
    attempts: int = 1
    completed_at: datetime = <factory>
    def __init__(self, contract: 'Contract[Any, Any]', status: "Literal['succeeded', 'app_error', 'unexpected_response', 'transport_error', 'timed_out', 'failed', 'cancelled']", status_code: 'int | None', duration_seconds: 'float', error_code: 'str | None' = None, attempts: 'int' = 1, completed_at: 'datetime' = <factory>) -> None
class ClientResponse(Generic)
    body: BodyT
    headers: HeadersT
    http_response: httpx.Response
    definition: ResponseDef[Any, Any] | None = None
    def __init__(self, body: 'BodyT', headers: 'HeadersT', http_response: 'httpx.Response', definition: 'ResponseDef[Any, Any] | None' = None) -> None
class UnexpectedResponseError(TenchiError)
    def __init__(self, *, contract_name: 'str', status_code: 'int', body: 'Any', reason: 'str | None' = None) -> 'None'

# tenchi.compatibility
class CompatibilityChange
    severity: ChangeSeverity
    location: str
    message: str
    def __init__(self, severity: 'ChangeSeverity', location: 'str', message: 'str') -> None
class CompatibilityReport
    changes: tuple[CompatibilityChange, ...]
    def __init__(self, changes: 'tuple[CompatibilityChange, ...]') -> None
    def as_dict(self) -> 'dict[str, object]'
    property compatible(self) -> 'bool'
    def count(self, severity: 'ChangeSeverity') -> 'int'
    property status(self) -> 'CompatibilityStatus'
def analyze_openapi_compatibility(baseline: 'object', current: 'object') -> 'CompatibilityReport'
def render_compatibility_report(report: 'CompatibilityReport', *, baseline_path: 'str') -> 'str'

# tenchi.contracts
class Contract(Generic)
    method: str
    path: str
    request: type[Any] | UnionType | None = None
    params: type[Any] | UnionType | None = None
    query: type[Any] | UnionType | None = None
    headers: type[Any] | UnionType | None = None
    response: type[ResponseT] | UnionType | None = None
    response_headers: type[ResponseHeadersT] | UnionType | None = None
    status: int = 200
    errors: tuple[ErrorDef, ...] = ()
    name: str = ''
    request_media_type: str = 'application/json'
    response_media_type: str = 'application/json'
    summary: str | None = None
    description: str | None = None
    tags: tuple[str, ...] = ()
    public: bool = False
    webhook: bool = False
    deprecated: bool | datetime = False
    sunset: datetime | None = None
    max_request_bytes: int | None = None
    responses: tuple[ResponseDef[Any, Any], ...] = ()
    timeout: float | None = None
    def __init__(self, method: 'str', path: 'str', request: 'type[Any] | UnionType | None' = None, params: 'type[Any] | UnionType | None' = None, query: 'type[Any] | UnionType | None' = None, headers: 'type[Any] | UnionType | None' = None, response: 'type[ResponseT] | UnionType | None' = None, response_headers: 'type[ResponseHeadersT] | UnionType | None' = None, status: 'int' = 200, errors: 'tuple[ErrorDef, ...]' = (), name: 'str' = '', request_media_type: 'str' = 'application/json', response_media_type: 'str' = 'application/json', summary: 'str | None' = None, description: 'str | None' = None, tags: 'tuple[str, ...]' = (), public: 'bool' = False, webhook: 'bool' = False, deprecated: 'bool | datetime' = False, sunset: 'datetime | None' = None, max_request_bytes: 'int | None' = None, responses: 'tuple[ResponseDef[Any, Any], ...]' = (), timeout: 'float | None' = None) -> None
    def declares_error(self, definition: 'ErrorDef') -> 'bool'
def contract(*, method: 'str', path: 'str', request: 'type[Any] | UnionType | None' = None, params: 'type[Any] | UnionType | None' = None, query: 'type[Any] | UnionType | None' = None, headers: 'type[Any] | UnionType | None' = None, response: 'type[ResponseT] | UnionType | None' = None, response_headers: 'type[ResponseHeadersT] | UnionType | None' = None, status: 'int' = 200, errors: 'Sequence[ErrorDef]' = (), name: 'str | None' = None, request_media_type: 'str' = 'application/json', response_media_type: 'str' = 'application/json', summary: 'str | None' = None, description: 'str | None' = None, tags: 'Sequence[str]' = (), public: 'bool' = False, webhook: 'bool' = False, deprecated: 'bool | datetime' = False, sunset: 'datetime | None' = None, max_request_bytes: 'int | None' = None, responses: 'Sequence[ResponseDef[Any, Any]]' = (), timeout: 'float | None' = None) -> 'Contract[ResponseT, ResponseHeadersT]'

# tenchi.errors
class AppError(TenchiError)
    def __init__(self, definition: 'ErrorDef', *, message: 'str | None' = None, details: 'Any' = None, headers: 'Mapping[str, str] | None' = None) -> 'None'
    property code(self) -> 'str'
    property message(self) -> 'str'
    property status(self) -> 'int'
class ConfigurationError(TenchiError, ValueError)
ERROR_SOURCE_HEADER = 'x-tenchi-error-source'
class ErrorDef
    code: str
    status: int
    message: str
    headers: tuple[str, ...] = ()
    def __init__(self, code: 'str', status: 'int', message: 'str', headers: 'tuple[str, ...]' = ()) -> None
REQUEST_ID_HEADER = 'x-request-id'
class TenchiError(Exception)
def error_body(*, code: 'str', message: 'str', details: 'Any' = None, request_id: 'str | None' = None) -> 'dict[str, Any]'

# tenchi.execution
class ExecutionError(TenchiError, TypeError)
UseCaseObserver = collections.abc.Callable[[tenchi.execution.UseCaseOutcome], typing.Any]
class UseCaseOutcome
    use_case: Callable[..., Awaitable[Any]]
    entrypoint: Literal['http', 'execute', 'job', 'task', 'tool']
    status: Literal['succeeded', 'app_error', 'failed', 'cancelled']
    duration_seconds: float
    error_code: str | None = None
    completed_at: datetime = <factory>
    def __init__(self, use_case: 'Callable[..., Awaitable[Any]]', entrypoint: "Literal['http', 'execute', 'job', 'task', 'tool']", status: "Literal['succeeded', 'app_error', 'failed', 'cancelled']", duration_seconds: 'float', error_code: 'str | None' = None, completed_at: 'datetime' = <factory>) -> None
def execute(use_case: 'Callable[..., Awaitable[ResultT]]', *, context: 'Any', request: 'Any' = UNSET, request_json: 'bytes | str | None' = None, use_case_observers: 'Sequence[UseCaseObserver]' = ()) -> 'ResultT'
def open_context(source: 'Any') -> 'AsyncGenerator[Any]'

# tenchi.health
HealthCheck = collections.abc.Callable[[typing.Any], typing.Any]
class HealthReport(BaseModel)
    status: str = 'ok'
    checks: dict[str, str] = {}
def health_route(*, path: 'str' = '/health', checks: 'Mapping[str, HealthCheck] | None' = None, check_timeout: 'float' = 5.0, public: 'bool' = True) -> 'Route'

# tenchi.idempotency
IDEMPOTENCY_CONFLICT = ErrorDef(code='IDEMPOTENCY_CONFLICT', status=409, message='The idempotency key was already used with different input', headers=())
IDEMPOTENCY_IN_PROGRESS = ErrorDef(code='IDEMPOTENCY_IN_PROGRESS', status=409, message='An operation with this idempotency key is already in progress', headers=('Retry-After',))
class IdempotencyConflict
    def __init__(self) -> None
IdempotencyDecision = IdempotencyDecision
class IdempotencyInProgress
    retry_after_seconds: int | None = None
    def __init__(self, retry_after_seconds: 'int | None' = None) -> None
class IdempotencyReplay
    result_json: bytes
    def __init__(self, result_json: 'bytes') -> None
class IdempotencyReservation
    namespace: str
    scope: str
    key: str
    fingerprint: str
    token: str
    completed_ttl: float | None
    def __init__(self, namespace: 'str', scope: 'str', key: 'str', fingerprint: 'str', token: 'str', completed_ttl: 'float | None') -> None
class IdempotencyResultError(TenchiError, TypeError)
class IdempotencyStore(Protocol)
    def __init__(self, *args, **kwargs)
    def abandon(self, reservation: 'IdempotencyReservation') -> 'None'
    def complete(self, reservation: 'IdempotencyReservation', *, result_json: 'bytes') -> 'None'
    def reserve(self, *, namespace: 'str', scope: 'str', key: 'str', fingerprint: 'str', completed_ttl: 'float | None', reservation_ttl: 'float') -> 'IdempotencyDecision'
class IdempotencyStoreError(TenchiError, RuntimeError)
class MemoryIdempotencyStore
    def __init__(self, *, clock: 'Callable[[], float]' = <built-in function monotonic>) -> 'None'
    def abandon(self, reservation: 'IdempotencyReservation') -> 'None'
    def complete(self, reservation: 'IdempotencyReservation', *, result_json: 'bytes') -> 'None'
    def reserve(self, *, namespace: 'str', scope: 'str', key: 'str', fingerprint: 'str', completed_ttl: 'float | None', reservation_ttl: 'float') -> 'IdempotencyDecision'
def fingerprint(value: 'Any', *, annotation: 'Any' = UNSET) -> 'str'
def run_idempotently(store: 'IdempotencyStore', *, namespace: 'str', scope: 'str', key: 'str', fingerprint: 'str', result_type: 'Any', operation: 'Callable[[], Awaitable[ResultT]]', completed_ttl: 'float | None' = None, reservation_ttl: 'float' = 300.0) -> 'ResultT'

# tenchi.jobs
class Job(Generic)
    name: str
    description: str | None
    request: Any
    result: Any
    def __init__(self, name: 'str', description: 'str | None', request: 'Any', result: 'Any') -> None
class JobBindingError(ConfigurationError, TypeError)
class JobDispatcher
    jobs: JobGroup
    use_case_observers: tuple[UseCaseObserver, ...] = ()
    def __init__(self, jobs: 'JobGroup', use_case_observers: 'tuple[UseCaseObserver, ...]' = ()) -> None
    def dispatch(self, name: 'str', *, payload_json: 'bytes | str', context: 'Any') -> 'Any'
class JobGroup
    handlers: tuple[JobHandler[Any, Any], ...]
    def __init__(self, handlers: 'tuple[JobHandler[Any, Any], ...]') -> None
class JobHandler(Generic)
    job: Job[RequestT, ResultT]
    use_case: Callable[..., Awaitable[ResultT]]
    def __init__(self, job: 'Job[RequestT, ResultT]', use_case: 'Callable[..., Awaitable[ResultT]]') -> None
class JobMessage
    name: str
    payload_json: bytes
    def __init__(self, name: 'str', payload_json: 'bytes') -> None
class JobNotFoundError(TenchiError, LookupError)
class JobResultError(TenchiError, TypeError)
def create_job_dispatcher(*, jobs: 'JobGroup', use_case_observers: 'Sequence[UseCaseObserver]' = ()) -> 'JobDispatcher'
def job(name: 'str', *, request: 'type[Any] | UnionType', result: 'type[Any] | UnionType | None', description: 'str | None' = None) -> 'Job[Any, Any]'
def job_group(*items: 'JobHandler[Any, Any] | JobGroup | Sequence[JobHandler[Any, Any]]') -> 'JobGroup'
def job_handler(declaration: 'Job[RequestT, ResultT]', use_case: 'Callable[..., Awaitable[ResultT]]') -> 'JobHandler[RequestT, ResultT]'
def job_message(declaration: 'Job[RequestT, ResultT]', request: 'RequestT') -> 'JobMessage'

# tenchi.mcp
class McpRequest
    request_id: str | int | None
    transport_request: Request | None
    def __init__(self, request_id: 'str | int | None', transport_request: 'Request | None') -> None
TOOL_MCP_PROTOCOL_VERSION = 1
def create_tool_mcp_server(*, tools: 'ToolGroup', authenticate: 'Callable[[McpRequest], PrincipalT | Awaitable[PrincipalT]]', runner_factory: 'Callable[[PrincipalT], ToolRunner | Awaitable[ToolRunner]]', allow_tool: 'Callable[[PrincipalT, Tool[Any, Any]], bool | Awaitable[bool]] | None' = None, approve: 'Callable[[PrincipalT, Tool[Any, Any], object], bool | Awaitable[bool]] | None' = None, name: 'str' = 'Tenchi application', instructions: 'str | None' = None, website_url: 'str | None' = None, transport_security: 'TransportSecuritySettings | None' = None) -> 'FastMCP[None]'

# tenchi.openapi
def openapi_route(routes: 'RouteGroup', *, title: 'str', version: 'str', description: 'str | None' = None, security: 'Mapping[str, Mapping[str, Any]] | None' = None, path: 'str' = '/openapi.json', tags: 'Sequence[str]' = ('docs',), public: 'bool' = True) -> 'Route'
def openapi_schema(routes: 'RouteGroup', *, title: 'str', version: 'str', description: 'str | None' = None, security: 'Mapping[str, Mapping[str, Any]] | None' = None) -> 'dict[str, Any]'
def swagger_ui_route(*, openapi_path: 'str' = '/openapi.json', path: 'str' = '/docs', title: 'str' = 'API Documentation', public: 'bool' = True, swagger_js_url: 'str' = 'https://unpkg.com/swagger-ui-dist@5.32.9/swagger-ui-bundle.js', swagger_css_url: 'str' = 'https://unpkg.com/swagger-ui-dist@5.32.9/swagger-ui.css', swagger_favicon_url: 'str | None' = None) -> 'Route'

# tenchi.opentelemetry
class OpenTelemetryObservers
    request: OutcomeObserver
    use_case: UseCaseObserver
    client: ClientObserver
    client_attempt: ClientAttemptObserver
    def __init__(self, request: 'OutcomeObserver', use_case: 'UseCaseObserver', client: 'ClientObserver', client_attempt: 'ClientAttemptObserver') -> None
def create_opentelemetry_observers(*, tracer_provider: 'TracerProvider | None' = None, meter_provider: 'MeterProvider | None' = None) -> 'OpenTelemetryObservers'

# tenchi.pagination
class Page(BaseModel, Generic)
    items: list[ItemT]
    total: int
    limit: int
    offset: int
class PageQuery(BaseModel)
    limit: int = 20
    offset: int = 0
def page(items: collections.abc.Sequence[ItemT], *, total: int, query: tenchi.pagination.PageQuery) -> tenchi.pagination.Page[TypeVar]

# tenchi.preflight
class PreflightBindingError(ConfigurationError, TypeError)
class PreflightCheck
    name: str
    check: Callable[[], Awaitable[None]]
    description: str | None
    timeout: float
    failure_code: str
    def __init__(self, name: 'str', check: 'Callable[[], Awaitable[None]]', description: 'str | None', timeout: 'float', failure_code: 'str') -> None
class PreflightGroup
    checks: tuple[PreflightCheck, ...]
    def __init__(self, checks: 'tuple[PreflightCheck, ...]') -> None
class PreflightOutcome
    name: str
    description: str | None
    status: PreflightStatus
    duration_seconds: float
    failure_code: str | None = None
    def __init__(self, name: 'str', description: 'str | None', status: 'PreflightStatus', duration_seconds: 'float', failure_code: 'str | None' = None) -> None
class PreflightReport
    outcomes: tuple[PreflightOutcome, ...]
    duration_seconds: float
    def __init__(self, outcomes: 'tuple[PreflightOutcome, ...]', duration_seconds: 'float') -> None
    property ok(self) -> 'bool'
PreflightStatus = PreflightStatus
def preflight_check(name: 'str', check: 'Callable[[], Awaitable[None]]', *, description: 'str | None' = None, timeout: 'float' = 5.0, failure_code: 'str | None' = None) -> 'PreflightCheck'
def preflight_group(*items: 'PreflightCheck | PreflightGroup | Sequence[PreflightCheck]') -> 'PreflightGroup'
def run_preflight(group: 'PreflightGroup', *, timeout: 'float | None' = None) -> 'PreflightReport'

# tenchi.rate_limits
class MemoryRateLimitStore
    def __init__(self, *, clock: 'Callable[[], float]' = <built-in function monotonic>) -> 'None'
    def consume(self, *, namespace: 'str', scope: 'str', limit: 'int', window_seconds: 'float', cost: 'int') -> 'RateLimitDecision'
RATE_LIMITED = ErrorDef(code='RATE_LIMITED', status=429, message='Too many requests', headers=('Retry-After',))
RateLimitDecision = RateLimitDecision
class RateLimitExceeded
    limit: int
    retry_after_seconds: int
    def __init__(self, limit: 'int', retry_after_seconds: 'int') -> None
class RateLimitPermit
    limit: int
    remaining: int
    reset_after_seconds: float
    def __init__(self, limit: 'int', remaining: 'int', reset_after_seconds: 'float') -> None
class RateLimitStore(Protocol)
    def __init__(self, *args, **kwargs)
    def consume(self, *, namespace: 'str', scope: 'str', limit: 'int', window_seconds: 'float', cost: 'int') -> 'RateLimitDecision'
class RateLimitStoreError(TenchiError, RuntimeError)
def enforce_rate_limit(store: 'RateLimitStore', *, namespace: 'str', scope: 'str', limit: 'int', window_seconds: 'float', cost: 'int' = 1) -> 'RateLimitPermit'

# tenchi.routes
class Route
    contract: Contract[Any, Any]
    use_case: UseCase
    call_kwargs: tuple[str, ...]
    response_headers: Callable[[Any], Any] | None = None
    presenter: Callable[[Any], PresentedResponse] | None = None
    def __init__(self, contract: 'Contract[Any, Any]', use_case: 'UseCase', call_kwargs: 'tuple[str, ...]', response_headers: 'Callable[[Any], Any] | None' = None, presenter: 'Callable[[Any], PresentedResponse] | None' = None) -> None
class RouteBindingError(ConfigurationError, TypeError)
class RouteGroup
    routes: tuple[Route, ...]
    def __init__(self, routes: 'tuple[Route, ...]') -> None
UseCase = collections.abc.Callable[..., collections.abc.Awaitable[typing.Any]]
def route(contract: 'Contract[Any, Any]', use_case: 'UseCase', *, response_headers: 'Callable[[Any], Any] | None' = None, present: 'Callable[[Any], PresentedResponse] | None' = None) -> 'Route'
def route_group(*items: 'Route | RouteGroup | Sequence[Route]', prefix: 'str' = '', errors: 'Sequence[ErrorDef]' = ()) -> 'RouteGroup'

# tenchi.responses
class PresentedResponse
    definition: ResponseDef[Any, Any]
    body: Any = UNSET
    headers: Any = UNSET
    response: Response | None = None
    def __init__(self, definition: 'ResponseDef[Any, Any]', body: 'Any' = UNSET, headers: 'Any' = UNSET, response: 'Response | None' = None) -> None
class ResponseDef(Generic)
    body: type[BodyT] | UnionType | None
    status: int
    headers: type[HeadersT] | None = None
    media_type: str | None = 'application/json'
    description: str = 'Successful response'
    passthrough: bool = False
    def __init__(self, body: 'type[BodyT] | UnionType | None', status: 'int', headers: 'type[HeadersT] | None' = None, media_type: 'str | None' = 'application/json', description: 'str' = 'Successful response', passthrough: 'bool' = False) -> None
def present(definition: 'ResponseDef[Any, Any]', body: 'Any' = UNSET, /, *, headers: 'Any' = UNSET, response: 'Response | None' = None) -> 'PresentedResponse'
def response(body: 'type[Any] | UnionType | None', /, *body_alternatives: 'type[Any]', status: 'int', headers: 'type[Any] | None' = None, media_type: 'str | None' = 'application/json', description: 'str' = 'Successful response', passthrough: 'bool' = False) -> 'ResponseDef[Any, Any]'

# tenchi.retries
class RetryPolicy
    max_attempts: int = 3
    retry_on: tuple[str, ...] = ()
    retry_transport_errors: bool = True
    base_delay_seconds: float = 0.1
    max_delay_seconds: float = 5.0
    jitter: float = 0.2
    total_timeout_seconds: float | None = None
    allow_unsafe_methods: bool = False
    def __init__(self, *, max_attempts: 'int' = 3, retry_on: 'tuple[str, ...]' = (), retry_transport_errors: 'bool' = True, base_delay_seconds: 'float' = 0.1, max_delay_seconds: 'float' = 5.0, jitter: 'float' = 0.2, total_timeout_seconds: 'float | None' = None, allow_unsafe_methods: 'bool' = False) -> None
class RetryTimeoutError(TenchiError, TimeoutError)
    def __init__(self, *, contract_name: 'str', attempts: 'int') -> 'None'
def retry_policy(*, max_attempts: 'int' = 3, retry_on: 'Sequence[str]' = (), retry_transport_errors: 'bool' = True, base_delay_seconds: 'float' = 0.1, max_delay_seconds: 'float' = 5.0, jitter: 'float' = 0.2, total_timeout_seconds: 'float | None' = None, allow_unsafe_methods: 'bool' = False) -> 'RetryPolicy'

# tenchi.server
ContextFactory = collections.abc.Callable[..., typing.Any]
DEFAULT_MAX_REQUEST_BYTES = 1048576
ERROR_SOURCE_HEADER = 'x-tenchi-error-source'
Hook = collections.abc.Callable[[tenchi.server.RequestInfo, typing.Any], typing.Any]
Lifespan = collections.abc.Callable[[], contextlib.AbstractAsyncContextManager[typing.Any]]
OutcomeObserver = collections.abc.Callable[[tenchi.server.RequestOutcome], typing.Any]
REQUEST_ID_HEADER = 'x-request-id'
class RequestInfo
    method: str
    path: str
    headers: Mapping[str, str]
    contract: Contract[Any, Any]
    request_id: str
    def __init__(self, method: 'str', path: 'str', headers: 'Mapping[str, str]', contract: 'Contract[Any, Any]', request_id: 'str') -> None
class RequestOutcome
    request: RequestInfo
    status_code: int
    duration_seconds: float
    error_source: Literal['app', 'framework'] | None
    completed_at: datetime = <factory>
    def __init__(self, request: 'RequestInfo', status_code: 'int', duration_seconds: 'float', error_source: "Literal['app', 'framework'] | None", completed_at: 'datetime' = <factory>) -> None
def create_app(*, routes: 'RouteGroup', context_factory: 'ContextFactory', lifespan: 'Lifespan | None' = None, hooks: 'Sequence[Hook]' = (), webhooks: 'Sequence[Webhook]' = (), middleware: 'Sequence[Middleware]' = (), observers: 'Sequence[OutcomeObserver]' = (), use_case_observers: 'Sequence[Callable[[UseCaseOutcome], Any]]' = (), max_request_bytes: 'int | None' = 1048576) -> 'Starlette'

# tenchi.testing
ASGIApp = collections.abc.Callable[..., collections.abc.Awaitable[None]]
ClockAdvance = ClockAdvance
IdempotencyStoreFactory = IdempotencyStoreFactory
RateLimitStoreFactory = RateLimitStoreFactory
StoreConformanceError (re-export of tenchi._store_conformance.StoreConformanceError)
def open_client(app: 'ASGIApp', *, headers: 'Mapping[str, str] | None' = None, errors: 'Sequence[ErrorDef]' = (), observers: 'Sequence[ClientObserver]' = (), attempt_observers: 'Sequence[ClientAttemptObserver]' = (), base_url: 'str' = 'http://testserver') -> 'AsyncGenerator[Client]'
def open_http(app: 'ASGIApp', *, headers: 'Mapping[str, str] | None' = None, base_url: 'str' = 'http://testserver') -> 'AsyncGenerator[httpx.AsyncClient]'
def verify_idempotency_store(open_store: 'IdempotencyStoreFactory', *, advance: 'ClockAdvance') -> 'None'
def verify_rate_limit_store(open_store: 'RateLimitStoreFactory', *, advance: 'ClockAdvance') -> 'None'

# tenchi.tasks
class Task
    name: str
    use_case: Callable[..., Awaitable[Any]]
    description: str | None
    request: Any
    result: Any
    request_required: bool
    def __init__(self, name: 'str', use_case: 'Callable[..., Awaitable[Any]]', description: 'str | None', request: 'Any', result: 'Any', request_required: 'bool') -> None
class TaskBindingError(ConfigurationError, TypeError)
class TaskGroup
    tasks: tuple[Task, ...]
    def __init__(self, tasks: 'tuple[Task, ...]') -> None
class TaskNotFoundError(TenchiError, LookupError)
class TaskResultError(TenchiError, TypeError)
class TaskRunner
    tasks: TaskGroup
    context_factory: Callable[..., Any]
    lifespan: Callable[[], AbstractAsyncContextManager[Any]] | None = None
    use_case_observers: tuple[UseCaseObserver, ...] = ()
    def __init__(self, tasks: 'TaskGroup', context_factory: 'Callable[..., Any]', lifespan: 'Callable[[], AbstractAsyncContextManager[Any]] | None' = None, use_case_observers: 'tuple[UseCaseObserver, ...]' = ()) -> None
    def run(self, name: 'str', *, input: 'Any' = UNSET, input_json: 'bytes | str | None' = None) -> 'Any'
def create_task_runner(*, tasks: 'TaskGroup', context_factory: 'Callable[..., Any]', lifespan: 'Callable[[], AbstractAsyncContextManager[Any]] | None' = None, use_case_observers: 'Sequence[UseCaseObserver]' = ()) -> 'TaskRunner'
def task(name: 'str', use_case: 'Callable[..., Awaitable[Any]]', *, description: 'str | None' = None) -> 'Task'
def task_group(*items: 'Task | TaskGroup | Sequence[Task]') -> 'TaskGroup'

# tenchi.tools
TOOL_MANIFEST_VERSION = 1
class Tool(Generic)
    name: str
    description: str
    request: Any
    result: Any
    errors: tuple[ErrorDef, ...]
    read_only: bool
    destructive: bool
    idempotent: bool
    open_world: bool
    def __init__(self, name: 'str', description: 'str', request: 'Any', result: 'Any', errors: 'tuple[ErrorDef, ...]', read_only: 'bool', destructive: 'bool', idempotent: 'bool', open_world: 'bool') -> None
    def declares_error(self, definition: 'ErrorDef') -> 'bool'
class ToolAnnotationManifest(dict)
class ToolBinding(Generic)
    tool: Tool[RequestT, ResultT]
    use_case: Callable[..., Awaitable[ResultT]]
    def __init__(self, tool: 'Tool[RequestT, ResultT]', use_case: 'Callable[..., Awaitable[ResultT]]') -> None
class ToolBindingError(ConfigurationError, TypeError)
class ToolErrorManifest(dict)
class ToolGroup
    handlers: tuple[ToolBinding[Any, Any], ...]
    def __init__(self, handlers: 'tuple[ToolBinding[Any, Any], ...]') -> None
class ToolInvocationError(TenchiError, RuntimeError)
class ToolManifest(dict)
class ToolManifestEntry(dict)
class ToolNotFoundError(TenchiError, LookupError)
class ToolResultError(TenchiError, TypeError)
class ToolRunner
    tools: ToolGroup
    context_factory: Callable[..., Any]
    lifespan: Callable[[], AbstractAsyncContextManager[Any]] | None = None
    use_case_observers: tuple[UseCaseObserver, ...] = ()
    def __init__(self, tools: 'ToolGroup', context_factory: 'Callable[..., Any]', lifespan: 'Callable[[], AbstractAsyncContextManager[Any]] | None' = None, use_case_observers: 'tuple[UseCaseObserver, ...]' = ()) -> None
    def call(self, name: 'str', *, input: 'Any' = UNSET, input_json: 'bytes | str | None' = None) -> 'Any'
def create_tool_runner(*, tools: 'ToolGroup', context_factory: 'Callable[..., Any]', lifespan: 'Callable[[], AbstractAsyncContextManager[Any]] | None' = None, use_case_observers: 'Sequence[UseCaseObserver]' = ()) -> 'ToolRunner'
def tool(name: 'str', *, request: 'object | None' = None, result: 'object | None', description: 'str', errors: 'Sequence[ErrorDef]' = (), read_only: 'bool' = False, destructive: 'bool | None' = None, idempotent: 'bool | None' = None, open_world: 'bool' = True) -> 'Tool[Any, Any]'
def tool_group(*items: 'ToolBinding[Any, Any] | ToolGroup | Sequence[ToolBinding[Any, Any]]') -> 'ToolGroup'
def tool_handler(declaration: 'Tool[RequestT, ResultT]', use_case: 'Callable[..., Awaitable[ResultT]]') -> 'ToolBinding[RequestT, ResultT]'
def tool_manifest(tools: 'ToolGroup') -> 'ToolManifest'

# tenchi.webhooks
class Webhook
    contract: Contract[Any, Any]
    verifier: WebhookVerifier
    def __init__(self, contract: 'Contract[Any, Any]', verifier: 'WebhookVerifier') -> None
class WebhookBindingError(ConfigurationError, TypeError)
class WebhookRequest
    body: bytes
    headers: Mapping[str, str]
    header_values: Mapping[str, tuple[str, ...]]
    contract: Contract[Any, Any]
    request_id: str
    def __init__(self, body: 'bytes', headers: 'Mapping[str, str]', header_values: 'Mapping[str, tuple[str, ...]]', contract: 'Contract[Any, Any]', request_id: 'str') -> None
WebhookVerifier = collections.abc.Callable[['WebhookRequest', typing.Any], typing.Any]
def webhook(contract: 'Contract[Any, Any]', verifier: 'WebhookVerifier') -> 'Webhook'
