mirror of
https://github.com/langgenius/dify.git
synced 2026-05-20 08:46:57 +08:00
Read-side surface for difyctl describe / get / list:
- GET /openapi/v1/apps paginated list (workspace_id required)
- GET /openapi/v1/apps/<id> single app summary
- GET /openapi/v1/apps/<id>/parameters port of service_api parameters
- GET /openapi/v1/apps/<id>/describe merged { info, parameters }
All gated by validate_bearer(ACCEPT_USER_ANY) + require_scope(APPS_READ) +
require_workspace_member(ctx, tenant_id). SSO subjects 404 (account-only
helper account_or_404 deduplicates the guard across the four endpoints).
PaginationEnvelope[T] (page, limit, total, has_more, data) is the canonical
shape for every /openapi/v1/* list endpoint. has_more is computed by the
server from page * limit < total. /account/sessions migrates from the
legacy { sessions: [...] } shape to the envelope; integration tests assert
the legacy key is gone.
35 lines
863 B
Python
35 lines
863 B
Python
"""Shared response substructures for openapi endpoints."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Generic, TypeVar
|
|
|
|
from pydantic import BaseModel
|
|
|
|
T = TypeVar("T")
|
|
|
|
|
|
class UsageInfo(BaseModel):
|
|
prompt_tokens: int = 0
|
|
completion_tokens: int = 0
|
|
total_tokens: int = 0
|
|
|
|
|
|
class MessageMetadata(BaseModel):
|
|
usage: UsageInfo | None = None
|
|
retriever_resources: list[dict[str, Any]] = []
|
|
|
|
|
|
class PaginationEnvelope(BaseModel, Generic[T]): # noqa: UP046
|
|
"""Canonical pagination envelope for `/openapi/v1/*` list endpoints."""
|
|
|
|
page: int
|
|
limit: int
|
|
total: int
|
|
has_more: bool
|
|
data: list[T]
|
|
|
|
@classmethod
|
|
def build(cls, *, page: int, limit: int, total: int, items: list[T]) -> PaginationEnvelope[T]:
|
|
return cls(page=page, limit=limit, total=total, has_more=page * limit < total, data=items)
|