mirror of
https://github.com/langgenius/dify.git
synced 2026-05-22 01:48:39 +08:00
Collapse the openapi-namespace per-app reads into one canonical endpoint
GET /openapi/v1/apps/<id>/describe[?fields=info,parameters,input_schema]
returning a single AppDescribeResponse with all blocks Optional and a new
JSON-Schema input_schema block derived server-side from user_input_form +
app mode.
- AppDescribeQuery (Pydantic, extra=forbid) parses the ?fields allow-list;
unknown member -> 422.
- _input_schema.build_input_schema(app) derives Draft 2020-12 JSON Schema:
chat-family modes carry top-level query (string, minLength=1, required);
workflow / completion only carry inputs. AppUnavailableError -> empty
sentinel (EMPTY_INPUT_SCHEMA).
- Drop AppByIdApi (/apps/<id>) and AppParametersApi (/apps/<id>/parameters)
route classes; delete app_info.py module + app_info_payload helper.
- AppDescribeResponse.{info,parameters,input_schema} now Optional[None].
Lock-step deploy with difyctl Phase B (/describe consumer migration).
70 lines
1.8 KiB
Python
70 lines
1.8 KiB
Python
"""Shared response substructures for openapi endpoints."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
from pydantic import BaseModel
|
|
|
|
# Server-side cap on `limit` query param for any /openapi/v1/* list endpoint.
|
|
# Sibling endpoints (`/apps`, `/account/sessions`, future routes) all clamp to
|
|
# this; do not introduce per-endpoint caps without raising the constant.
|
|
MAX_PAGE_LIMIT = 200
|
|
|
|
|
|
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[T](BaseModel):
|
|
"""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)
|
|
|
|
|
|
class AppListRow(BaseModel):
|
|
id: str
|
|
name: str
|
|
description: str | None = None
|
|
mode: str
|
|
tags: list[dict[str, str]] = []
|
|
updated_at: str | None = None
|
|
created_by_name: str | None = None
|
|
workspace_id: str | None = None
|
|
workspace_name: str | None = None
|
|
|
|
|
|
class AppInfoResponse(BaseModel):
|
|
id: str
|
|
name: str
|
|
description: str | None = None
|
|
mode: str
|
|
author: str | None = None
|
|
tags: list[dict[str, str]] = []
|
|
|
|
|
|
class AppDescribeInfo(AppInfoResponse):
|
|
updated_at: str | None = None
|
|
service_api_enabled: bool
|
|
|
|
|
|
class AppDescribeResponse(BaseModel):
|
|
info: AppDescribeInfo | None = None
|
|
parameters: dict[str, Any] | None = None
|
|
input_schema: dict[str, Any] | None = None
|