feat(web): set up @dify/openapi-content-mapper foundations (#44627)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
Stephen Zhouandautofix-ci[bot] authored and GitHub committed 2026-10-26 05:06:34 +00:00
1 parent 3a909827c3
commit 226110d611
150 files changed
+25051 -223

No files matched your search

+8
View File
@@ -4,3 +4,11 @@ omit =
api/tests/*
api/migrations/*
api/core/rag/datasource/vdb/*
[paths]
# Cache lifecycle tests execute an unchanged helper in an isolated backend.
# Only that helper is measured there; fixture modules are omitted by the tests.
openapi_export_tools =
api/dev
*/pytest-*/test_*/api/dev
*/pytest-*/popen-*/test_*/api/dev
+38
View File
@@ -10,6 +10,44 @@ permissions:
contents: read
jobs:
openapi-sdk-test:
name: OpenAPI SDK and Next.js adapters
runs-on: depot-ubuntu-24.04-4
timeout-minutes: 15
steps:
- name: Checkout code
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Setup web environment
uses: ./.github/actions/setup-web
- name: Setup Python for in-memory Console schema export
uses: astral-sh/setup-uv@c18668ad3cf93ea998bef934396af7bb5c839dc7 # v10.2.0
with:
enable-cache: true
python-version: '3.13'
cache-dependency-glob: api/uv.lock
- name: Install schema exporter dependencies
run: uv sync --project api --frozen
- name: Test SDK types, runtime and Vite integration
run: pnpm --filter @dify/openapi-content-mapper test
- name: Verify the packed SDK in an independent npm project
run: pnpm --filter @dify/openapi-content-mapper test:package
- name: Test Next.js adapters and tree-shaking
run: pnpm --filter @dify/openapi-content-mapper test:next
- name: Verify standalone Console imports, error maps and editor support
run: pnpm --filter @dify/openapi-content-mapper exec node --test --test-concurrency=1 integration/knowledge-fs-console.test.mjs integration/orpc-errors.test.mjs integration/console-preparation.test.mjs integration/console-editor.test.mjs
- name: Check all Console types against the reviewed migration differences
run: pnpm --filter @dify/openapi-content-mapper check:console
test:
name: Web Tests (${{ matrix.shardIndex }}/${{ matrix.shardTotal }})
runs-on: depot-ubuntu-24.04-4
+17
View File
@@ -9,3 +9,20 @@
1. **Start Debugging**: Select the desired configuration from the dropdown menu and click the green play button.
Start the frontend separately using the [frontend guide](../web/README.md).
## Frontend OpenAPI types
After installing workspace dependencies, install the TypeScript 7 extension
(`TypeScriptTeam.native-preview`). Copy `settings.example.json` to `settings.json`,
or merge its three `js/ts.*` settings into your existing configuration. Open the
repository root in a trusted workspace, then open a consuming TypeScript file so
the language server loads the project's Content Mapper configuration.
If lifecycle scripts were disabled during installation, first run
`pnpm --filter @dify/openapi-content-mapper build`. For the repository Console
example, run `uv sync --project api --frozen` to prepare its local schema exporter,
then open `packages/openapi-content-mapper/examples/repository/client.ts`. The
exported OpenAPI content stays in memory; no preparation of a specification file
is needed. Accept the editor prompt to use the workspace TypeScript 7.1 compiler.
Local `settings.json` remains ignored; the shared template is exercised by the
Console language-server test.
+4
View File
@@ -1,4 +1,8 @@
{
"js/ts.experimental.useTsgo": true,
"js/ts.tsdk.path": "./packages/openapi-content-mapper/node_modules/typescript",
"js/ts.contentMappers.enabled": true,
"cucumber.features": ["e2e/features/**/*.feature"],
"cucumber.glue": ["e2e/features/**/*.ts"],
+6
View File
@@ -31,11 +31,13 @@ from controllers.console.explore.error import AgentVersionNotFoundHTTPError
from controllers.console.explore.installed_app_admission import get_installed_app
from controllers.console.flask_admission import console_account_admission
from controllers.console.wraps import model_validate
from core.base.tts.audio_mime import SUPPORTED_TTS_AUDIO_MIME_TYPES
from core.errors.error import ModelCurrentlyNotSupportError, ProviderTokenNotInitError, QuotaExceededError
from extensions.ext_application_services import application_services
from graphon.model_runtime.errors.invoke import InvokeError
from libs.exception import BaseHTTPException
from libs.external_api import error_responses
from libs.flask_restx_compat import BINARY_RESPONSE_MEDIA_TYPES_VENDOR_KEY
from libs.helper import dump_response
from machinery.context import RequestContext
from services.agent.errors import AgentVersionNotFoundError
@@ -155,6 +157,10 @@ class ChatTextApi(Resource):
ProviderQuotaExceededError,
)
@console_ns.expect(console_ns.models[TextToAudioPayload.__name__])
@console_ns.doc(
produces=list(SUPPORTED_TTS_AUDIO_MIME_TYPES),
vendor={BINARY_RESPONSE_MEDIA_TYPES_VENDOR_KEY: list(SUPPORTED_TTS_AUDIO_MIME_TYPES)},
)
@console_ns.response(HTTPStatus.OK, "Success", console_ns.models[AudioBinaryResponse.__name__])
@console_account_admission()
@get_installed_app
+6
View File
@@ -83,6 +83,7 @@ from controllers.console.wraps import cloud_edition_billing_resource_check, mode
from controllers.web.error import InvokeRateLimitError as InvokeRateLimitHttpError
from core.app.apps.agent_app.errors import AgentAppGeneratorError, AgentAppNotPublishedError
from core.app.entities.app_invoke_entities import InvokeFrom
from core.base.tts.audio_mime import SUPPORTED_TTS_AUDIO_MIME_TYPES
from core.errors.error import (
AppInvokeQuotaExceededError,
ModelCurrentlyNotSupportError,
@@ -102,6 +103,7 @@ from graphon.variables import SecretVariable, VariableBase
from libs import helper
from libs.exception import BaseHTTPException
from libs.external_api import error_responses
from libs.flask_restx_compat import BINARY_RESPONSE_MEDIA_TYPES_VENDOR_KEY
from libs.helper import dump_response, to_timestamp, uuid_value
from libs.stream import close_stream
from libs.url_utils import normalize_api_base_url
@@ -871,6 +873,10 @@ class TrialChatTextApi(Resource):
ProviderQuotaExceededError,
)
@console_ns.expect(console_ns.models[TextToSpeechRequest.__name__])
@console_ns.doc(
produces=list(SUPPORTED_TTS_AUDIO_MIME_TYPES),
vendor={BINARY_RESPONSE_MEDIA_TYPES_VENDOR_KEY: list(SUPPORTED_TTS_AUDIO_MIME_TYPES)},
)
@console_ns.response(HTTPStatus.OK, "Success", console_ns.models[AudioBinaryResponse.__name__])
@console_account_admission()
@get_trial_app
@@ -54,6 +54,7 @@ from extensions.ext_database import db
from fields.base import ResponseModel
from graphon.model_runtime.utils.encoders import jsonable_encoder
from libs.external_api import error_responses
from libs.flask_restx_compat import BINARY_RESPONSE_MEDIA_TYPES_VENDOR_KEY
from libs.helper import dump_response
from libs.login import login_required
from models.account import (
@@ -719,6 +720,10 @@ class PluginListInstallationsFromIdsApi(Resource):
class PluginIconApi(Resource):
@error_responses(PluginOperationError)
@console_ns.doc(params=query_params_from_model(ParserIcon))
@console_ns.doc(
produces=["*/*"],
vendor={BINARY_RESPONSE_MEDIA_TYPES_VENDOR_KEY: ["*/*"]},
)
@console_ns.response(200, "Success", console_ns.models[BinaryFileResponse.__name__])
@setup_required
@model_validate(ParserIcon)
@@ -736,6 +741,10 @@ class PluginIconApi(Resource):
class PluginAssetApi(Resource):
@error_responses(PluginOperationError)
@console_ns.doc(params=query_params_from_model(ParserAsset))
@console_ns.doc(
produces=["application/octet-stream"],
vendor={BINARY_RESPONSE_MEDIA_TYPES_VENDOR_KEY: ["application/octet-stream"]},
)
@console_ns.response(200, "Success", console_ns.models[BinaryFileResponse.__name__])
@setup_required
@login_required
@@ -17,6 +17,7 @@ from controllers.console.workspace.rbac.schemas import (
_ReplaceBindingsRequest,
_ResourceAccessScopeRequest,
_ResourceUserAccessPoliciesQuery,
_WorkspaceMatrixQuery,
pagination_options,
)
from extensions.ext_application_services import application_services
@@ -203,6 +204,7 @@ def _build_resource_access_apis(spec: _ResourceAccessRoutes) -> _ResourceAccessA
return dump_response(SimpleResultResponse, {"result": "success"})
class WorkspaceMatrixApi(Resource):
@console_ns.doc(params=query_params_from_model(_WorkspaceMatrixQuery))
@console_account_admission()
@console_ns.response(200, "Success", console_ns.models[dto.WorkspaceAccessMatrix.__name__])
def get(self, context: RequestContext):
@@ -130,6 +130,10 @@ class _AccessControlLanguageQuery(BaseModel):
language: Literal["en", "ja", "zh"] | None = Field(default=None, description="Localized policy label language")
class _WorkspaceMatrixQuery(_PaginationQuery, _AccessControlLanguageQuery):
pass
class _ResourceUserAccessPoliciesQuery(_PaginationQuery):
language: Literal["en", "ja", "zh"] | None = Field(default=None, description="Localized policy label language")
+10 -1
View File
@@ -25,6 +25,7 @@ from fields.base import ResponseModel
from libs import helper
from libs.exception import RelayedHTTPError
from libs.external_api import error_responses
from libs.flask_restx_compat import BINARY_RESPONSE_MEDIA_TYPES_VENDOR_KEY
from libs.helper import dump_response
from machinery.context import RequestContext
from services.skill_management_service import (
@@ -388,7 +389,11 @@ class WorkspaceSkillTagsApi(Resource):
@console_ns.route("/workspaces/current/skills/import")
class WorkspaceSkillImportApi(Resource):
@error_responses(RelayedHTTPError, SkillRequestError)
@console_ns.doc(description="Import a Skill zip package from multipart form field `file`.")
@console_ns.doc(
description="Import a Skill zip package from multipart form field `file`.",
consumes=["multipart/form-data"],
params=_FILE_UPLOAD_PARAMS,
)
@console_ns.response(201, "Skill imported", console_ns.models[SkillDetailResponse.__name__])
@console_account_admission(
rbac_checks=[RBACCheck(RBACPermission.SKILL_EDIT, Workspace())],
@@ -659,6 +664,10 @@ class WorkspaceSkillFilePreviewApi(Resource):
class WorkspaceSkillFileContentApi(Resource):
@error_responses(RelayedHTTPError, SkillRequestError)
@console_ns.doc(params={**query_params_from_model(SkillFileQuery), "download": "Return as an attachment when 1."})
@console_ns.doc(
produces=["*/*"],
vendor={BINARY_RESPONSE_MEDIA_TYPES_VENDOR_KEY: ["*/*"]},
)
@console_ns.response(200, "Skill file content", console_ns.models[BinaryFileResponse.__name__])
@console_account_admission()
@with_session
+357
View File
@@ -0,0 +1,357 @@
"""Local, idle-expiring OpenAPI export cache. Contract bytes never touch the filesystem.
The POSIX server owns a private Unix socket and an empty lifecycle lock. It caches
the document in RAM. A single-threaded snapshot preloads only dependency modules,
never controllers. Each refresh imports controllers in a fresh fork; edits to a
preloaded dependency re-exec the snapshot before exporting. Unsupported platforms
or unsafe snapshots use the ordinary fresh-process exporter.
"""
from __future__ import annotations
import contextlib
import hashlib
import importlib.machinery
import io
import json
import os
import select
import signal
import socket
import subprocess
import sys
import tempfile
import time
import traceback
from pathlib import Path
from typing import Any, Never
API_ROOT = Path(__file__).resolve().parents[1]
TIMEOUT = 90
IDLE_TIMEOUT = 120
MAX_BYTES = 64 * 1024 * 1024
def source_imports() -> None:
"""Read editable backend modules from source, preserving installed-library bytecode caches."""
original = importlib.machinery.SourceFileLoader.get_code
def get_code(self: importlib.machinery.SourceFileLoader, fullname: str):
path = Path(self.path)
if path.is_relative_to(API_ROOT) and ".venv" not in path.parts:
return self.source_to_code(self.get_data(self.path), self.path)
return original(self, fullname)
importlib.machinery.SourceFileLoader.get_code = get_code
sys.dont_write_bytecode = True
def source_state() -> dict[str, tuple[int, int, int]]:
"""Match the Console descriptor's inputs, excluding tests and local environments."""
files = [API_ROOT / "pyproject.toml", API_ROOT / "uv.lock", Path.cwd() / ".env"]
for directory, children, names in os.walk(API_ROOT):
children[:] = [name for name in children if name not in {".venv", ".git", "__pycache__"}]
if Path(directory) == API_ROOT:
children[:] = [name for name in children if name != "tests"]
files.extend(Path(directory) / name for name in names if name.endswith(".py"))
return {str(file): file_stamp(file) for file in files}
def file_stamp(file: Path) -> tuple[int, int, int]:
try:
stat = file.stat()
return stat.st_mtime_ns, stat.st_ctime_ns, stat.st_size
except FileNotFoundError:
return 0, 0, 0
def fresh_export() -> bytes:
result = subprocess.run(
[
sys.executable,
"-B",
"-c",
"import sys;sys.path.insert(0,sys.argv[1]);"
"from dev.cached_console_openapi import source_imports;source_imports();"
"from dev.export_console_openapi import main;main()",
str(API_ROOT),
],
capture_output=True,
timeout=TIMEOUT,
check=False,
)
if result.returncode:
raise RuntimeError(result.stderr.decode(errors="replace")[-16000:])
return result.stdout
def single_threaded() -> bool:
"""Check native threads too: threading.active_count misses C library pools."""
try:
if sys.platform.startswith("linux"):
return len(os.listdir("/proc/self/task")) == 1
if sys.platform == "darwin":
# Darwin -M always prints its thread header, even with -o pid=.
output = subprocess.check_output(["ps", "-M", "-p", str(os.getpid())], timeout=5)
return len(output.strip().splitlines()) == 2
except (OSError, subprocess.SubprocessError):
return False
return False
def preload() -> tuple[bool, dict[str, tuple[int, int, int]]]:
"""Load schema dependencies without retaining route registries or controller classes."""
import urllib.request
getproxies = urllib.request.getproxies
try:
if sys.platform == "darwin":
# macOS SystemConfiguration starts native threads. Resolve its proxy
# settings in a helper, preserving the values without forking those threads.
proxies = json.loads(
subprocess.check_output(
[sys.executable, "-c", "import json,urllib.request;print(json.dumps(urllib.request.getproxies()))"],
timeout=10,
)
)
urllib.request.getproxies = lambda: proxies
sys.path.insert(0, str(API_ROOT))
from dev.generate_swagger_specs import apply_runtime_defaults
apply_runtime_defaults()
# Keep runtime composition (and libraries with native thread pools) out
# of the snapshot. These pure model dependencies account for much of startup.
import dify_agent.protocol.schemas
import core.mcp.types
import graphon.nodes.parameter_extractor.entities
import models
import services.knowledge_fs.product_dto
_ = core.mcp.types, dify_agent.protocol.schemas, graphon.nodes.parameter_extractor.entities
_ = models, services.knowledge_fs.product_dto
safe = not any(name.startswith("controllers.") for name in sys.modules) and single_threaded()
except Exception:
# A cache optimization must not prevent a normal export from working.
safe = False
finally:
urllib.request.getproxies = getproxies
dependencies = {}
for module in tuple(sys.modules.values()):
filename = getattr(module, "__file__", None) # guard-ignore: no-new-getattr -- optional module source metadata
if isinstance(filename, str):
dependencies[str(Path(filename).resolve())] = file_stamp(Path(filename))
for filename in (API_ROOT / "pyproject.toml", API_ROOT / "uv.lock", Path.cwd() / ".env"):
dependencies[str(filename)] = file_stamp(filename)
return safe, dependencies
def export_worker(write_fd: int) -> Never:
"""Run the isolated exporter and keep its pipe open through process exit."""
try:
from dev.export_console_openapi import main
output = io.StringIO()
with contextlib.redirect_stdout(output):
main()
payload = b"OK\n" + output.getvalue().encode()
except BaseException:
payload = b"ERROR\n" + traceback.format_exc().encode()
try:
with os.fdopen(write_fd, "wb") as pipe:
pipe.write(payload)
pipe.flush()
# Keep the pipe open through process exit. Closing it first lets
# the parent kill a successful worker while exit instrumentation
# (for example, subprocess coverage) is still flushing its data.
os._exit(0)
finally:
os._exit(1)
def fork_export() -> bytes:
"""Export from a clean controller registry; the parent snapshot is never mutated."""
read_fd, write_fd = os.pipe()
pid = os.fork()
if pid == 0:
os.close(read_fd)
export_worker(write_fd)
os.close(write_fd)
chunks: list[bytes] = []
size = 0
deadline = time.monotonic() + TIMEOUT
try:
while True:
if not select.select([read_fd], [], [], max(0, deadline - time.monotonic()))[0]:
raise TimeoutError("OpenAPI refresh timed out")
chunk = os.read(read_fd, 65536)
if not chunk:
break
size += len(chunk)
if size > MAX_BYTES:
raise ValueError("OpenAPI export exceeds the response limit")
chunks.append(chunk)
result = b"".join(chunks)
status, _, payload = result.partition(b"\n")
if status != b"OK":
raise RuntimeError(payload.decode(errors="replace") or "OpenAPI worker exited without a response")
return payload
finally:
os.close(read_fd)
# A worker can fail after closing its pipe. Never leave it running or unreaped.
with contextlib.suppress(ProcessLookupError):
os.kill(pid, signal.SIGKILL)
os.waitpid(pid, 0)
def socket_path() -> Path:
directory = Path(tempfile.gettempdir()) / f"dify-openapi-{os.getuid()}"
# macOS Unix socket paths have a small length limit.
if len(str(directory)) > 55:
directory = Path("/tmp") / f"dify-openapi-{os.getuid()}"
directory.mkdir(mode=0o700, exist_ok=True)
stat = directory.lstat()
if directory.is_symlink() or stat.st_uid != os.getuid() or stat.st_mode & 0o077:
raise PermissionError("OpenAPI IPC directory must be private to the current user")
environment = {
key: value
for key, value in os.environ.items()
if key not in {"_", "PWD", "OLDPWD", "SHLVL", "UV_RUN_RECURSION_DEPTH"}
}
key = hashlib.sha256(json.dumps([str(API_ROOT), os.getcwd(), sys.executable, environment], sort_keys=True).encode())
key.update(Path(__file__).read_bytes())
return directory / f"{key.hexdigest()[:24]}.sock"
def serve(path: Path, inherited: list[str]) -> None:
import fcntl
if inherited:
listener = socket.socket(fileno=int(inherited[0]))
lock_fd = int(inherited[1])
else:
lock_fd = os.open(path.with_suffix(".lock"), os.O_CREAT | os.O_RDWR, 0o600)
try:
fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
except BlockingIOError:
os.close(lock_fd)
return
path.unlink(missing_ok=True)
listener = socket.socket(socket.AF_UNIX)
listener.bind(str(path))
listener.listen(16)
listener.settimeout(IDLE_TIMEOUT)
baseline = source_state()
safe, dependencies = preload()
snapshot_dirty = source_state() != baseline
cached_state: dict[str, tuple[int, int, int]] | None = None
cached = b""
try:
while True:
try:
connection, _ = listener.accept()
except TimeoutError:
return
with connection:
connection.settimeout(TIMEOUT)
try:
request = b""
while not request.endswith(b"\n") and len(request) < 16:
part = connection.recv(16 - len(request))
if not part:
break
request += part
if request == b"stop\n":
connection.sendall(b"OK\n")
return
if request != b"export\n":
continue
current = source_state()
stale = (
snapshot_dirty
or set(current) != set(baseline)
or any(file_stamp(Path(file)) != stamp for file, stamp in dependencies.items())
)
if stale:
# No reload(sys.modules): restart all preloaded dependencies.
connection.sendall(b"RETRY\n")
connection.close()
os.set_inheritable(listener.fileno(), True)
os.set_inheritable(lock_fd, True)
os.execv(
sys.executable,
[sys.executable, __file__, "--serve", str(path), str(listener.fileno()), str(lock_fd)],
)
if current != cached_state:
output = fork_export() if safe and single_threaded() else fresh_export()
# Do not publish a contract assembled while source files changed.
if source_state() != current:
connection.sendall(b"RETRY\n")
continue
payload: Any = json.loads(output)
if not isinstance(payload, dict) or set(payload) != {"console", "fast"}:
raise ValueError("Invalid Console export response")
cached, cached_state = output, current
connection.sendall(b"OK\n" + cached)
except (BrokenPipeError, ConnectionResetError):
pass
except Exception:
with contextlib.suppress(OSError):
connection.sendall(b"ERROR\n" + traceback.format_exc().encode()[-16000:])
finally:
listener.close()
path.unlink(missing_ok=True)
os.close(lock_fd)
def request_export(*, stop: bool = False) -> bytes:
if not hasattr(os, "fork"):
return b"" if stop else fresh_export()
path = socket_path()
deadline = time.monotonic() + TIMEOUT
launched = False
while time.monotonic() < deadline:
try:
with socket.socket(socket.AF_UNIX) as connection:
connection.settimeout(max(0.1, deadline - time.monotonic()))
connection.connect(str(path))
connection.sendall(b"stop\n" if stop else b"export\n")
chunks: list[bytes] = []
size = 0
while chunk := connection.recv(65536):
size += len(chunk)
if size > MAX_BYTES:
raise ValueError("OpenAPI response exceeds the limit")
chunks.append(chunk)
status, _, payload = b"".join(chunks).partition(b"\n")
if status == b"OK":
return payload
if status == b"ERROR":
raise RuntimeError(payload.decode(errors="replace"))
if status != b"RETRY":
raise RuntimeError("Incomplete OpenAPI cache response")
except (FileNotFoundError, ConnectionRefusedError):
if stop:
return b""
if not launched:
subprocess.Popen(
[sys.executable, __file__, "--serve", str(path)],
start_new_session=True,
stdin=subprocess.DEVNULL,
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
)
launched = True
time.sleep(0.03)
raise TimeoutError("OpenAPI cache did not respond in time")
if __name__ == "__main__":
# Timestamp-based .pyc files can serve stale code after same-size edits within one second.
source_imports()
if sys.argv[1:2] == ["--serve"]:
serve(Path(sys.argv[2]), sys.argv[3:])
elif sys.argv[1:] == ["--stop"]:
request_export(stop=True)
else:
sys.stdout.buffer.write(request_export())
+64
View File
@@ -0,0 +1,64 @@
"""Export community Console schemas to stdout for the OpenAPI content mapper."""
import ast
import contextlib
import inspect
import json
import sys
import textwrap
from pathlib import Path
from typing import Any
def attach_source_location(document: dict[str, Any], path: str, method: str, handler: Any) -> None:
"""Attach editor-only origins to exported operations, leaving live schemas unchanged."""
operation = document["paths"].get(path, {}).get(method.lower())
if not isinstance(operation, dict) or handler is None:
return
try:
handler = inspect.unwrap(handler)
filename = inspect.getsourcefile(handler)
lines, start = inspect.getsourcelines(handler)
definition = ast.parse(textwrap.dedent("".join(lines))).body[0]
except (OSError, TypeError, ValueError, SyntaxError):
# Dynamically created or native handlers have no navigable Python source.
return
if filename and isinstance(definition, (ast.FunctionDef, ast.AsyncFunctionDef)):
operation["x-source-location"] = {
"file": str(Path(filename).resolve()),
"line": start + definition.lineno - 1,
}
def main() -> None:
# Backend initialization may log to stdout. Keep the protocol output pure JSON.
with contextlib.redirect_stdout(sys.stderr):
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
from dev.generate_fastopenapi_specs import export_fastopenapi_specs
from dev.generate_swagger_specs import export_console_spec
documents = {
"console": export_console_spec(),
"fast": export_fastopenapi_specs()["fastopenapi-console-openapi.json"],
}
from flask_restx.swagger import extract_path
from controllers.console import api
from controllers.fastopenapi import console_router
for namespace in api.namespaces:
for resource in namespace.resources:
cls = resource.resource
for url in api.ns_urls(namespace, resource.urls):
path = extract_path(url)
for method in cls.methods:
handler = getattr(cls, method.lower(), None) # guard-ignore: no-new-getattr -- HTTP method
attach_source_location(documents["console"], path, method, handler)
for path, method, handler in console_router.get_routes():
attach_source_location(documents["fast"], f"/console/api{path}", method, handler)
json.dump(documents, sys.stdout, sort_keys=True)
sys.stdout.write("\n")
if __name__ == "__main__":
main()
+14 -9
View File
@@ -8,6 +8,7 @@ import logging
import sys
from dataclasses import dataclass
from pathlib import Path
from typing import Any
API_ROOT = Path(__file__).resolve().parents[1]
if str(API_ROOT) not in sys.path:
@@ -46,26 +47,30 @@ def create_fastopenapi_spec_app():
return app
def generate_fastopenapi_specs(output_dir: Path) -> list[Path]:
"""Write FastOpenAPI specs to `output_dir` and return the written paths."""
output_dir.mkdir(parents=True, exist_ok=True)
def export_fastopenapi_specs() -> dict[str, dict[str, Any]]:
"""Build FastOpenAPI documents in memory without writing generated files."""
app = create_fastopenapi_spec_app()
client = app.test_client()
written_paths: list[Path] = []
documents = {}
for target in FASTOPENAPI_SPEC_TARGETS:
response = client.get(target.route)
if response.status_code != 200:
raise RuntimeError(f"failed to fetch {target.route}: {response.status_code}")
payload = response.get_json()
payload = sort_openapi_arrays(response.get_json())
if not isinstance(payload, dict):
raise RuntimeError(f"unexpected response payload for {target.route}")
payload = sort_openapi_arrays(payload)
documents[target.filename] = payload
return documents
output_path = output_dir / target.filename
def generate_fastopenapi_specs(output_dir: Path) -> list[Path]:
"""Write FastOpenAPI specs to `output_dir` and return the written paths."""
output_dir.mkdir(parents=True, exist_ok=True)
written_paths: list[Path] = []
for filename, payload in export_fastopenapi_specs().items():
output_path = output_dir / filename
output_path.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8")
written_paths.append(output_path)
+26 -7
View File
@@ -17,7 +17,7 @@ import sys
from collections.abc import MutableMapping
from dataclasses import dataclass
from pathlib import Path
from typing import Protocol, TypeGuard
from typing import Any, Protocol, TypeGuard, cast
from flask import Flask
from flask_restx import Api
@@ -272,15 +272,26 @@ def _materialize_inline_model_definitions(api: RestxApi) -> None:
materialize_field(field)
def generate_specs(output_dir: Path) -> list[Path]:
"""Write all OpenAPI specs to `output_dir` and return the written paths."""
def export_console_spec() -> dict[str, Any]:
"""Build only Console; editor refreshes do not need the other four API surfaces."""
apply_runtime_defaults()
from libs.flask_restx_compat import install_swagger_compatibility
output_dir.mkdir(parents=True, exist_ok=True)
install_swagger_compatibility()
from controllers.console import api, bp
app = Flask(__name__)
app.register_blueprint(bp)
_materialize_inline_model_definitions(cast(RestxApi, api))
with app.test_request_context("/console/api/openapi.json"):
return finalize_openapi_payload(Swagger(api).as_dict())
def export_specs() -> dict[str, dict[str, Any]]:
"""Build OpenAPI documents in memory without writing generated files."""
app = create_spec_app()
target_apis = _target_apis()
written_paths: list[Path] = []
documents = {}
for target in SPEC_TARGETS:
# Build directly from the API instance instead of depending on the
# optional HTTP spec route. ExternalApi decides whether to register
@@ -289,8 +300,16 @@ def generate_specs(output_dir: Path) -> list[Path]:
with app.test_request_context(target.route):
payload = Swagger(target_apis[target.route]).as_dict()
payload = finalize_openapi_payload(payload)
documents[target.filename] = payload
return documents
output_path = output_dir / target.filename
def generate_specs(output_dir: Path) -> list[Path]:
"""Write all OpenAPI specs to `output_dir` and return the written paths."""
output_dir.mkdir(parents=True, exist_ok=True)
written_paths: list[Path] = []
for filename, payload in export_specs().items():
output_path = output_dir / filename
output_path.write_text(json.dumps(payload, indent=2, sort_keys=True) + "\n", encoding="utf-8")
written_paths.append(output_path)
+38 -5
View File
@@ -8176,7 +8176,7 @@ Request body:
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Success | **application/json**: [AudioBinaryResponse](#audiobinaryresponse)<br> |
| 200 | Success | **audio/aac**: binary<br>**audio/flac**: binary<br>**audio/mp4**: binary<br>**audio/mpeg**: binary<br>**audio/ogg**: binary<br>**audio/wav**: binary<br>**audio/webm**: binary<br> |
| 400 | Bad Request | **application/json**: [AppUnavailableError](#appunavailableerror)<br>[CompletionRequestError](#completionrequesterror)<br>[ModelCurrentlyNotSupportError](#modelcurrentlynotsupporterror)<br>[ProviderNotInitializeError](#providernotinitializeerror)<br>[ProviderNotSupportTextToSpeechError](#providernotsupporttexttospeecherror)<br>[ProviderQuotaExceededError](#providerquotaexceedederror)<br>[ErrorResponse](#errorresponse)<br> |
| 403 | Forbidden | **application/json**: [AccessDeniedError](#accessdeniederror)<br>[ErrorResponse](#errorresponse)<br> |
| 404 | Not Found | **application/json**: [AgentVersionNotFoundError](#agentversionnotfounderror)<br>[InstalledAppNotFoundError](#installedappnotfounderror)<br>[ErrorResponse](#errorresponse)<br> |
@@ -13859,7 +13859,7 @@ Returns the site configuration for the application including theme, icons, and t
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Success | **application/json**: [AudioBinaryResponse](#audiobinaryresponse)<br> |
| 200 | Success | **audio/aac**: binary<br>**audio/flac**: binary<br>**audio/mp4**: binary<br>**audio/mpeg**: binary<br>**audio/ogg**: binary<br>**audio/wav**: binary<br>**audio/webm**: binary<br> |
| 400 | Bad Request | **application/json**: [AppUnavailableError](#appunavailableerror)<br>[CompletionRequestError](#completionrequesterror)<br>[ModelCurrentlyNotSupportError](#modelcurrentlynotsupporterror)<br>[ProviderNotInitializeError](#providernotinitializeerror)<br>[ProviderNotSupportTextToSpeechError](#providernotsupporttexttospeecherror)<br>[ProviderQuotaExceededError](#providerquotaexceedederror)<br>[ErrorResponse](#errorresponse)<br> |
| 403 | Forbidden | **application/json**: [TrialAppFeatureDisabledError](#trialappfeaturedisablederror)<br>[TrialAppLimitExceededError](#trialapplimitexceedederror)<br>[TrialAppNotAllowedError](#trialappnotallowederror)<br>[ErrorResponse](#errorresponse)<br> |
| 404 | Not Found | **application/json**: [AgentVersionNotFoundError](#agentversionnotfounderror)<br>[ErrorResponse](#errorresponse)<br> |
@@ -15318,7 +15318,7 @@ Update a plugin endpoint
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Success | **application/json**: [BinaryFileResponse](#binaryfileresponse)<br> |
| 200 | Success | **application/octet-stream**: binary<br> |
| 400 | Bad Request | **application/json**: [PluginError](#pluginerror)<br>[ErrorResponse](#errorresponse)<br> |
| default | Error | **application/json**: [ErrorResponse](#errorresponse)<br> |
@@ -15400,7 +15400,7 @@ Update a plugin endpoint
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Success | **application/json**: [BinaryFileResponse](#binaryfileresponse)<br> |
| 200 | Success | `*/*`: binary<br> |
| 400 | Bad Request | **application/json**: [PluginError](#pluginerror)<br>[ErrorResponse](#errorresponse)<br> |
| default | Error | **application/json**: [ErrorResponse](#errorresponse)<br> |
@@ -16595,6 +16595,15 @@ Update a plugin endpoint
| default | Error | **application/json**: [ErrorResponse](#errorresponse)<br> |
### [GET] /workspaces/current/rbac/workspace/agents/access-policy
#### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| language | query | Localized policy label language | No | string, <br>**Available values:** "en", "ja", "zh" |
| limit | query | | No | integer |
| page | query | | No | integer |
| reverse | query | | No | boolean |
#### Responses
| Code | Description | Schema |
@@ -16651,6 +16660,15 @@ Update a plugin endpoint
| default | Error | **application/json**: [ErrorResponse](#errorresponse)<br> |
### [GET] /workspaces/current/rbac/workspace/apps/access-policy
#### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| language | query | Localized policy label language | No | string, <br>**Available values:** "en", "ja", "zh" |
| limit | query | | No | integer |
| page | query | | No | integer |
| reverse | query | | No | boolean |
#### Responses
| Code | Description | Schema |
@@ -16707,6 +16725,15 @@ Update a plugin endpoint
| default | Error | **application/json**: [ErrorResponse](#errorresponse)<br> |
### [GET] /workspaces/current/rbac/workspace/datasets/access-policy
#### Parameters
| Name | Located in | Description | Required | Schema |
| ---- | ---------- | ----------- | -------- | ------ |
| language | query | Localized policy label language | No | string, <br>**Available values:** "en", "ja", "zh" |
| limit | query | | No | integer |
| page | query | | No | integer |
| reverse | query | | No | boolean |
#### Responses
| Code | Description | Schema |
@@ -16764,6 +16791,12 @@ Update a plugin endpoint
### [POST] /workspaces/current/skills/import
Import a Skill zip package from multipart form field `file`.
#### Request Body
| Required | Schema |
| -------- | ------ |
| Yes | **multipart/form-data**: { **"file"**: binary }<br> |
#### Responses
| Code | Description | Schema |
@@ -16962,7 +16995,7 @@ Import a Skill zip package from multipart form field `file`.
| Code | Description | Schema |
| ---- | ----------- | ------ |
| 200 | Skill file content | **application/json**: [BinaryFileResponse](#binaryfileresponse)<br> |
| 200 | Skill file content | `*/*`: binary<br> |
| 400 | Bad Request | **application/json**: [InvalidRequestError](#invalidrequesterror)<br>[ErrorResponse](#errorresponse)<br> |
| default | Error | **application/json**: [ErrorResponse](#errorresponse)<br> |
@@ -170,3 +170,19 @@ def test_resource_whitelist_parses_body_and_returns_response(
assert result == {"account_ids": ["member"]}
assert domain.transport.only_request.json == {"automatic_include_workspace_members": True}
assert domain.tasks.queued == [Initialization("tenant", "actor", {_id_param(spec): resource_id})]
def test_workspace_matrix_documents_pagination_and_language(apis: rbac_mod._ResourceAccessApis) -> None:
from flask_restx.swagger import Swagger
from controllers.console import api
resource = Swagger(api).serialize_resource(console_ns, apis.workspace_matrix, "/workspace/access-policy")
assert resource is not None
operation = resource["get"]
parameters = {parameter["name"]: parameter for parameter in operation["parameters"]}
assert {"page", "limit", "reverse", "language"} <= parameters.keys()
assert all(parameters[name]["in"] == "query" for name in ("page", "limit", "language"))
assert parameters["page"]["schema"]["type"] == "integer"
assert parameters["limit"]["schema"]["type"] == "integer"
assert parameters["language"]["schema"]["enum"] == ["en", "ja", "zh"]
@@ -1494,3 +1494,19 @@ def test_agent_skill_bindings_rejects_invalid_payload(app: Flask, request_contex
assert status == 400
assert payload["code"] == "invalid_request"
def test_skill_import_documents_required_multipart_file() -> None:
from flask_restx.swagger import Swagger
from controllers.console import api
resource = Swagger(api).serialize_resource(console_ns, WorkspaceSkillImportApi, "/workspaces/current/skills/import")
assert resource is not None
operation = resource["post"]
body = operation["requestBody"]
assert body["required"] is True
schema = body["content"]["multipart/form-data"]["schema"]
assert schema["required"] == ["file"]
assert schema["properties"]["file"]["type"] == "string"
assert schema["properties"]["file"]["format"] == "binary"
+56
View File
@@ -0,0 +1,56 @@
"""Collect coverage from the OpenAPI tools' real process boundaries."""
import os
from pathlib import Path
import coverage
import pytest
@pytest.fixture(autouse=True)
def openapi_subprocess_coverage(
request: pytest.FixtureRequest, monkeypatch: pytest.MonkeyPatch, tmp_path: Path
) -> None:
if request.path.name not in {"test_cached_console_openapi.py", "test_generate_swagger_specs.py"}:
return
current = coverage.Coverage.current()
if current is None:
return
# Scope process instrumentation to these CLI tests instead of changing how
# every backend test launches subprocesses. pytest-cov combines the parallel
# data files with its own report after all fixtures have torn down.
config = tmp_path / "subprocess-coverage.ini"
api_root = Path(__file__).resolve().parents[3]
data_file = current.get_option("run:data_file")
assert isinstance(data_file, str)
data_file = str(Path(data_file).absolute())
omitted = current.get_option("run:omit") or []
assert isinstance(omitted, list)
# Children run from temporary directories. Preserve the parent report's
# exclusions, resolving repository-relative patterns before changing cwd.
isolated_dev = tmp_path / "api/dev"
sources = [str(api_root)]
if request.path.name == "test_cached_console_openapi.py":
sources.append(str(isolated_dev))
omit = "\n ".join(
[str(Path(pattern).absolute()) for pattern in omitted]
+ [
str(isolated_dev / name)
for name in ("__init__.py", "generate_swagger_specs.py", "export_console_openapi.py")
]
)
patches = ["subprocess", "_exit"]
if hasattr(os, "fork"):
patches.extend(["fork", "execv"])
config.write_text(
"[run]\n"
f"data_file = {data_file}\n"
f"branch = {current.get_option('run:branch')}\n"
"parallel = true\n"
"source =\n " + "\n ".join(sources) + "\n"
f"omit =\n {omit}\n"
f"patch = {', '.join(patches)}\n"
)
monkeypatch.setenv("COVERAGE_PROCESS_START", str(config))
# CI supplies a relative COVERAGE_FILE, which takes precedence over the ini.
monkeypatch.setenv("COVERAGE_FILE", data_file)
@@ -0,0 +1,202 @@
"""Exercise the actual cache client/server, with small isolated backend modules."""
import concurrent.futures
import json
import os
import shutil
import subprocess
import sys
import tempfile
from collections.abc import Iterator
from dataclasses import dataclass, field
from pathlib import Path
import pytest
pytestmark = pytest.mark.skipif(not hasattr(os, "fork"), reason="The memory export server uses POSIX isolation")
@dataclass
class CacheClient:
api: Path
env: dict[str, str]
used_envs: list[dict[str, str]] = field(default_factory=list)
def request(self, *, setting: str | None = None, check: bool = True) -> subprocess.CompletedProcess[str]:
request_env = self.env if setting is None else {**self.env, "OPENAPI_TEST_SETTING": setting}
self.used_envs.append(request_env)
return subprocess.run(
[sys.executable, str(self.api / "dev/cached_console_openapi.py")],
cwd=self.api.parent,
env=request_env,
capture_output=True,
text=True,
timeout=30,
check=check,
)
def export(self, *, setting: str | None = None) -> dict[str, str | int | None]:
return json.loads(self.request(setting=setting).stdout)["console"]
@pytest.fixture
def backend(tmp_path: Path) -> Iterator[CacheClient]:
api = tmp_path / "api"
(api / "dev").mkdir(parents=True)
script = api / "dev/cached_console_openapi.py"
original = Path(__file__).resolve().parents[3] / "dev/cached_console_openapi.py"
shutil.copyfile(original, script)
modules = {
"dev/__init__.py": "",
"dev/generate_swagger_specs.py": "def apply_runtime_defaults(): pass\n",
"models.py": "import secrets\nVALUE = 'v1'\nSNAPSHOT = secrets.token_hex(8)\n",
"controllers/fixture.py": "FIELD = 'integer'\n",
"core/mcp/types.py": "",
"dify_agent/protocol/schemas.py": "",
"graphon/nodes/parameter_extractor/entities.py": "",
"services/knowledge_fs/product_dto.py": "",
"dev/export_console_openapi.py": """
import json, os
def main():
from controllers.fixture import FIELD
from models import VALUE, SNAPSHOT
print(json.dumps({'console': {'field': FIELD, 'model': VALUE, 'pid': os.getpid(),
'snapshot': SNAPSHOT, 'setting': os.getenv('OPENAPI_TEST_SETTING')}, 'fast': {}}))
if __name__ == '__main__': main()
""",
}
for filename, content in modules.items():
path = api / filename
path.parent.mkdir(parents=True, exist_ok=True)
for parent in path.parents:
if parent == api:
break
(parent / "__init__.py").touch()
path.write_text(content)
client = CacheClient(api, {**os.environ, "PYTHONPATH": str(api)})
yield client
for request_env in client.used_envs:
subprocess.run(
[sys.executable, str(script), "--stop"],
cwd=tmp_path,
env=request_env,
capture_output=True,
timeout=10,
check=True,
)
def test_memory_cache_is_shared_and_ignores_test_files(backend: CacheClient) -> None:
api, call = backend.api, backend.export
first = call()
assert call() == first
(api / "tests").mkdir()
(api / "tests/test_unrelated.py").write_text("# unrelated test\n")
assert call() == first
with concurrent.futures.ThreadPoolExecutor(max_workers=4) as pool:
assert all(result == first for result in pool.map(lambda _: call(), range(4)))
assert not list(api.rglob("*.json"))
assert not list(api.rglob("*.pyc"))
def test_changed_controller_is_fresh_and_preloaded_dependency_restarts_snapshot(backend: CacheClient) -> None:
api, call = backend.api, backend.export
first = call()
controller = api / "controllers/fixture.py"
controller.write_text("FIELD = 'number'\n")
second = call()
assert second["field"] == "number"
assert second["pid"] != first["pid"]
assert second["snapshot"] == first["snapshot"]
# Same-size edit with unchanged mtime must not revive a stale .pyc or snapshot.
model = api / "models.py"
stat = model.stat()
model.write_text(model.read_text().replace("'v1'", "'v2'"))
os.utime(model, ns=(stat.st_atime_ns, stat.st_mtime_ns))
third = call()
assert third["model"] == "v2"
assert third["snapshot"] != second["snapshot"]
assert third["field"] == "number"
def test_export_errors_never_return_old_contracts_and_recover_after_fix(backend: CacheClient) -> None:
api, call = backend.api, backend.export
first = call()
controller = api / "controllers/fixture.py"
controller.write_text("FIELD = syntax error\n")
failure = backend.request(check=False)
assert failure.returncode != 0
assert not failure.stdout
assert "SyntaxError" in failure.stderr
controller.write_text("FIELD = 'string'\n")
fixed = call()
assert fixed["field"] == "string"
assert fixed["pid"] != first["pid"]
def test_environment_and_file_additions_invalidate_memory_cache(backend: CacheClient) -> None:
api, call = backend.api, backend.export
first = call()
variant = call(setting="variant")
assert variant["setting"] == "variant"
assert variant["snapshot"] != first["snapshot"]
(api / "new_dependency.py").write_text("VALUE = 1\n")
added = call()
assert added["snapshot"] != first["snapshot"]
(api / "new_dependency.py").unlink()
assert call()["snapshot"] != added["snapshot"]
def test_native_threads_use_fresh_exports_and_propagate_failures(backend: CacheClient) -> None:
model = backend.api / "models.py"
model.write_text(
model.read_text()
+ "import threading, time\n"
+ "threading.Thread(target=time.sleep, args=(60,), daemon=True).start()\n"
)
first = backend.export()
controller = backend.api / "controllers/fixture.py"
controller.write_text("FIELD = 'string'\n")
changed = backend.export()
assert changed["field"] == "string"
assert changed["snapshot"] != first["snapshot"]
controller.write_text("FIELD = syntax error\n")
failure = backend.request(check=False)
assert failure.returncode != 0
assert not failure.stdout
assert "SyntaxError" in failure.stderr
def test_invalid_export_payload_does_not_replace_a_valid_contract(backend: CacheClient) -> None:
first = backend.export()
exporter = backend.api / "dev/export_console_openapi.py"
original = exporter.read_text()
exporter.write_text("def main(): print('{\"unexpected\": {}}')\n")
failure = backend.request(check=False)
assert failure.returncode != 0
assert not failure.stdout
assert "Invalid Console export response" in failure.stderr
exporter.write_text(original)
assert backend.export()["field"] == first["field"]
def test_failed_preload_falls_back_to_fresh_exports(backend: CacheClient) -> None:
(backend.api / "core/mcp/types.py").write_text("raise RuntimeError('Cannot preload this dependency')\n")
first = backend.export()
(backend.api / "controllers/fixture.py").write_text("FIELD = 'string'\n")
changed = backend.export()
assert changed["field"] == "string"
assert changed["snapshot"] != first["snapshot"]
def test_socket_directory_must_be_private(monkeypatch: pytest.MonkeyPatch) -> None:
from dev.cached_console_openapi import socket_path
# Keep this short enough for the Unix socket path limit on macOS.
with tempfile.TemporaryDirectory(prefix="dify-ipc-", dir="/tmp") as directory:
monkeypatch.setattr(tempfile, "tempdir", directory)
path = socket_path()
assert path.parent.stat().st_mode & 0o077 == 0
path.parent.chmod(0o755)
with pytest.raises(PermissionError, match="private to the current user"):
socket_path()
@@ -7,6 +7,7 @@ import subprocess
import sys
from pathlib import Path
import pytest
from jsonschema import Draft202012Validator
from tests.helpers.unit.config_override import apply_config_overrides
@@ -71,6 +72,39 @@ def _reset_schema_cache(api):
api.__dict__.pop("__schema__", None)
@pytest.mark.timeout(150) # Two cold, coverage-instrumented CLI exports each have a 60-second limit.
def test_console_stdout_export_contains_both_surfaces_without_spec_files(tmp_path: Path):
script = Path(__file__).resolve().parents[3] / "dev" / "export_console_openapi.py"
result = subprocess.run(
[sys.executable, str(script)], cwd=tmp_path, capture_output=True, text=True, check=True, timeout=60
)
documents = json.loads(result.stdout)
assert set(documents) == {"console", "fast"}
for document in documents.values():
assert document["openapi"].startswith("3.")
assert document["paths"]
for item in document["paths"].values():
for operation in item.values():
if not isinstance(operation, dict) or "responses" not in operation:
continue
origin = operation["x-source-location"]
source_line = Path(origin["file"]).read_text().splitlines()[origin["line"] - 1].lstrip()
assert source_line.startswith(("def ", "async def "))
datasets = documents["console"]["paths"]["/datasets"]["get"]["x-source-location"]
assert datasets["file"].endswith("/controllers/console/datasets/datasets.py")
cached_script = script.with_name("cached_console_openapi.py")
try:
cached = subprocess.run(
[sys.executable, str(cached_script)], cwd=tmp_path, capture_output=True, text=True, check=True, timeout=60
)
assert json.loads(cached.stdout) == documents
finally:
subprocess.run(
[sys.executable, str(cached_script), "--stop"], cwd=tmp_path, capture_output=True, check=True, timeout=10
)
assert not list(tmp_path.rglob("*.json"))
def test_generate_specs_writes_all_openapi_files(tmp_path: Path):
module = _load_generate_swagger_specs_module()
@@ -104,6 +138,11 @@ def test_generate_specs_writes_all_openapi_files(tmp_path: Path):
assert "/enterprise/apps/{app_id}/dsl" in inner_payload["paths"]
def test_console_only_export_matches_the_full_export():
module = _load_generate_swagger_specs_module()
assert module.export_console_spec() == module.export_specs()["console-openapi.json"]
def test_generate_specs_match_live_openapi_payloads(tmp_path: Path):
module = _load_generate_swagger_specs_module()
app = module.create_spec_app()
@@ -296,6 +335,29 @@ def test_finalize_openapi_payload_only_marks_explicit_binary_responses():
assert "x-dify-binary-response-media-types" not in operation
def test_console_file_and_audio_responses_declare_binary_success_and_json_errors(tmp_path: Path):
module = _load_generate_swagger_specs_module()
module.generate_specs(tmp_path)
payload = json.loads((tmp_path / "console-openapi.json").read_text(encoding="utf-8"))
audio_media = {"audio/aac", "audio/flac", "audio/mp4", "audio/mpeg", "audio/ogg", "audio/wav", "audio/webm"}
operations = [
("/workspaces/current/plugin/asset", "get", {"application/octet-stream"}),
("/workspaces/current/plugin/icon", "get", {"*/*"}),
("/workspaces/current/skills/{skill_id}/files/content", "get", {"*/*"}),
("/installed-apps/{installed_app_id}/text-to-audio", "post", audio_media),
("/trial-apps/{app_id}/text-to-audio", "post", audio_media),
]
for path, method, media_types in operations:
responses = payload["paths"][path][method]["responses"]
assert responses["200"]["content"] == {
media_type: {"schema": {"type": "string", "format": "binary"}} for media_type in media_types
}, path
errors = {status: response for status, response in responses.items() if status.startswith(("4", "5"))}
assert errors, path
for status, response in errors.items():
assert set(response["content"]) == {"application/json"}, (path, status)
def test_system_features_specs_exclude_backend_only_fields(tmp_path: Path):
module = _load_generate_swagger_specs_module()
@@ -0,0 +1,241 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zAccountNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_not_found'),
status: z.literal(400),
}),
))()
const zInvalidEmailError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_email'),
status: z.literal(400),
}),
))()
const zInvalidOrExpiredTokenError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_or_expired_token'),
status: z.literal(400),
}),
))()
const zEmailChangeRateLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_change_rate_limit_exceeded'),
status: z.literal(429),
}),
))()
const zEmailSendIpLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_send_ip_limit'),
status: z.literal(429),
}),
))()
const zAccountInFreezeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_in_freeze'),
status: z.literal(400),
}),
))()
const zEmailAlreadyInUseError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_already_in_use'),
status: z.literal(400),
}),
))()
const zEmailDomainSuspendedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_domain_suspended'),
status: z.literal(400),
}),
))()
const zEmailCodeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_code_error'),
status: z.literal(400),
}),
))()
const zEmailChangeLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_change_limit'),
status: z.literal(429),
}),
))()
const zInvalidAccountDeletionCodeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_account_deletion_code'),
status: z.literal(400),
}),
))()
const zEmailCodeAccountDeletionRateLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_code_account_deletion_rate_limit_exceeded'),
status: z.literal(429),
}),
))()
const zEducationActivateLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('education_activate_limit'),
status: z.literal(429),
}),
))()
const zEducationVerifyLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('education_verify_limit'),
status: z.literal(429),
}),
))()
const zAccountAlreadyInitedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_already_inited'),
status: z.literal(400),
}),
))()
const zInvalidInvitationCodeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_invitation_code'),
status: z.literal(400),
}),
))()
const zMissingInvitationCodeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('missing_invitation_code'),
status: z.literal(400),
}),
))()
const zCurrentPasswordIncorrectError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('current_password_incorrect'),
status: z.literal(400),
}),
))()
const zInvalidAccountPasswordError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_account_password'),
status: z.literal(400),
}),
))()
export const postErrors = { account_not_found: { status: 400, data: zAccountNotFoundError } }
export const post2Errors = {
account_in_freeze: { status: 400, data: zAccountInFreezeError },
email_already_in_use: { status: 400, data: zEmailAlreadyInUseError },
email_domain_suspended: { status: 400, data: zEmailDomainSuspendedError },
}
export const post3Errors = {
account_in_freeze: { status: 400, data: zAccountInFreezeError },
account_not_found: { status: 400, data: zAccountNotFoundError },
email_already_in_use: { status: 400, data: zEmailAlreadyInUseError },
email_domain_suspended: { status: 400, data: zEmailDomainSuspendedError },
invalid_or_expired_token: { status: 400, data: zInvalidOrExpiredTokenError },
}
export const post4Errors = {
email_change_limit: { status: 429, data: zEmailChangeLimitError },
email_code_error: { status: 400, data: zEmailCodeError },
invalid_email: { status: 400, data: zInvalidEmailError },
invalid_or_expired_token: { status: 400, data: zInvalidOrExpiredTokenError },
}
export const post5Errors = {
account_not_found: { status: 400, data: zAccountNotFoundError },
email_change_rate_limit_exceeded: { status: 429, data: zEmailChangeRateLimitExceededError },
email_send_ip_limit: { status: 429, data: zEmailSendIpLimitError },
invalid_email: { status: 400, data: zInvalidEmailError },
invalid_or_expired_token: { status: 400, data: zInvalidOrExpiredTokenError },
}
export const get2Errors = {
account_not_found: { status: 400, data: zAccountNotFoundError },
email_code_account_deletion_rate_limit_exceeded: {
status: 429,
data: zEmailCodeAccountDeletionRateLimitExceededError,
},
}
export const post7Errors = {
invalid_account_deletion_code: { status: 400, data: zInvalidAccountDeletionCodeError },
}
export const get4Errors = {
account_not_found: { status: 400, data: zAccountNotFoundError },
education_verify_limit: { status: 429, data: zEducationVerifyLimitError },
}
export const post8Errors = {
account_not_found: { status: 400, data: zAccountNotFoundError },
education_activate_limit: { status: 429, data: zEducationActivateLimitError },
}
export const post9Errors = {
account_already_inited: { status: 400, data: zAccountAlreadyInitedError },
account_not_found: { status: 400, data: zAccountNotFoundError },
invalid_invitation_code: { status: 400, data: zInvalidInvitationCodeError },
missing_invitation_code: { status: 400, data: zMissingInvitationCodeError },
}
export const post10Errors = { account_not_found: { status: 400, data: zAccountNotFoundError } }
export const post11Errors = { account_not_found: { status: 400, data: zAccountNotFoundError } }
export const post12Errors = { account_not_found: { status: 400, data: zAccountNotFoundError } }
export const post13Errors = {
account_not_found: { status: 400, data: zAccountNotFoundError },
current_password_incorrect: { status: 400, data: zCurrentPasswordIncorrectError },
invalid_account_password: { status: 400, data: zInvalidAccountPasswordError },
}
export const get7Errors = { account_not_found: { status: 400, data: zAccountNotFoundError } }
export const patchErrors = { account_not_found: { status: 400, data: zAccountNotFoundError } }
export const post14Errors = { account_not_found: { status: 400, data: zAccountNotFoundError } }
@@ -0,0 +1,50 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zAccountInFreezeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_in_freeze'),
status: z.literal(400),
}),
))()
const zEmailDomainSuspendedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_domain_suspended'),
status: z.literal(400),
}),
))()
const zAlreadyActivateError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('already_activate'),
status: z.literal(403),
}),
))()
const zInvitationAccountMismatchError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invitation_account_mismatch'),
status: z.literal(403),
}),
))()
export const postErrors = {
account_in_freeze: { status: 400, data: zAccountInFreezeError },
already_activate: { status: 403, data: zAlreadyActivateError },
email_domain_suspended: { status: 400, data: zEmailDomainSuspendedError },
invitation_account_mismatch: { status: 403, data: zInvitationAccountMismatchError },
}
@@ -0,0 +1,675 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zAgentNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_not_found_error'),
status: z.literal(404),
}),
))()
const zAgentNameConflictError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_name_conflict_error'),
status: z.literal(409),
}),
))()
const zAgentNotPublishedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_not_published'),
status: z.literal(409),
}),
))()
const zMaxKeysExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('max_keys_exceeded'),
status: z.literal(400),
}),
))()
const zAppUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_unavailable'),
status: z.literal(400),
}),
))()
const zCompletionRequestError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('completion_request_error'),
status: z.literal(400),
}),
))()
const zModelCurrentlyNotSupportError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('model_currently_not_support'),
status: z.literal(400),
}),
))()
const zNoAudioUploadedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('no_audio_uploaded'),
status: z.literal(400),
}),
))()
const zProviderNotInitializeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_initialize'),
status: z.literal(400),
}),
))()
const zProviderNotSupportSpeechToTextError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_support_speech_to_text'),
status: z.literal(400),
}),
))()
const zProviderQuotaExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_quota_exceeded'),
status: z.literal(400),
}),
))()
const zSpeechToTextDisabledError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('speech_to_text_disabled'),
status: z.literal(400),
}),
))()
const zAgentVersionNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_version_not_found_error'),
status: z.literal(404),
}),
))()
const zAudioTooLargeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('audio_too_large'),
status: z.literal(413),
}),
))()
const zUnsupportedAudioTypeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('unsupported_audio_type'),
status: z.literal(415),
}),
))()
const zRateLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('rate_limit_error'),
status: z.literal(429),
}),
))()
const zAgentBuildSandboxNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_build_sandbox_not_found'),
status: z.literal(404),
}),
))()
const zAgentSoulLockedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_soul_locked_error'),
status: z.literal(400),
}),
))()
const zInvalidComposerConfigError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_composer_config_error'),
status: z.literal(400),
}),
))()
const zPlaintextSecretNotAllowedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('plaintext_secret_not_allowed_error'),
status: z.literal(400),
}),
))()
const zAgentHomeSnapshotTooLargeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_home_snapshot_too_large'),
status: z.literal(413),
}),
))()
const zAgentHomeSnapshotCreateFailedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_home_snapshot_create_failed'),
status: z.literal(502),
}),
))()
const zAppSuggestedQuestionsAfterAnswerDisabledError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_suggested_questions_after_answer_disabled'),
status: z.literal(403),
}),
))()
const zAgentModelNotConfiguredError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_model_not_configured'),
status: z.literal(400),
}),
))()
const zNoActiveBindingError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('no_active_binding'),
status: z.literal(404),
}),
))()
const zAgentBackendUnreachableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_backend_unreachable'),
status: z.literal(502),
}),
))()
const zInspectorUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('inspector_unavailable'),
status: z.literal(503),
}),
))()
const zBindingFileDownloadUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('binding_file_download_unavailable'),
status: z.literal(502),
}),
))()
const zProviderNotSupportTextToSpeechError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_support_text_to_speech'),
status: z.literal(400),
}),
))()
const zInvalidTracingConfigError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_tracing_config'),
status: z.literal(400),
}),
))()
const zTracingProviderUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('tracing_provider_unavailable'),
status: z.literal(400),
}),
))()
const zUnsupportedTracingProviderError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('unsupported_tracing_provider'),
status: z.literal(400),
}),
))()
const zTraceConfigNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('trace_config_not_found'),
status: z.literal(404),
}),
))()
const zTracingConfigConflictError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('tracing_config_conflict'),
status: z.literal(409),
}),
))()
const zTracingConfigProcessingFailedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('tracing_config_processing_failed'),
status: z.literal(500),
}),
))()
const zAppNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_not_found'),
status: z.literal(404),
}),
))()
const zTracingConfigVerificationFailedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('tracing_config_verification_failed'),
status: z.literal(400),
}),
))()
const zTraceConfigAlreadyExistsError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('trace_config_already_exists'),
status: z.literal(409),
}),
))()
const zTracingNodeNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('tracing_node_not_found'),
status: z.literal(404),
}),
))()
const zTracingSourceNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('tracing_source_not_found'),
status: z.literal(404),
}),
))()
const zTracingRunNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('tracing_run_not_found'),
status: z.literal(404),
}),
))()
const zTracingAlreadyAcceptedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('tracing_already_accepted'),
status: z.literal(409),
}),
))()
const zTracingDuplicateAcknowledgementRequiredError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('tracing_duplicate_acknowledgement_required'),
status: z.literal(409),
}),
))()
const zTracingRetryNotAllowedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('tracing_retry_not_allowed'),
status: z.literal(409),
}),
))()
export const get2Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const postErrors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_not_published: { status: 409, data: zAgentNotPublishedError },
}
export const post2Errors = {
agent_not_published: { status: 409, data: zAgentNotPublishedError },
max_keys_exceeded: { status: 400, data: zMaxKeysExceededError },
}
export const post3Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
audio_too_large: { status: 413, data: zAudioTooLargeError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
no_audio_uploaded: { status: 400, data: zNoAudioUploadedError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_not_support_speech_to_text: { status: 400, data: zProviderNotSupportSpeechToTextError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
speech_to_text_disabled: { status: 400, data: zSpeechToTextDisabledError },
unsupported_audio_type: { status: 415, data: zUnsupportedAudioTypeError },
}
export const post4Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
rate_limit_error: { status: 429, data: zRateLimitError },
}
export const post5Errors = {
agent_build_sandbox_not_found: { status: 404, data: zAgentBuildSandboxNotFoundError },
agent_home_snapshot_create_failed: { status: 502, data: zAgentHomeSnapshotCreateFailedError },
agent_home_snapshot_too_large: { status: 413, data: zAgentHomeSnapshotTooLargeError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
invalid_composer_config_error: { status: 400, data: zInvalidComposerConfigError },
plaintext_secret_not_allowed_error: { status: 400, data: zPlaintextSecretNotAllowedError },
}
export const post6Errors = {
agent_build_sandbox_not_found: { status: 404, data: zAgentBuildSandboxNotFoundError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
}
export const delete2Errors = {
agent_build_sandbox_not_found: { status: 404, data: zAgentBuildSandboxNotFoundError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
}
export const get4Errors = {
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
}
export const putErrors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_soul_locked_error: { status: 400, data: zAgentSoulLockedError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
}
export const get5Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
app_suggested_questions_after_answer_disabled: {
status: 403,
data: zAppSuggestedQuestionsAfterAnswerDisabledError,
},
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
export const post7Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get6Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get7Errors = {
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
}
export const post8Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_soul_locked_error: { status: 400, data: zAgentSoulLockedError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
invalid_composer_config_error: { status: 400, data: zInvalidComposerConfigError },
plaintext_secret_not_allowed_error: { status: 400, data: zPlaintextSecretNotAllowedError },
}
export const get8Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
}
export const put2Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_soul_locked_error: { status: 400, data: zAgentSoulLockedError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
invalid_composer_config_error: { status: 400, data: zInvalidComposerConfigError },
plaintext_secret_not_allowed_error: { status: 400, data: zPlaintextSecretNotAllowedError },
}
export const get9Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get10Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const delete3Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get11Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const post9Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get12Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const post10Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get13Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get14Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get15Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get16Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get17Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const delete4Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get18Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const post11Errors = {
agent_name_conflict_error: { status: 409, data: zAgentNameConflictError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
}
export const post12Errors = {
agent_build_sandbox_not_found: { status: 404, data: zAgentBuildSandboxNotFoundError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
}
export const post13Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const post14Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get19Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get20Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get21Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get22Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const post15Errors = {
agent_model_not_configured: { status: 400, data: zAgentModelNotConfiguredError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
invalid_composer_config_error: { status: 400, data: zInvalidComposerConfigError },
plaintext_secret_not_allowed_error: { status: 400, data: zPlaintextSecretNotAllowedError },
}
export const get23Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const post16Errors = {
agent_backend_unreachable: { status: 502, data: zAgentBackendUnreachableError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
binding_file_download_unavailable: { status: 502, data: zBindingFileDownloadUnavailableError },
inspector_unavailable: { status: 503, data: zInspectorUnavailableError },
no_active_binding: { status: 404, data: zNoActiveBindingError },
}
export const get24Errors = {
agent_backend_unreachable: { status: 502, data: zAgentBackendUnreachableError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
inspector_unavailable: { status: 503, data: zInspectorUnavailableError },
no_active_binding: { status: 404, data: zNoActiveBindingError },
}
export const get25Errors = {
agent_backend_unreachable: { status: 502, data: zAgentBackendUnreachableError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
inspector_unavailable: { status: 503, data: zInspectorUnavailableError },
no_active_binding: { status: 404, data: zNoActiveBindingError },
}
export const get26Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
no_active_binding: { status: 404, data: zNoActiveBindingError },
}
export const get27Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get28Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
export const post17Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_not_support_text_to_speech: { status: 400, data: zProviderNotSupportTextToSpeechError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
export const post18Errors = {
invalid_tracing_config: { status: 400, data: zInvalidTracingConfigError },
trace_config_not_found: { status: 404, data: zTraceConfigNotFoundError },
tracing_config_conflict: { status: 409, data: zTracingConfigConflictError },
tracing_config_processing_failed: { status: 500, data: zTracingConfigProcessingFailedError },
tracing_provider_unavailable: { status: 400, data: zTracingProviderUnavailableError },
unsupported_tracing_provider: { status: 400, data: zUnsupportedTracingProviderError },
}
export const get30Errors = {
unsupported_tracing_provider: { status: 400, data: zUnsupportedTracingProviderError },
}
export const delete5Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
trace_config_not_found: { status: 404, data: zTraceConfigNotFoundError },
tracing_config_processing_failed: { status: 500, data: zTracingConfigProcessingFailedError },
unsupported_tracing_provider: { status: 400, data: zUnsupportedTracingProviderError },
}
export const get31Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
tracing_config_processing_failed: { status: 500, data: zTracingConfigProcessingFailedError },
tracing_provider_unavailable: { status: 400, data: zTracingProviderUnavailableError },
unsupported_tracing_provider: { status: 400, data: zUnsupportedTracingProviderError },
}
export const patchErrors = {
app_not_found: { status: 404, data: zAppNotFoundError },
invalid_tracing_config: { status: 400, data: zInvalidTracingConfigError },
trace_config_not_found: { status: 404, data: zTraceConfigNotFoundError },
tracing_config_conflict: { status: 409, data: zTracingConfigConflictError },
tracing_config_processing_failed: { status: 500, data: zTracingConfigProcessingFailedError },
tracing_config_verification_failed: { status: 400, data: zTracingConfigVerificationFailedError },
tracing_provider_unavailable: { status: 400, data: zTracingProviderUnavailableError },
unsupported_tracing_provider: { status: 400, data: zUnsupportedTracingProviderError },
}
export const post19Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
invalid_tracing_config: { status: 400, data: zInvalidTracingConfigError },
trace_config_already_exists: { status: 409, data: zTraceConfigAlreadyExistsError },
tracing_config_processing_failed: { status: 500, data: zTracingConfigProcessingFailedError },
tracing_config_verification_failed: { status: 400, data: zTracingConfigVerificationFailedError },
tracing_provider_unavailable: { status: 400, data: zTracingProviderUnavailableError },
unsupported_tracing_provider: { status: 400, data: zUnsupportedTracingProviderError },
}
export const post20Errors = {
tracing_already_accepted: { status: 409, data: zTracingAlreadyAcceptedError },
tracing_duplicate_acknowledgement_required: {
status: 409,
data: zTracingDuplicateAcknowledgementRequiredError,
},
tracing_node_not_found: { status: 404, data: zTracingNodeNotFoundError },
tracing_retry_not_allowed: { status: 409, data: zTracingRetryNotAllowedError },
tracing_run_not_found: { status: 404, data: zTracingRunNotFoundError },
tracing_source_not_found: { status: 404, data: zTracingSourceNotFoundError },
}
export const get32Errors = {
tracing_node_not_found: { status: 404, data: zTracingNodeNotFoundError },
tracing_source_not_found: { status: 404, data: zTracingSourceNotFoundError },
}
export const post21Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
}
export const get33Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
}
export const get34Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const delete6Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const get35Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const put3Errors = {
agent_name_conflict_error: { status: 409, data: zAgentNameConflictError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
}
export const get36Errors = { agent_not_found_error: { status: 404, data: zAgentNotFoundError } }
export const post22Errors = {
agent_name_conflict_error: { status: 409, data: zAgentNameConflictError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
}
@@ -0,0 +1,38 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zUnsupportedDataSourceApiKeyAuthProviderError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('unsupported_data_source_api_key_auth_provider'),
status: z.literal(400),
}),
))()
const zDataSourceApiKeyAuthProviderUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('data_source_api_key_auth_provider_unavailable'),
status: z.literal(502),
}),
))()
export const postErrors = {
data_source_api_key_auth_provider_unavailable: {
status: 502,
data: zDataSourceApiKeyAuthProviderUnavailableError,
},
unsupported_data_source_api_key_auth_provider: {
status: 400,
data: zUnsupportedDataSourceApiKeyAuthProviderError,
},
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,37 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zBillingOperationFailedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('billing_operation_failed'),
status: z.literal(502),
}),
))()
const zBillingUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('billing_unavailable'),
status: z.literal(503),
}),
))()
export const getErrors = {
billing_operation_failed: { status: 502, data: zBillingOperationFailedError },
billing_unavailable: { status: 503, data: zBillingUnavailableError },
}
export const get2Errors = {
billing_operation_failed: { status: 502, data: zBillingOperationFailedError },
billing_unavailable: { status: 503, data: zBillingUnavailableError },
}
@@ -0,0 +1,41 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zComplianceRateLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('compliance_rate_limit'),
status: z.literal(429),
}),
))()
const zBillingOperationFailedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('billing_operation_failed'),
status: z.literal(502),
}),
))()
const zBillingUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('billing_unavailable'),
status: z.literal(503),
}),
))()
export const getErrors = {
billing_operation_failed: { status: 502, data: zBillingOperationFailedError },
billing_unavailable: { status: 503, data: zBillingUnavailableError },
compliance_rate_limit: { status: 429, data: zComplianceRateLimitError },
}
@@ -0,0 +1,21 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zInvalidActionError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_action'),
status: z.literal(400),
}),
))()
export const patchErrors = { invalid_action: { status: 400, data: zInvalidActionError } }
@@ -0,0 +1,265 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zDatasetNameDuplicateError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('dataset_name_duplicate'),
status: z.literal(409),
}),
))()
const zMaxKeysExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('max_keys_exceeded'),
status: z.literal(400),
}),
))()
const zProviderNotInitializeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_initialize'),
status: z.literal(400),
}),
))()
const zDatasetAccessDeniedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('dataset_access_denied'),
status: z.literal(403),
}),
))()
const zIndexingEstimateError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('indexing_estimate_error'),
status: z.literal(500),
}),
))()
const zModelCurrentlyNotSupportError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('model_currently_not_support'),
status: z.literal(400),
}),
))()
const zProviderQuotaExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_quota_exceeded'),
status: z.literal(400),
}),
))()
const zDocumentAlreadyFinishedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('document_already_finished'),
status: z.literal(400),
}),
))()
const zInvalidActionError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_action'),
status: z.literal(400),
}),
))()
const zInvalidMetadataError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_metadata'),
status: z.literal(400),
}),
))()
const zDocumentIndexingError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('document_indexing'),
status: z.literal(400),
}),
))()
const zArchivedDocumentImmutableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('archived_document_immutable'),
status: z.literal(403),
}),
))()
const zChildChunkIndexingError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('child_chunk_indexing_error'),
status: z.literal(500),
}),
))()
const zChildChunkDeleteIndexError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('child_chunk_delete_index_error'),
status: z.literal(500),
}),
))()
const zCompletionRequestError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('completion_request_error'),
status: z.literal(400),
}),
))()
export const postErrors = { max_keys_exceeded: { status: 400, data: zMaxKeysExceededError } }
export const post2Errors = {
dataset_name_duplicate: { status: 409, data: zDatasetNameDuplicateError },
}
export const delete2Errors = {
dataset_name_duplicate: { status: 409, data: zDatasetNameDuplicateError },
}
export const get5Errors = {
dataset_name_duplicate: { status: 409, data: zDatasetNameDuplicateError },
}
export const patchErrors = {
dataset_name_duplicate: { status: 409, data: zDatasetNameDuplicateError },
}
export const post3Errors = {
dataset_name_duplicate: { status: 409, data: zDatasetNameDuplicateError },
}
export const post4Errors = {
dataset_access_denied: { status: 403, data: zDatasetAccessDeniedError },
indexing_estimate_error: { status: 500, data: zIndexingEstimateError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
}
export const post5Errors = {
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
export const post6Errors = {
indexing_estimate_error: { status: 500, data: zIndexingEstimateError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
}
export const get13Errors = {
dataset_access_denied: { status: 403, data: zDatasetAccessDeniedError },
document_already_finished: { status: 400, data: zDocumentAlreadyFinishedError },
indexing_estimate_error: { status: 500, data: zIndexingEstimateError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
}
export const patch2Errors = { invalid_action: { status: 400, data: zInvalidActionError } }
export const get16Errors = {
dataset_access_denied: { status: 403, data: zDatasetAccessDeniedError },
document_already_finished: { status: 400, data: zDocumentAlreadyFinishedError },
indexing_estimate_error: { status: 500, data: zIndexingEstimateError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
}
export const get18Errors = {
dataset_access_denied: { status: 403, data: zDatasetAccessDeniedError },
}
export const patch3Errors = {
archived_document_immutable: { status: 403, data: zArchivedDocumentImmutableError },
document_indexing: { status: 400, data: zDocumentIndexingError },
}
export const patch4Errors = {
archived_document_immutable: { status: 403, data: zArchivedDocumentImmutableError },
document_indexing: { status: 400, data: zDocumentIndexingError },
}
export const patch5Errors = { invalid_action: { status: 400, data: zInvalidActionError } }
export const patch6Errors = {
invalid_action: { status: 400, data: zInvalidActionError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
}
export const post12Errors = {
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
}
export const delete3Errors = {
child_chunk_delete_index_error: { status: 500, data: zChildChunkDeleteIndexError },
}
export const patch7Errors = {
child_chunk_indexing_error: { status: 500, data: zChildChunkIndexingError },
}
export const patch8Errors = {
child_chunk_indexing_error: { status: 500, data: zChildChunkIndexingError },
}
export const post14Errors = {
child_chunk_indexing_error: { status: 500, data: zChildChunkIndexingError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
}
export const patch9Errors = {
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
}
export const get23Errors = {
archived_document_immutable: { status: 403, data: zArchivedDocumentImmutableError },
}
export const get24Errors = { invalid_metadata: { status: 400, data: zInvalidMetadataError } }
export const post15Errors = {
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
export const post16Errors = {
dataset_name_duplicate: { status: 409, data: zDatasetNameDuplicateError },
}
export const post17Errors = {
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
export const get31Errors = {
dataset_access_denied: { status: 403, data: zDatasetAccessDeniedError },
}
export const post23Errors = { max_keys_exceeded: { status: 400, data: zMaxKeysExceededError } }
export const post24Errors = {
dataset_name_duplicate: { status: 409, data: zDatasetNameDuplicateError },
}
@@ -0,0 +1,167 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zAccountBannedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_banned'),
status: z.literal(400),
}),
))()
const zAccountInFreezeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_in_freeze'),
status: z.literal(400),
}),
))()
const zEmailDomainSuspendedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_domain_suspended'),
status: z.literal(400),
}),
))()
const zTurnstileVerificationFailedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('turnstile_verification_failed'),
status: z.literal(400),
}),
))()
const zEmailCodeLoginRateLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_code_login_rate_limit_exceeded'),
status: z.literal(429),
}),
))()
const zEmailSendIpLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_send_ip_limit'),
status: z.literal(429),
}),
))()
const zEmailCodeLoginServiceUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_code_login_service_unavailable'),
status: z.literal(503),
}),
))()
const zTurnstileServiceUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('turnstile_service_unavailable'),
status: z.literal(503),
}),
))()
const zAccountNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_not_found'),
status: z.literal(400),
}),
))()
const zEmailCodeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_code_error'),
status: z.literal(400),
}),
))()
const zInvalidEmailError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_email'),
status: z.literal(400),
}),
))()
const zInvalidOrExpiredTokenError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_or_expired_token'),
status: z.literal(400),
}),
))()
const zLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('limit_exceeded'),
status: z.literal(400),
}),
))()
const zNormalizedEmailAlreadyInUseError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('normalized_email_already_in_use'),
status: z.literal(400),
}),
))()
const zNotAllowedCreateWorkspaceError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('not_allowed_create_workspace'),
status: z.literal(400),
}),
))()
export const postErrors = {
account_banned: { status: 400, data: zAccountBannedError },
account_in_freeze: { status: 400, data: zAccountInFreezeError },
account_not_found: { status: 400, data: zAccountNotFoundError },
email_code_error: { status: 400, data: zEmailCodeError },
email_code_login_service_unavailable: {
status: 503,
data: zEmailCodeLoginServiceUnavailableError,
},
email_domain_suspended: { status: 400, data: zEmailDomainSuspendedError },
invalid_email: { status: 400, data: zInvalidEmailError },
invalid_or_expired_token: { status: 400, data: zInvalidOrExpiredTokenError },
limit_exceeded: { status: 400, data: zLimitExceededError },
normalized_email_already_in_use: { status: 400, data: zNormalizedEmailAlreadyInUseError },
not_allowed_create_workspace: { status: 400, data: zNotAllowedCreateWorkspaceError },
turnstile_service_unavailable: { status: 503, data: zTurnstileServiceUnavailableError },
turnstile_verification_failed: { status: 400, data: zTurnstileVerificationFailedError },
}
export const post2Errors = {
account_banned: { status: 400, data: zAccountBannedError },
account_in_freeze: { status: 400, data: zAccountInFreezeError },
email_code_login_rate_limit_exceeded: {
status: 429,
data: zEmailCodeLoginRateLimitExceededError,
},
email_code_login_service_unavailable: {
status: 503,
data: zEmailCodeLoginServiceUnavailableError,
},
email_domain_suspended: { status: 400, data: zEmailDomainSuspendedError },
email_send_ip_limit: { status: 429, data: zEmailSendIpLimitError },
turnstile_service_unavailable: { status: 503, data: zTurnstileServiceUnavailableError },
turnstile_verification_failed: { status: 400, data: zTurnstileVerificationFailedError },
}
@@ -0,0 +1,131 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zAccountInFreezeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_in_freeze'),
status: z.literal(400),
}),
))()
const zEmailAlreadyInUseError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_already_in_use'),
status: z.literal(400),
}),
))()
const zEmailDomainSuspendedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_domain_suspended'),
status: z.literal(400),
}),
))()
const zInvalidOrExpiredTokenError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_or_expired_token'),
status: z.literal(400),
}),
))()
const zLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('limit_exceeded'),
status: z.literal(400),
}),
))()
const zNormalizedEmailAlreadyInUseError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('normalized_email_already_in_use'),
status: z.literal(400),
}),
))()
const zPasswordMismatchError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('password_mismatch'),
status: z.literal(400),
}),
))()
const zEmailRegisterRateLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_register_rate_limit_exceeded'),
status: z.literal(429),
}),
))()
const zEmailSendIpLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_send_ip_limit'),
status: z.literal(429),
}),
))()
const zEmailCodeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_code_error'),
status: z.literal(400),
}),
))()
const zInvalidEmailError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_email'),
status: z.literal(400),
}),
))()
const zEmailRegisterLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_register_limit'),
status: z.literal(429),
}),
))()
export const postErrors = {
account_in_freeze: { status: 400, data: zAccountInFreezeError },
email_domain_suspended: { status: 400, data: zEmailDomainSuspendedError },
email_register_rate_limit_exceeded: { status: 429, data: zEmailRegisterRateLimitExceededError },
email_send_ip_limit: { status: 429, data: zEmailSendIpLimitError },
}
export const post2Errors = {
email_code_error: { status: 400, data: zEmailCodeError },
email_register_limit: { status: 429, data: zEmailRegisterLimitError },
invalid_email: { status: 400, data: zInvalidEmailError },
invalid_or_expired_token: { status: 400, data: zInvalidOrExpiredTokenError },
}
export const post3Errors = {
account_in_freeze: { status: 400, data: zAccountInFreezeError },
email_already_in_use: { status: 400, data: zEmailAlreadyInUseError },
email_domain_suspended: { status: 400, data: zEmailDomainSuspendedError },
invalid_or_expired_token: { status: 400, data: zInvalidOrExpiredTokenError },
limit_exceeded: { status: 400, data: zLimitExceededError },
normalized_email_already_in_use: { status: 400, data: zNormalizedEmailAlreadyInUseError },
password_mismatch: { status: 400, data: zPasswordMismatchError },
}
+567
View File
@@ -0,0 +1,567 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
export { delete10Errors as 'DELETE /apps/{app_id}/workflow/comments/{comment_id}' } from './apps/errors.gen.ts'
export { delete10Errors as 'DELETE /knowledge-fs/spaces/{control_space_id}/research-tasks/{task_id}' } from './knowledge-fs/errors.gen.ts'
export { delete11Errors as 'DELETE /apps/{app_id}/workflows/draft/nodes/{node_id}/variables' } from './apps/errors.gen.ts'
export { delete11Errors as 'DELETE /knowledge-fs/spaces/{control_space_id}/sources/{source_id}' } from './knowledge-fs/errors.gen.ts'
export { delete12Errors as 'DELETE /apps/{app_id}/workflows/draft/variables/{variable_id}' } from './apps/errors.gen.ts'
export { delete12Errors as 'DELETE /knowledge-fs/spaces/{control_space_id}' } from './knowledge-fs/errors.gen.ts'
export { delete13Errors as 'DELETE /apps/{app_id}/workflows/draft/variables' } from './apps/errors.gen.ts'
export { delete13Errors as 'DELETE /knowledge-fs/uploads/{upload_id}' } from './knowledge-fs/errors.gen.ts'
export { delete14Errors as 'DELETE /apps/{app_id}/workflows/{workflow_id}' } from './apps/errors.gen.ts'
export { delete16Errors as 'DELETE /workspaces/current/skills/{skill_id}' } from './workspaces/errors.gen.ts'
export { delete2Errors as 'DELETE /agent/{agent_id}/build-draft' } from './agent/errors.gen.ts'
export { delete2Errors as 'DELETE /apps/{app_id}/agent/config/skills/{name}' } from './apps/errors.gen.ts'
export { delete2Errors as 'DELETE /datasets/external-knowledge-api/{external_knowledge_api_id}' } from './datasets/errors.gen.ts'
export { delete2Errors as 'DELETE /installed-apps/{installed_app_id}/saved-messages/{message_id}' } from './installed-apps/errors.gen.ts'
export { delete2Errors as 'DELETE /knowledge-fs/spaces/{control_space_id}/app-bindings/{caller_kind}/{app_id}' } from './knowledge-fs/errors.gen.ts'
export { delete2Errors as 'DELETE /rag/pipelines/{pipeline_id}/workflows/draft/nodes/{node_id}/variables' } from './rag/errors.gen.ts'
export { delete3Errors as 'DELETE /agent/{agent_id}/config/files/{name}' } from './agent/errors.gen.ts'
export { delete3Errors as 'DELETE /datasets/{dataset_id}/documents/{document_id}/segments/{segment_id}/child_chunks/{child_chunk_id}' } from './datasets/errors.gen.ts'
export { delete3Errors as 'DELETE /knowledge-fs/spaces/{control_space_id}/documents/bulk' } from './knowledge-fs/errors.gen.ts'
export { delete3Errors as 'DELETE /rag/pipelines/{pipeline_id}/workflows/draft/variables/{variable_id}' } from './rag/errors.gen.ts'
export { delete4Errors as 'DELETE /agent/{agent_id}/config/skills/{name}' } from './agent/errors.gen.ts'
export { delete4Errors as 'DELETE /knowledge-fs/spaces/{control_space_id}/documents/{document_id}' } from './knowledge-fs/errors.gen.ts'
export { delete4Errors as 'DELETE /rag/pipelines/{pipeline_id}/workflows/draft/variables' } from './rag/errors.gen.ts'
export { delete4Errors as 'DELETE /workspaces/current/members/{member_id}' } from './workspaces/errors.gen.ts'
export { delete5Errors as 'DELETE /agent/{agent_id}/trace-config' } from './agent/errors.gen.ts'
export { delete5Errors as 'DELETE /apps/{app_id}/chat-conversations/{conversation_id}' } from './apps/errors.gen.ts'
export { delete5Errors as 'DELETE /knowledge-fs/spaces/{control_space_id}/golden-questions/{question_id}' } from './knowledge-fs/errors.gen.ts'
export { delete5Errors as 'DELETE /rag/pipelines/{pipeline_id}/workflows/{workflow_id}' } from './rag/errors.gen.ts'
export { delete6Errors as 'DELETE /agent/{agent_id}' } from './agent/errors.gen.ts'
export { delete6Errors as 'DELETE /apps/{app_id}/completion-conversations/{conversation_id}' } from './apps/errors.gen.ts'
export { delete6Errors as 'DELETE /knowledge-fs/spaces/{control_space_id}/jobs/{job_id}' } from './knowledge-fs/errors.gen.ts'
export { delete7Errors as 'DELETE /knowledge-fs/spaces/{control_space_id}/logical-documents/bulk' } from './knowledge-fs/errors.gen.ts'
export { delete8Errors as 'DELETE /apps/{app_id}/trace-config' } from './apps/errors.gen.ts'
export { delete8Errors as 'DELETE /knowledge-fs/spaces/{control_space_id}/logical-documents/{document_id}' } from './knowledge-fs/errors.gen.ts'
export { delete9Errors as 'DELETE /apps/{app_id}/workflow/comments/{comment_id}/replies/{reply_id}' } from './apps/errors.gen.ts'
export { delete9Errors as 'DELETE /knowledge-fs/spaces/{control_space_id}/metadata/{field_id}' } from './knowledge-fs/errors.gen.ts'
export { delete_Errors as 'DELETE /apps/{app_id}/agent/config/files/{name}' } from './apps/errors.gen.ts'
export { delete_Errors as 'DELETE /installed-apps/{installed_app_id}/conversations/{c_id}' } from './installed-apps/errors.gen.ts'
export { delete_Errors as 'DELETE /knowledge-fs/source-provider-preview/jobs/{job_id}' } from './knowledge-fs/errors.gen.ts'
export { get10Errors as 'GET /agent/{agent_id}/config/files/{name}/preview' } from './agent/errors.gen.ts'
export { get10Errors as 'GET /apps/{app_id}/agent/config/skills/{name}/download' } from './apps/errors.gen.ts'
export { get10Errors as 'GET /knowledge-fs/spaces/{control_space_id}/documents/{document_id}/multimodal' } from './knowledge-fs/errors.gen.ts'
export { get10Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/default-workflow-block-configs/{block_type}' } from './rag/errors.gen.ts'
export { get10Errors as 'GET /trial-apps/{app_id}/agent/config/skills' } from './trial-apps/errors.gen.ts'
export { get11Errors as 'GET /agent/{agent_id}/config/files' } from './agent/errors.gen.ts'
export { get11Errors as 'GET /apps/{app_id}/agent/config/skills/{name}/files/content' } from './apps/errors.gen.ts'
export { get11Errors as 'GET /knowledge-fs/spaces/{control_space_id}/documents/{document_id}/outline' } from './knowledge-fs/errors.gen.ts'
export { get11Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/default-workflow-block-configs' } from './rag/errors.gen.ts'
export { get11Errors as 'GET /trial-apps/{app_id}/datasets' } from './trial-apps/errors.gen.ts'
export { get12Errors as 'GET /agent/{agent_id}/config/manifest' } from './agent/errors.gen.ts'
export { get12Errors as 'GET /apps/{app_id}/agent/config/skills/{name}/files/download' } from './apps/errors.gen.ts'
export { get12Errors as 'GET /knowledge-fs/spaces/{control_space_id}/documents/{document_id}/revisions/{revision}/chunks/{chunk_id}' } from './knowledge-fs/errors.gen.ts'
export { get12Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/draft/environment-variables' } from './rag/errors.gen.ts'
export { get12Errors as 'GET /trial-apps/{app_id}/export' } from './trial-apps/errors.gen.ts'
export { get13Errors as 'GET /agent/{agent_id}/config/skills/{name}/download' } from './agent/errors.gen.ts'
export { get13Errors as 'GET /apps/{app_id}/agent/config/skills/{name}/files/preview' } from './apps/errors.gen.ts'
export { get13Errors as 'GET /datasets/{dataset_id}/batch/{batch}/indexing-estimate' } from './datasets/errors.gen.ts'
export { get13Errors as 'GET /knowledge-fs/spaces/{control_space_id}/documents/{document_id}/revisions/{revision}/chunks' } from './knowledge-fs/errors.gen.ts'
export { get13Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/draft/nodes/{node_id}/last-run' } from './rag/errors.gen.ts'
export { get13Errors as 'GET /trial-apps/{app_id}/messages/{message_id}/suggested-questions' } from './trial-apps/errors.gen.ts'
export { get14Errors as 'GET /agent/{agent_id}/config/skills/{name}/files/content' } from './agent/errors.gen.ts'
export { get14Errors as 'GET /apps/{app_id}/agent/config/skills/{name}/inspect' } from './apps/errors.gen.ts'
export { get14Errors as 'GET /knowledge-fs/spaces/{control_space_id}/documents/{document_id}/revisions' } from './knowledge-fs/errors.gen.ts'
export { get14Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/draft/nodes/{node_id}/variables' } from './rag/errors.gen.ts'
export { get14Errors as 'GET /snippets/{snippet_id}/workflows/draft/variables' } from './snippets/errors.gen.ts'
export { get14Errors as 'GET /trial-apps/{app_id}/parameters' } from './trial-apps/errors.gen.ts'
export { get15Errors as 'GET /agent/{agent_id}/config/skills/{name}/files/download' } from './agent/errors.gen.ts'
export { get15Errors as 'GET /apps/{app_id}/agent/config/skills' } from './apps/errors.gen.ts'
export { get15Errors as 'GET /knowledge-fs/spaces/{control_space_id}/documents/{document_id}' } from './knowledge-fs/errors.gen.ts'
export { get15Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/draft/pre-processing/parameters' } from './rag/errors.gen.ts'
export { get15Errors as 'GET /snippets/{snippet_id}/workflows/draft' } from './snippets/errors.gen.ts'
export { get15Errors as 'GET /trial-apps/{app_id}/site' } from './trial-apps/errors.gen.ts'
export { get16Errors as 'GET /agent/{agent_id}/config/skills/{name}/files/preview' } from './agent/errors.gen.ts'
export { get16Errors as 'GET /apps/{app_id}/agent/logs' } from './apps/errors.gen.ts'
export { get16Errors as 'GET /datasets/{dataset_id}/documents/{document_id}/indexing-estimate' } from './datasets/errors.gen.ts'
export { get16Errors as 'GET /knowledge-fs/spaces/{control_space_id}/documents' } from './knowledge-fs/errors.gen.ts'
export { get16Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/draft/processing/parameters' } from './rag/errors.gen.ts'
export { get16Errors as 'GET /trial-apps/{app_id}/workflows' } from './trial-apps/errors.gen.ts'
export { get17Errors as 'GET /agent/{agent_id}/config/skills/{name}/inspect' } from './agent/errors.gen.ts'
export { get17Errors as 'GET /knowledge-fs/spaces/{control_space_id}/external-access' } from './knowledge-fs/errors.gen.ts'
export { get17Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/draft/system-variables' } from './rag/errors.gen.ts'
export { get17Errors as 'GET /trial-apps/{app_id}' } from './trial-apps/errors.gen.ts'
export { get18Errors as 'GET /agent/{agent_id}/config/skills' } from './agent/errors.gen.ts'
export { get18Errors as 'GET /datasets/{dataset_id}/documents/{document_id}/notion/sync' } from './datasets/errors.gen.ts'
export { get18Errors as 'GET /knowledge-fs/spaces/{control_space_id}/golden-questions' } from './knowledge-fs/errors.gen.ts'
export { get18Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/draft/variables/{variable_id}' } from './rag/errors.gen.ts'
export { get19Errors as 'GET /agent/{agent_id}/log-sources' } from './agent/errors.gen.ts'
export { get19Errors as 'GET /knowledge-fs/spaces/{control_space_id}/jobs/{job_id}' } from './knowledge-fs/errors.gen.ts'
export { get19Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/draft/variables' } from './rag/errors.gen.ts'
export { get20Errors as 'GET /agent/{agent_id}/logs/{conversation_id}/messages' } from './agent/errors.gen.ts'
export { get20Errors as 'GET /apps/{app_id}/annotations/count' } from './apps/errors.gen.ts'
export { get20Errors as 'GET /knowledge-fs/spaces/{control_space_id}/logical-documents/{document_id}/download' } from './knowledge-fs/errors.gen.ts'
export { get20Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/draft' } from './rag/errors.gen.ts'
export { get21Errors as 'GET /agent/{agent_id}/logs' } from './agent/errors.gen.ts'
export { get21Errors as 'GET /knowledge-fs/spaces/{control_space_id}/logical-documents/{document_id}' } from './knowledge-fs/errors.gen.ts'
export { get21Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/publish' } from './rag/errors.gen.ts'
export { get22Errors as 'GET /agent/{agent_id}/messages/{message_id}' } from './agent/errors.gen.ts'
export { get22Errors as 'GET /knowledge-fs/spaces/{control_space_id}/logical-documents' } from './knowledge-fs/errors.gen.ts'
export { get22Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/published/pre-processing/parameters' } from './rag/errors.gen.ts'
export { get23Errors as 'GET /agent/{agent_id}/referencing-workflows' } from './agent/errors.gen.ts'
export { get23Errors as 'GET /datasets/{dataset_id}/documents/{document_id}/website-sync' } from './datasets/errors.gen.ts'
export { get23Errors as 'GET /knowledge-fs/spaces/{control_space_id}/metadata' } from './knowledge-fs/errors.gen.ts'
export { get23Errors as 'GET /rag/pipelines/{pipeline_id}/workflows/published/processing/parameters' } from './rag/errors.gen.ts'
export { get24Errors as 'GET /agent/{agent_id}/sandbox/files/read' } from './agent/errors.gen.ts'
export { get24Errors as 'GET /apps/{app_id}/chat-conversations/{conversation_id}' } from './apps/errors.gen.ts'
export { get24Errors as 'GET /datasets/{dataset_id}/documents/{document_id}' } from './datasets/errors.gen.ts'
export { get24Errors as 'GET /knowledge-fs/spaces/{control_space_id}/overview/activity' } from './knowledge-fs/errors.gen.ts'
export { get24Errors as 'GET /rag/pipelines/{pipeline_id}/workflows' } from './rag/errors.gen.ts'
export { get25Errors as 'GET /agent/{agent_id}/sandbox/files' } from './agent/errors.gen.ts'
export { get25Errors as 'GET /apps/{app_id}/chat-conversations' } from './apps/errors.gen.ts'
export { get25Errors as 'GET /knowledge-fs/spaces/{control_space_id}/overview/attention' } from './knowledge-fs/errors.gen.ts'
export { get26Errors as 'GET /agent/{agent_id}/sandbox' } from './agent/errors.gen.ts'
export { get26Errors as 'GET /apps/{app_id}/chat-messages/{message_id}/suggested-questions' } from './apps/errors.gen.ts'
export { get26Errors as 'GET /knowledge-fs/spaces/{control_space_id}/overview/health' } from './knowledge-fs/errors.gen.ts'
export { get27Errors as 'GET /agent/{agent_id}/statistics/summary' } from './agent/errors.gen.ts'
export { get27Errors as 'GET /apps/{app_id}/chat-messages' } from './apps/errors.gen.ts'
export { get27Errors as 'GET /knowledge-fs/spaces/{control_space_id}/overview/inventory' } from './knowledge-fs/errors.gen.ts'
export { get27Errors as 'GET /workspaces/current/plugin/asset' } from './workspaces/errors.gen.ts'
export { get28Errors as 'GET /agent/{agent_id}/text-to-audio/voices' } from './agent/errors.gen.ts'
export { get28Errors as 'GET /apps/{app_id}/completion-conversations/{conversation_id}' } from './apps/errors.gen.ts'
export { get28Errors as 'GET /knowledge-fs/spaces/{control_space_id}/overview/query-outcomes' } from './knowledge-fs/errors.gen.ts'
export { get29Errors as 'GET /apps/{app_id}/completion-conversations' } from './apps/errors.gen.ts'
export { get29Errors as 'GET /knowledge-fs/spaces/{control_space_id}/overview/stats' } from './knowledge-fs/errors.gen.ts'
export { get29Errors as 'GET /workspaces/current/plugin/debugging-key' } from './workspaces/errors.gen.ts'
export { get2Errors as 'GET /account/delete/verify' } from './account/errors.gen.ts'
export { get2Errors as 'GET /agent/{agent_id}/api-access' } from './agent/errors.gen.ts'
export { get2Errors as 'GET /billing/subscription' } from './billing/errors.gen.ts'
export { get2Errors as 'GET /explore/apps/{app_id}' } from './explore/errors.gen.ts'
export { get2Errors as 'GET /installed-apps/{installed_app_id}/messages/{message_id}/more-like-this' } from './installed-apps/errors.gen.ts'
export { get2Errors as 'GET /notion/pre-import/pages' } from './notion/errors.gen.ts'
export { get2Errors as 'GET /trial-apps/{app_id}/agent/config/files/{name}/download' } from './trial-apps/errors.gen.ts'
export { get30Errors as 'GET /agent/{agent_id}/trace-capabilities' } from './agent/errors.gen.ts'
export { get30Errors as 'GET /apps/{app_id}/conversation-variables' } from './apps/errors.gen.ts'
export { get30Errors as 'GET /knowledge-fs/spaces/{control_space_id}/permissions' } from './knowledge-fs/errors.gen.ts'
export { get30Errors as 'GET /workspaces/current/plugin/fetch-manifest' } from './workspaces/errors.gen.ts'
export { get31Errors as 'GET /agent/{agent_id}/trace-config' } from './agent/errors.gen.ts'
export { get31Errors as 'GET /apps/{app_id}/export' } from './apps/errors.gen.ts'
export { get31Errors as 'GET /datasets/{dataset_id}/notion/sync' } from './datasets/errors.gen.ts'
export { get31Errors as 'GET /knowledge-fs/spaces/{control_space_id}/quality/bad-cases/{bad_case_id}/trace-reference' } from './knowledge-fs/errors.gen.ts'
export { get31Errors as 'GET /workspaces/current/plugin/icon' } from './workspaces/errors.gen.ts'
export { get32Errors as 'GET /agent/{agent_id}/trace-runs/{message_id}' } from './agent/errors.gen.ts'
export { get32Errors as 'GET /apps/{app_id}/messages/{message_id}' } from './apps/errors.gen.ts'
export { get32Errors as 'GET /knowledge-fs/spaces/{control_space_id}/quality/bad-cases/{bad_case_id}' } from './knowledge-fs/errors.gen.ts'
export { get32Errors as 'GET /workspaces/current/plugin/installed-ids' } from './workspaces/errors.gen.ts'
export { get33Errors as 'GET /agent/{agent_id}/versions/{version_id}' } from './agent/errors.gen.ts'
export { get33Errors as 'GET /apps/{app_id}/network-access-group/status' } from './apps/errors.gen.ts'
export { get33Errors as 'GET /knowledge-fs/spaces/{control_space_id}/quality/bad-cases' } from './knowledge-fs/errors.gen.ts'
export { get33Errors as 'GET /workspaces/current/plugin/list' } from './workspaces/errors.gen.ts'
export { get34Errors as 'GET /agent/{agent_id}/versions' } from './agent/errors.gen.ts'
export { get34Errors as 'GET /apps/{app_id}/network-access-group' } from './apps/errors.gen.ts'
export { get34Errors as 'GET /knowledge-fs/spaces/{control_space_id}/quality/replay-runs/{run_id}' } from './knowledge-fs/errors.gen.ts'
export { get34Errors as 'GET /workspaces/current/plugin/marketplace/pkg' } from './workspaces/errors.gen.ts'
export { get35Errors as 'GET /agent/{agent_id}' } from './agent/errors.gen.ts'
export { get35Errors as 'GET /apps/{app_id}/server' } from './apps/errors.gen.ts'
export { get35Errors as 'GET /knowledge-fs/spaces/{control_space_id}/quality/replay-runs' } from './knowledge-fs/errors.gen.ts'
export { get35Errors as 'GET /workspaces/current/plugin/parameters/dynamic-options' } from './workspaces/errors.gen.ts'
export { get36Errors as 'GET /agent' } from './agent/errors.gen.ts'
export { get36Errors as 'GET /apps/{app_id}/statistics/average-response-time' } from './apps/errors.gen.ts'
export { get36Errors as 'GET /knowledge-fs/spaces/{control_space_id}/research-tasks/{task_id}/partials' } from './knowledge-fs/errors.gen.ts'
export { get37Errors as 'GET /apps/{app_id}/statistics/average-session-interactions' } from './apps/errors.gen.ts'
export { get37Errors as 'GET /knowledge-fs/spaces/{control_space_id}/research-tasks/{task_id}' } from './knowledge-fs/errors.gen.ts'
export { get38Errors as 'GET /apps/{app_id}/statistics/daily-conversations' } from './apps/errors.gen.ts'
export { get38Errors as 'GET /knowledge-fs/spaces/{control_space_id}/research-tasks' } from './knowledge-fs/errors.gen.ts'
export { get38Errors as 'GET /workspaces/current/plugin/tasks/{task_id}' } from './workspaces/errors.gen.ts'
export { get39Errors as 'GET /apps/{app_id}/statistics/daily-end-users' } from './apps/errors.gen.ts'
export { get39Errors as 'GET /knowledge-fs/spaces/{control_space_id}/settings/migrations/{migration_id}' } from './knowledge-fs/errors.gen.ts'
export { get39Errors as 'GET /workspaces/current/plugin/tasks' } from './workspaces/errors.gen.ts'
export { get3Errors as 'GET /installed-apps/{installed_app_id}/messages/{message_id}/suggested-questions' } from './installed-apps/errors.gen.ts'
export { get3Errors as 'GET /knowledge-fs/research-tasks/{task_id}/events' } from './knowledge-fs/errors.gen.ts'
export { get3Errors as 'GET /trial-apps/{app_id}/agent/config/files/{name}/preview' } from './trial-apps/errors.gen.ts'
export { get40Errors as 'GET /apps/{app_id}/statistics/daily-messages' } from './apps/errors.gen.ts'
export { get40Errors as 'GET /knowledge-fs/spaces/{control_space_id}/settings' } from './knowledge-fs/errors.gen.ts'
export { get40Errors as 'GET /workspaces/current/plugin/{category}/list' } from './workspaces/errors.gen.ts'
export { get41Errors as 'GET /apps/{app_id}/statistics/token-costs' } from './apps/errors.gen.ts'
export { get41Errors as 'GET /knowledge-fs/spaces/{control_space_id}/source-connections' } from './knowledge-fs/errors.gen.ts'
export { get42Errors as 'GET /apps/{app_id}/statistics/tokens-per-second' } from './apps/errors.gen.ts'
export { get42Errors as 'GET /knowledge-fs/spaces/{control_space_id}/source-providers' } from './knowledge-fs/errors.gen.ts'
export { get43Errors as 'GET /apps/{app_id}/statistics/user-satisfaction-rate' } from './apps/errors.gen.ts'
export { get43Errors as 'GET /knowledge-fs/spaces/{control_space_id}/source-workflows/{run_id}/pages' } from './knowledge-fs/errors.gen.ts'
export { get44Errors as 'GET /apps/{app_id}/text-to-audio/voices' } from './apps/errors.gen.ts'
export { get44Errors as 'GET /knowledge-fs/spaces/{control_space_id}/source-workflows/{run_id}' } from './knowledge-fs/errors.gen.ts'
export { get45Errors as 'GET /knowledge-fs/spaces/{control_space_id}/sources/{source_id}/files' } from './knowledge-fs/errors.gen.ts'
export { get46Errors as 'GET /apps/{app_id}/trace-capabilities' } from './apps/errors.gen.ts'
export { get46Errors as 'GET /knowledge-fs/spaces/{control_space_id}/sources/{source_id}/pages' } from './knowledge-fs/errors.gen.ts'
export { get47Errors as 'GET /apps/{app_id}/trace-config' } from './apps/errors.gen.ts'
export { get47Errors as 'GET /knowledge-fs/spaces/{control_space_id}/sources/{source_id}/sync-policy' } from './knowledge-fs/errors.gen.ts'
export { get48Errors as 'GET /apps/{app_id}/trace-runs/{source_kind}/{source_id}' } from './apps/errors.gen.ts'
export { get48Errors as 'GET /knowledge-fs/spaces/{control_space_id}/sources/{source_id}' } from './knowledge-fs/errors.gen.ts'
export { get49Errors as 'GET /apps/{app_id}/triggers' } from './apps/errors.gen.ts'
export { get49Errors as 'GET /knowledge-fs/spaces/{control_space_id}/sources' } from './knowledge-fs/errors.gen.ts'
export { get4Errors as 'GET /account/education/verify' } from './account/errors.gen.ts'
export { get4Errors as 'GET /agent/{agent_id}/build-draft' } from './agent/errors.gen.ts'
export { get4Errors as 'GET /apps/{app_id}/advanced-chat/workflow-runs/count' } from './apps/errors.gen.ts'
export { get4Errors as 'GET /installed-apps/{installed_app_id}/messages' } from './installed-apps/errors.gen.ts'
export { get4Errors as 'GET /knowledge-fs/source-provider-preview/jobs/{job_id}' } from './knowledge-fs/errors.gen.ts'
export { get4Errors as 'GET /rag/pipelines/imports/{pipeline_id}/check-dependencies' } from './rag/errors.gen.ts'
export { get4Errors as 'GET /trial-apps/{app_id}/agent/config/files' } from './trial-apps/errors.gen.ts'
export { get50Errors as 'GET /apps/{app_id}/workflow-app-logs' } from './apps/errors.gen.ts'
export { get50Errors as 'GET /knowledge-fs/spaces/{control_space_id}/tags' } from './knowledge-fs/errors.gen.ts'
export { get51Errors as 'GET /apps/{app_id}/workflow-runs/count' } from './apps/errors.gen.ts'
export { get51Errors as 'GET /knowledge-fs/spaces/{control_space_id}/traces/{trace_id}/conflicts' } from './knowledge-fs/errors.gen.ts'
export { get52Errors as 'GET /apps/{app_id}/workflow-runs/{run_id}/node-executions/{node_execution_id}/children' } from './apps/errors.gen.ts'
export { get52Errors as 'GET /knowledge-fs/spaces/{control_space_id}/traces/{trace_id}/evidence' } from './knowledge-fs/errors.gen.ts'
export { get53Errors as 'GET /apps/{app_id}/workflow-runs/{run_id}/node-executions' } from './apps/errors.gen.ts'
export { get53Errors as 'GET /knowledge-fs/spaces/{control_space_id}/traces/{trace_id}/missing' } from './knowledge-fs/errors.gen.ts'
export { get54Errors as 'GET /apps/{app_id}/workflow-runs/{run_id}' } from './apps/errors.gen.ts'
export { get54Errors as 'GET /knowledge-fs/spaces/{control_space_id}/traces/{trace_id}' } from './knowledge-fs/errors.gen.ts'
export { get55Errors as 'GET /apps/{app_id}/workflow-runs/{workflow_run_id}/agent-nodes/{node_id}/sandbox/files/read' } from './apps/errors.gen.ts'
export { get55Errors as 'GET /knowledge-fs/spaces/{control_space_id}/traces' } from './knowledge-fs/errors.gen.ts'
export { get56Errors as 'GET /apps/{app_id}/workflow-runs/{workflow_run_id}/agent-nodes/{node_id}/sandbox/files' } from './apps/errors.gen.ts'
export { get56Errors as 'GET /knowledge-fs/spaces/{control_space_id}' } from './knowledge-fs/errors.gen.ts'
export { get57Errors as 'GET /apps/{app_id}/workflow-runs' } from './apps/errors.gen.ts'
export { get57Errors as 'GET /knowledge-fs/spaces' } from './knowledge-fs/errors.gen.ts'
export { get58Errors as 'GET /apps/{app_id}/workflow/comments/mention-users' } from './apps/errors.gen.ts'
export { get59Errors as 'GET /apps/{app_id}/workflow/comments/{comment_id}' } from './apps/errors.gen.ts'
export { get5Errors as 'GET /agent/{agent_id}/chat-messages/{message_id}/suggested-questions' } from './agent/errors.gen.ts'
export { get5Errors as 'GET /apps/{app_id}/advanced-chat/workflow-runs' } from './apps/errors.gen.ts'
export { get5Errors as 'GET /datasets/external-knowledge-api/{external_knowledge_api_id}' } from './datasets/errors.gen.ts'
export { get5Errors as 'GET /installed-apps/{installed_app_id}/meta' } from './installed-apps/errors.gen.ts'
export { get5Errors as 'GET /knowledge-fs/spaces/{control_space_id}/app-bindings' } from './knowledge-fs/errors.gen.ts'
export { get5Errors as 'GET /trial-apps/{app_id}/agent/config/skills/{name}/download' } from './trial-apps/errors.gen.ts'
export { get60Errors as 'GET /apps/{app_id}/workflow/comments' } from './apps/errors.gen.ts'
export { get61Errors as 'GET /apps/{app_id}/workflow/statistics/average-app-interactions' } from './apps/errors.gen.ts'
export { get62Errors as 'GET /apps/{app_id}/workflow/statistics/daily-conversations' } from './apps/errors.gen.ts'
export { get63Errors as 'GET /apps/{app_id}/workflow/statistics/daily-terminals' } from './apps/errors.gen.ts'
export { get64Errors as 'GET /apps/{app_id}/workflow/statistics/token-costs' } from './apps/errors.gen.ts'
export { get65Errors as 'GET /apps/{app_id}/workflows/default-workflow-block-configs/{block_type}' } from './apps/errors.gen.ts'
export { get66Errors as 'GET /apps/{app_id}/workflows/default-workflow-block-configs' } from './apps/errors.gen.ts'
export { get67Errors as 'GET /apps/{app_id}/workflows/draft/conversation-variables' } from './apps/errors.gen.ts'
export { get68Errors as 'GET /apps/{app_id}/workflows/draft/environment-variables' } from './apps/errors.gen.ts'
export { get69Errors as 'GET /apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer/candidates' } from './apps/errors.gen.ts'
export { get6Errors as 'GET /agent/{agent_id}/chat-messages' } from './agent/errors.gen.ts'
export { get6Errors as 'GET /apps/{app_id}/agent/config/files/{name}/download' } from './apps/errors.gen.ts'
export { get6Errors as 'GET /installed-apps/{installed_app_id}/parameters' } from './installed-apps/errors.gen.ts'
export { get6Errors as 'GET /knowledge-fs/spaces/{control_space_id}/background-tasks' } from './knowledge-fs/errors.gen.ts'
export { get6Errors as 'GET /rag/pipelines/{pipeline_id}/exports' } from './rag/errors.gen.ts'
export { get6Errors as 'GET /trial-apps/{app_id}/agent/config/skills/{name}/files/content' } from './trial-apps/errors.gen.ts'
export { get70Errors as 'GET /apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer' } from './apps/errors.gen.ts'
export { get71Errors as 'GET /apps/{app_id}/workflows/draft/nodes/{node_id}/last-run' } from './apps/errors.gen.ts'
export { get72Errors as 'GET /apps/{app_id}/workflows/draft/nodes/{node_id}/variables' } from './apps/errors.gen.ts'
export { get73Errors as 'GET /apps/{app_id}/workflows/draft/runs/{run_id}/node-outputs/events' } from './apps/errors.gen.ts'
export { get74Errors as 'GET /apps/{app_id}/workflows/draft/runs/{run_id}/node-outputs/{node_id}/{output_name}/preview' } from './apps/errors.gen.ts'
export { get75Errors as 'GET /apps/{app_id}/workflows/draft/runs/{run_id}/node-outputs/{node_id}' } from './apps/errors.gen.ts'
export { get76Errors as 'GET /apps/{app_id}/workflows/draft/runs/{run_id}/node-outputs' } from './apps/errors.gen.ts'
export { get77Errors as 'GET /apps/{app_id}/workflows/draft/system-variables' } from './apps/errors.gen.ts'
export { get78Errors as 'GET /apps/{app_id}/workflows/draft/variables/{variable_id}' } from './apps/errors.gen.ts'
export { get79Errors as 'GET /apps/{app_id}/workflows/draft/variables' } from './apps/errors.gen.ts'
export { get7Errors as 'GET /account/profile' } from './account/errors.gen.ts'
export { get7Errors as 'GET /agent/{agent_id}/composer/candidates' } from './agent/errors.gen.ts'
export { get7Errors as 'GET /apps/{app_id}/agent/config/files/{name}/preview' } from './apps/errors.gen.ts'
export { get7Errors as 'GET /installed-apps/{installed_app_id}/saved-messages' } from './installed-apps/errors.gen.ts'
export { get7Errors as 'GET /knowledge-fs/spaces/{control_space_id}/bulk-jobs/{job_id}' } from './knowledge-fs/errors.gen.ts'
export { get7Errors as 'GET /rag/pipelines/{pipeline_id}/workflow-runs/{run_id}/node-executions' } from './rag/errors.gen.ts'
export { get7Errors as 'GET /snippets/{snippet_id}/workflows/draft/environment-variables' } from './snippets/errors.gen.ts'
export { get7Errors as 'GET /trial-apps/{app_id}/agent/config/skills/{name}/files/download' } from './trial-apps/errors.gen.ts'
export { get80Errors as 'GET /apps/{app_id}/workflows/draft' } from './apps/errors.gen.ts'
export { get81Errors as 'GET /apps/{app_id}/workflows/publish' } from './apps/errors.gen.ts'
export { get81Errors as 'GET /workspaces/current/skills/{skill_id}/files/content' } from './workspaces/errors.gen.ts'
export { get82Errors as 'GET /apps/{app_id}/workflows/published/runs/{run_id}/node-outputs/events' } from './apps/errors.gen.ts'
export { get82Errors as 'GET /workspaces/current/skills/{skill_id}/files/preview' } from './workspaces/errors.gen.ts'
export { get83Errors as 'GET /apps/{app_id}/workflows/published/runs/{run_id}/node-outputs/{node_id}/{output_name}/preview' } from './apps/errors.gen.ts'
export { get84Errors as 'GET /apps/{app_id}/workflows/published/runs/{run_id}/node-outputs/{node_id}' } from './apps/errors.gen.ts'
export { get85Errors as 'GET /apps/{app_id}/workflows/published/runs/{run_id}/node-outputs' } from './apps/errors.gen.ts'
export { get86Errors as 'GET /apps/{app_id}/workflows/triggers/webhook' } from './apps/errors.gen.ts'
export { get87Errors as 'GET /apps/{app_id}/workflows' } from './apps/errors.gen.ts'
export { get88Errors as 'GET /workspaces/current/summary' } from './workspaces/errors.gen.ts'
export { get8Errors as 'GET /agent/{agent_id}/composer' } from './agent/errors.gen.ts'
export { get8Errors as 'GET /apps/{app_id}/agent/config/files' } from './apps/errors.gen.ts'
export { get8Errors as 'GET /installed-apps/{installed_app_id}' } from './installed-apps/errors.gen.ts'
export { get8Errors as 'GET /knowledge-fs/spaces/{control_space_id}/document-references/resolve' } from './knowledge-fs/errors.gen.ts'
export { get8Errors as 'GET /rag/pipelines/{pipeline_id}/workflow-runs/{run_id}' } from './rag/errors.gen.ts'
export { get8Errors as 'GET /trial-apps/{app_id}/agent/config/skills/{name}/files/preview' } from './trial-apps/errors.gen.ts'
export { get9Errors as 'GET /agent/{agent_id}/config/files/{name}/download' } from './agent/errors.gen.ts'
export { get9Errors as 'GET /apps/{app_id}/agent/config/manifest' } from './apps/errors.gen.ts'
export { get9Errors as 'GET /installed-apps' } from './installed-apps/errors.gen.ts'
export { get9Errors as 'GET /knowledge-fs/spaces/{control_space_id}/documents/{document_id}/multimodal/{item_id}/asset' } from './knowledge-fs/errors.gen.ts'
export { get9Errors as 'GET /rag/pipelines/{pipeline_id}/workflow-runs' } from './rag/errors.gen.ts'
export { get9Errors as 'GET /snippets/{snippet_id}/workflows/draft/nodes/{node_id}/agent-composer' } from './snippets/errors.gen.ts'
export { get9Errors as 'GET /trial-apps/{app_id}/agent/config/skills/{name}/inspect' } from './trial-apps/errors.gen.ts'
export { getErrors as 'GET /apps/imports/{app_id}/check-dependencies' } from './apps/errors.gen.ts'
export { getErrors as 'GET /billing/invoices' } from './billing/errors.gen.ts'
export { getErrors as 'GET /compliance/download' } from './compliance/errors.gen.ts'
export { getErrors as 'GET /form/human_input/{form_token}' } from './form/errors.gen.ts'
export { getErrors as 'GET /installed-apps/{installed_app_id}/conversations' } from './installed-apps/errors.gen.ts'
export { getErrors as 'GET /remote-files/{url}' } from './remote-files/errors.gen.ts'
export { getErrors as 'GET /trial-apps/{app_id}/agent-composer' } from './trial-apps/errors.gen.ts'
export { getErrors as 'GET /website/crawl/status/{job_id}' } from './website/errors.gen.ts'
export { patch2Errors as 'PATCH /apps/{app_id}/workflows/draft/variables/{variable_id}' } from './apps/errors.gen.ts'
export { patch2Errors as 'PATCH /datasets/{dataset_id}/documents/status/{action}/batch' } from './datasets/errors.gen.ts'
export { patch2Errors as 'PATCH /installed-apps/{installed_app_id}/conversations/{c_id}/unpin' } from './installed-apps/errors.gen.ts'
export { patch2Errors as 'PATCH /knowledge-fs/spaces/{control_space_id}/golden-questions/{question_id}' } from './knowledge-fs/errors.gen.ts'
export { patch2Errors as 'PATCH /rag/pipelines/{pipeline_id}/workflows/draft/variables/{variable_id}' } from './rag/errors.gen.ts'
export { patch3Errors as 'PATCH /apps/{app_id}/workflows/{workflow_id}' } from './apps/errors.gen.ts'
export { patch3Errors as 'PATCH /datasets/{dataset_id}/documents/{document_id}/processing/pause' } from './datasets/errors.gen.ts'
export { patch3Errors as 'PATCH /installed-apps/{installed_app_id}' } from './installed-apps/errors.gen.ts'
export { patch3Errors as 'PATCH /knowledge-fs/spaces/{control_space_id}/logical-documents/{document_id}' } from './knowledge-fs/errors.gen.ts'
export { patch3Errors as 'PATCH /rag/pipelines/{pipeline_id}/workflows/{workflow_id}' } from './rag/errors.gen.ts'
export { patch4Errors as 'PATCH /datasets/{dataset_id}/documents/{document_id}/processing/resume' } from './datasets/errors.gen.ts'
export { patch4Errors as 'PATCH /knowledge-fs/spaces/{control_space_id}/logical-documents' } from './knowledge-fs/errors.gen.ts'
export { patch5Errors as 'PATCH /datasets/{dataset_id}/documents/{document_id}/processing/{action}' } from './datasets/errors.gen.ts'
export { patch5Errors as 'PATCH /knowledge-fs/spaces/{control_space_id}/metadata/{field_id}' } from './knowledge-fs/errors.gen.ts'
export { patch5Errors as 'PATCH /workspaces/current/skills/{skill_id}/files' } from './workspaces/errors.gen.ts'
export { patch6Errors as 'PATCH /datasets/{dataset_id}/documents/{document_id}/segment/{action}' } from './datasets/errors.gen.ts'
export { patch6Errors as 'PATCH /knowledge-fs/spaces/{control_space_id}/quality/bad-cases/{bad_case_id}' } from './knowledge-fs/errors.gen.ts'
export { patch6Errors as 'PATCH /workspaces/current/skills/{skill_id}/versions/{version_id}' } from './workspaces/errors.gen.ts'
export { patch7Errors as 'PATCH /datasets/{dataset_id}/documents/{document_id}/segments/{segment_id}/child_chunks/{child_chunk_id}' } from './datasets/errors.gen.ts'
export { patch7Errors as 'PATCH /knowledge-fs/spaces/{control_space_id}/settings' } from './knowledge-fs/errors.gen.ts'
export { patch7Errors as 'PATCH /workspaces/current/skills/{skill_id}' } from './workspaces/errors.gen.ts'
export { patch8Errors as 'PATCH /datasets/{dataset_id}/documents/{document_id}/segments/{segment_id}/child_chunks' } from './datasets/errors.gen.ts'
export { patch8Errors as 'PATCH /knowledge-fs/spaces/{control_space_id}/sources/{source_id}' } from './knowledge-fs/errors.gen.ts'
export { patch9Errors as 'PATCH /datasets/{dataset_id}/documents/{document_id}/segments/{segment_id}' } from './datasets/errors.gen.ts'
export { patch9Errors as 'PATCH /knowledge-fs/spaces/{control_space_id}' } from './knowledge-fs/errors.gen.ts'
export { patchErrors as 'PATCH /account/profile' } from './account/errors.gen.ts'
export { patchErrors as 'PATCH /agent/{agent_id}/trace-config' } from './agent/errors.gen.ts'
export { patchErrors as 'PATCH /apps/{app_id}/trace-config' } from './apps/errors.gen.ts'
export { patchErrors as 'PATCH /data-source/integrates/{binding_id}/{action}' } from './data-source/errors.gen.ts'
export { patchErrors as 'PATCH /datasets/external-knowledge-api/{external_knowledge_api_id}' } from './datasets/errors.gen.ts'
export { patchErrors as 'PATCH /installed-apps/{installed_app_id}/conversations/{c_id}/pin' } from './installed-apps/errors.gen.ts'
export { patchErrors as 'PATCH /knowledge-fs/spaces/{control_space_id}/documents/{document_id}' } from './knowledge-fs/errors.gen.ts'
export { post10Errors as 'POST /account/interface-language' } from './account/errors.gen.ts'
export { post10Errors as 'POST /agent/{agent_id}/config/skills/upload' } from './agent/errors.gen.ts'
export { post10Errors as 'POST /apps/{app_id}/agent/config/skills/upload' } from './apps/errors.gen.ts'
export { post10Errors as 'POST /installed-apps/{installed_app_id}/workflows/run' } from './installed-apps/errors.gen.ts'
export { post10Errors as 'POST /knowledge-fs/spaces/{control_space_id}/golden-questions' } from './knowledge-fs/errors.gen.ts'
export { post10Errors as 'POST /rag/pipelines/{pipeline_id}/workflows/draft/datasource/variables-inspect' } from './rag/errors.gen.ts'
export { post10Errors as 'POST /snippets/{snippet_id}/workflows/draft' } from './snippets/errors.gen.ts'
export { post11Errors as 'POST /account/interface-theme' } from './account/errors.gen.ts'
export { post11Errors as 'POST /agent/{agent_id}/copy' } from './agent/errors.gen.ts'
export { post11Errors as 'POST /installed-apps/{installed_app_id}/workflows/tasks/{task_id}/stop' } from './installed-apps/errors.gen.ts'
export { post11Errors as 'POST /knowledge-fs/spaces/{control_space_id}/jobs/{job_id}/retry' } from './knowledge-fs/errors.gen.ts'
export { post11Errors as 'POST /rag/pipelines/{pipeline_id}/workflows/draft/iteration/nodes/{node_id}/run' } from './rag/errors.gen.ts'
export { post12Errors as 'POST /account/name' } from './account/errors.gen.ts'
export { post12Errors as 'POST /agent/{agent_id}/debug-conversation/refresh' } from './agent/errors.gen.ts'
export { post12Errors as 'POST /datasets/{dataset_id}/documents/{document_id}/segment' } from './datasets/errors.gen.ts'
export { post12Errors as 'POST /knowledge-fs/spaces/{control_space_id}/logical-documents/download-zip' } from './knowledge-fs/errors.gen.ts'
export { post12Errors as 'POST /rag/pipelines/{pipeline_id}/workflows/draft/loop/nodes/{node_id}/run' } from './rag/errors.gen.ts'
export { post12Errors as 'POST /workspaces/current/members/invite-email' } from './workspaces/errors.gen.ts'
export { post13Errors as 'POST /account/password' } from './account/errors.gen.ts'
export { post13Errors as 'POST /agent/{agent_id}/features' } from './agent/errors.gen.ts'
export { post13Errors as 'POST /apps/{app_id}/annotations/batch-import' } from './apps/errors.gen.ts'
export { post13Errors as 'POST /knowledge-fs/spaces/{control_space_id}/metadata' } from './knowledge-fs/errors.gen.ts'
export { post13Errors as 'POST /rag/pipelines/{pipeline_id}/workflows/draft/nodes/{node_id}/run' } from './rag/errors.gen.ts'
export { post13Errors as 'POST /workspaces/current/members/owner-transfer-check' } from './workspaces/errors.gen.ts'
export { post14Errors as 'POST /account/timezone' } from './account/errors.gen.ts'
export { post14Errors as 'POST /agent/{agent_id}/feedbacks' } from './agent/errors.gen.ts'
export { post14Errors as 'POST /datasets/{dataset_id}/documents/{document_id}/segments/{segment_id}/child_chunks' } from './datasets/errors.gen.ts'
export { post14Errors as 'POST /knowledge-fs/spaces/{control_space_id}/quality/bad-cases' } from './knowledge-fs/errors.gen.ts'
export { post14Errors as 'POST /rag/pipelines/{pipeline_id}/workflows/draft/run' } from './rag/errors.gen.ts'
export { post14Errors as 'POST /workspaces/current/members/send-owner-transfer-confirm-email' } from './workspaces/errors.gen.ts'
export { post15Errors as 'POST /agent/{agent_id}/publish' } from './agent/errors.gen.ts'
export { post15Errors as 'POST /datasets/{dataset_id}/documents' } from './datasets/errors.gen.ts'
export { post15Errors as 'POST /knowledge-fs/spaces/{control_space_id}/quality/replay-runs' } from './knowledge-fs/errors.gen.ts'
export { post15Errors as 'POST /rag/pipelines/{pipeline_id}/workflows/draft' } from './rag/errors.gen.ts'
export { post15Errors as 'POST /workspaces/current/members/{member_id}/owner-transfer' } from './workspaces/errors.gen.ts'
export { post16Errors as 'POST /agent/{agent_id}/sandbox/files/download' } from './agent/errors.gen.ts'
export { post16Errors as 'POST /datasets/{dataset_id}/external-hit-testing' } from './datasets/errors.gen.ts'
export { post16Errors as 'POST /knowledge-fs/spaces/{control_space_id}/queries/admission' } from './knowledge-fs/errors.gen.ts'
export { post16Errors as 'POST /rag/pipelines/{pipeline_id}/workflows/publish' } from './rag/errors.gen.ts'
export { post17Errors as 'POST /agent/{agent_id}/text-to-audio' } from './agent/errors.gen.ts'
export { post17Errors as 'POST /apps/{app_id}/audio-to-text' } from './apps/errors.gen.ts'
export { post17Errors as 'POST /datasets/{dataset_id}/hit-testing' } from './datasets/errors.gen.ts'
export { post17Errors as 'POST /knowledge-fs/spaces/{control_space_id}/queries' } from './knowledge-fs/errors.gen.ts'
export { post17Errors as 'POST /rag/pipelines/{pipeline_id}/workflows/published/datasource/nodes/{node_id}/preview' } from './rag/errors.gen.ts'
export { post18Errors as 'POST /agent/{agent_id}/trace' } from './agent/errors.gen.ts'
export { post18Errors as 'POST /apps/{app_id}/chat-messages/{task_id}/stop' } from './apps/errors.gen.ts'
export { post18Errors as 'POST /knowledge-fs/spaces/{control_space_id}/query-stream-capability' } from './knowledge-fs/errors.gen.ts'
export { post18Errors as 'POST /rag/pipelines/{pipeline_id}/workflows/published/datasource/nodes/{node_id}/run' } from './rag/errors.gen.ts'
export { post19Errors as 'POST /agent/{agent_id}/trace-config' } from './agent/errors.gen.ts'
export { post19Errors as 'POST /apps/{app_id}/completion-messages/{task_id}/stop' } from './apps/errors.gen.ts'
export { post19Errors as 'POST /knowledge-fs/spaces/{control_space_id}/research-tasks/plan' } from './knowledge-fs/errors.gen.ts'
export { post19Errors as 'POST /rag/pipelines/{pipeline_id}/workflows/published/run' } from './rag/errors.gen.ts'
export { post20Errors as 'POST /agent/{agent_id}/trace-runs/{message_id}/retry' } from './agent/errors.gen.ts'
export { post20Errors as 'POST /apps/{app_id}/completion-messages' } from './apps/errors.gen.ts'
export { post20Errors as 'POST /knowledge-fs/spaces/{control_space_id}/research-tasks' } from './knowledge-fs/errors.gen.ts'
export { post20Errors as 'POST /rag/pipelines/{pipeline_id}/workflows/{workflow_id}/restore' } from './rag/errors.gen.ts'
export { post21Errors as 'POST /agent/{agent_id}/versions/{version_id}/restore' } from './agent/errors.gen.ts'
export { post21Errors as 'POST /apps/{app_id}/convert-to-workflow' } from './apps/errors.gen.ts'
export { post21Errors as 'POST /knowledge-fs/spaces/{control_space_id}/source-connections/{connection_id}/refresh' } from './knowledge-fs/errors.gen.ts'
export { post22Errors as 'POST /agent' } from './agent/errors.gen.ts'
export { post22Errors as 'POST /knowledge-fs/spaces/{control_space_id}/source-connections' } from './knowledge-fs/errors.gen.ts'
export { post23Errors as 'POST /apps/{app_id}/feedbacks' } from './apps/errors.gen.ts'
export { post23Errors as 'POST /datasets/{resource_id}/api-keys' } from './datasets/errors.gen.ts'
export { post23Errors as 'POST /knowledge-fs/spaces/{control_space_id}/source-workflows/{run_id}/cancel' } from './knowledge-fs/errors.gen.ts'
export { post24Errors as 'POST /datasets' } from './datasets/errors.gen.ts'
export { post24Errors as 'POST /knowledge-fs/spaces/{control_space_id}/source-workflows/{run_id}/retry' } from './knowledge-fs/errors.gen.ts'
export { post25Errors as 'POST /apps/{app_id}/model-config' } from './apps/errors.gen.ts'
export { post25Errors as 'POST /knowledge-fs/spaces/{control_space_id}/source-workflows/{run_id}/selection' } from './knowledge-fs/errors.gen.ts'
export { post26Errors as 'POST /knowledge-fs/spaces/{control_space_id}/sources/{source_id}/async-import' } from './knowledge-fs/errors.gen.ts'
export { post27Errors as 'POST /knowledge-fs/spaces/{control_space_id}/sources/{source_id}/crawl-import' } from './knowledge-fs/errors.gen.ts'
export { post28Errors as 'POST /apps/{app_id}/server/refresh' } from './apps/errors.gen.ts'
export { post28Errors as 'POST /knowledge-fs/spaces/{control_space_id}/sources/{source_id}/crawl-preview' } from './knowledge-fs/errors.gen.ts'
export { post29Errors as 'POST /apps/{app_id}/server' } from './apps/errors.gen.ts'
export { post29Errors as 'POST /knowledge-fs/spaces/{control_space_id}/sources/{source_id}/import' } from './knowledge-fs/errors.gen.ts'
export { post29Errors as 'POST /workspaces/current/plugin/install/github' } from './workspaces/errors.gen.ts'
export { post2Errors as 'POST /account/change-email/check-email-unique' } from './account/errors.gen.ts'
export { post2Errors as 'POST /agent/{agent_id}/api-keys' } from './agent/errors.gen.ts'
export { post2Errors as 'POST /apps/imports' } from './apps/errors.gen.ts'
export { post2Errors as 'POST /datasets/external' } from './datasets/errors.gen.ts'
export { post2Errors as 'POST /email-code-login' } from './email-code-login/errors.gen.ts'
export { post2Errors as 'POST /email-register/validity' } from './email-register/errors.gen.ts'
export { post2Errors as 'POST /forgot-password/validity' } from './forgot-password/errors.gen.ts'
export { post2Errors as 'POST /installed-apps/{installed_app_id}/chat-messages/{task_id}/stop' } from './installed-apps/errors.gen.ts'
export { post2Errors as 'POST /instruction-generate' } from './instruction-generate/errors.gen.ts'
export { post2Errors as 'POST /knowledge-fs/source-provider-preview/jobs' } from './knowledge-fs/errors.gen.ts'
export { post2Errors as 'POST /rag/pipeline/dataset' } from './rag/errors.gen.ts'
export { post2Errors as 'POST /trial-apps/{app_id}/chat-messages/{task_id}/stop' } from './trial-apps/errors.gen.ts'
export { post30Errors as 'POST /apps/{app_id}/site/access-token-reset' } from './apps/errors.gen.ts'
export { post30Errors as 'POST /knowledge-fs/spaces/{control_space_id}/sources/{source_id}/import-files' } from './knowledge-fs/errors.gen.ts'
export { post30Errors as 'POST /workspaces/current/plugin/install/marketplace' } from './workspaces/errors.gen.ts'
export { post31Errors as 'POST /apps/{app_id}/site' } from './apps/errors.gen.ts'
export { post31Errors as 'POST /knowledge-fs/spaces/{control_space_id}/sources/{source_id}/sync' } from './knowledge-fs/errors.gen.ts'
export { post31Errors as 'POST /workspaces/current/plugin/install/pkg' } from './workspaces/errors.gen.ts'
export { post32Errors as 'POST /knowledge-fs/spaces/{control_space_id}/sources/{source_id}/test' } from './knowledge-fs/errors.gen.ts'
export { post32Errors as 'POST /workspaces/current/plugin/list/installations/ids' } from './workspaces/errors.gen.ts'
export { post33Errors as 'POST /knowledge-fs/spaces/{control_space_id}/sources/{source_id}/workflow-imports' } from './knowledge-fs/errors.gen.ts'
export { post33Errors as 'POST /workspaces/current/plugin/list/latest-versions' } from './workspaces/errors.gen.ts'
export { post34Errors as 'POST /apps/{app_id}/text-to-audio' } from './apps/errors.gen.ts'
export { post34Errors as 'POST /knowledge-fs/spaces/{control_space_id}/sources' } from './knowledge-fs/errors.gen.ts'
export { post34Errors as 'POST /workspaces/current/plugin/parameters/dynamic-options-with-credentials' } from './workspaces/errors.gen.ts'
export { post35Errors as 'POST /apps/{app_id}/trace' } from './apps/errors.gen.ts'
export { post35Errors as 'POST /knowledge-fs/spaces/{control_space_id}/upload-sessions/{upload_session_id}/abort' } from './knowledge-fs/errors.gen.ts'
export { post36Errors as 'POST /apps/{app_id}/trace-config' } from './apps/errors.gen.ts'
export { post36Errors as 'POST /knowledge-fs/spaces/{control_space_id}/upload-sessions/{upload_session_id}/complete' } from './knowledge-fs/errors.gen.ts'
export { post36Errors as 'POST /workspaces/current/plugin/tasks/delete_all' } from './workspaces/errors.gen.ts'
export { post37Errors as 'POST /apps/{app_id}/trace-runs/{source_kind}/{source_id}/retry' } from './apps/errors.gen.ts'
export { post37Errors as 'POST /knowledge-fs/spaces/{control_space_id}/upload-sessions/{upload_session_id}/parts/{part_number}/presign' } from './knowledge-fs/errors.gen.ts'
export { post37Errors as 'POST /workspaces/current/plugin/tasks/{task_id}/delete/{identifier}' } from './workspaces/errors.gen.ts'
export { post38Errors as 'POST /apps/{app_id}/trigger-enable' } from './apps/errors.gen.ts'
export { post38Errors as 'POST /knowledge-fs/spaces/{control_space_id}/upload-sessions/{upload_session_id}/small-file' } from './knowledge-fs/errors.gen.ts'
export { post38Errors as 'POST /workspaces/current/plugin/tasks/{task_id}/delete' } from './workspaces/errors.gen.ts'
export { post39Errors as 'POST /apps/{app_id}/workflow-runs/tasks/{task_id}/stop' } from './apps/errors.gen.ts'
export { post39Errors as 'POST /knowledge-fs/spaces/{control_space_id}/upload-sessions' } from './knowledge-fs/errors.gen.ts'
export { post39Errors as 'POST /workspaces/current/plugin/uninstall' } from './workspaces/errors.gen.ts'
export { post3Errors as 'POST /account/change-email/reset' } from './account/errors.gen.ts'
export { post3Errors as 'POST /agent/{agent_id}/audio-to-text' } from './agent/errors.gen.ts'
export { post3Errors as 'POST /datasets/external-knowledge-api' } from './datasets/errors.gen.ts'
export { post3Errors as 'POST /email-register' } from './email-register/errors.gen.ts'
export { post3Errors as 'POST /forgot-password' } from './forgot-password/errors.gen.ts'
export { post3Errors as 'POST /installed-apps/{installed_app_id}/chat-messages' } from './installed-apps/errors.gen.ts'
export { post3Errors as 'POST /knowledge-fs/source-provider-preview' } from './knowledge-fs/errors.gen.ts'
export { post3Errors as 'POST /trial-apps/{app_id}/chat-messages' } from './trial-apps/errors.gen.ts'
export { post3Errors as 'POST /workflow-generate' } from './workflow-generate/errors.gen.ts'
export { post40Errors as 'POST /apps/{app_id}/workflow-runs/{workflow_run_id}/agent-nodes/{node_id}/sandbox/files/download' } from './apps/errors.gen.ts'
export { post40Errors as 'POST /knowledge-fs/spaces' } from './knowledge-fs/errors.gen.ts'
export { post40Errors as 'POST /workspaces/current/plugin/upgrade/github' } from './workspaces/errors.gen.ts'
export { post41Errors as 'POST /apps/{app_id}/workflow/comments/{comment_id}/replies' } from './apps/errors.gen.ts'
export { post41Errors as 'POST /knowledge-fs/tasks/{task_id}/stream-capability' } from './knowledge-fs/errors.gen.ts'
export { post41Errors as 'POST /workspaces/current/plugin/upgrade/marketplace' } from './workspaces/errors.gen.ts'
export { post42Errors as 'POST /apps/{app_id}/workflow/comments/{comment_id}/resolve' } from './apps/errors.gen.ts'
export { post42Errors as 'POST /knowledge-fs/uploads' } from './knowledge-fs/errors.gen.ts'
export { post43Errors as 'POST /apps/{app_id}/workflow/comments' } from './apps/errors.gen.ts'
export { post43Errors as 'POST /workspaces/current/plugin/upload/github' } from './workspaces/errors.gen.ts'
export { post44Errors as 'POST /apps/{app_id}/workflows/draft/conversation-variables' } from './apps/errors.gen.ts'
export { post44Errors as 'POST /workspaces/current/plugin/upload/pkg' } from './workspaces/errors.gen.ts'
export { post45Errors as 'POST /apps/{app_id}/workflows/draft/environment-variables' } from './apps/errors.gen.ts'
export { post46Errors as 'POST /apps/{app_id}/workflows/draft/features' } from './apps/errors.gen.ts'
export { post47Errors as 'POST /apps/{app_id}/workflows/draft/human-input/nodes/{node_id}/delivery-test' } from './apps/errors.gen.ts'
export { post48Errors as 'POST /apps/{app_id}/workflows/draft/human-input/nodes/{node_id}/form/preview' } from './apps/errors.gen.ts'
export { post49Errors as 'POST /apps/{app_id}/workflows/draft/human-input/nodes/{node_id}/form/run' } from './apps/errors.gen.ts'
export { post49Errors as 'POST /workspaces/current/skills/files/upload' } from './workspaces/errors.gen.ts'
export { post4Errors as 'POST /account/change-email/validity' } from './account/errors.gen.ts'
export { post4Errors as 'POST /agent/{agent_id}/build-chat/finalize' } from './agent/errors.gen.ts'
export { post4Errors as 'POST /apps/{app_id}/advanced-chat/workflows/draft/human-input/nodes/{node_id}/form/preview' } from './apps/errors.gen.ts'
export { post4Errors as 'POST /datasets/indexing-estimate' } from './datasets/errors.gen.ts'
export { post4Errors as 'POST /installed-apps/{installed_app_id}/completion-messages/{task_id}/stop' } from './installed-apps/errors.gen.ts'
export { post4Errors as 'POST /knowledge-fs/spaces/{control_space_id}/background-tasks/{task_kind}/{task_id}/cancel' } from './knowledge-fs/errors.gen.ts'
export { post4Errors as 'POST /snippets/{snippet_id}/workflows/draft/nodes/{node_id}/agent-composer/copy-from-roster' } from './snippets/errors.gen.ts'
export { post4Errors as 'POST /trial-apps/{app_id}/completion-messages' } from './trial-apps/errors.gen.ts'
export { post50Errors as 'POST /apps/{app_id}/workflows/draft/iteration/nodes/{node_id}/run' } from './apps/errors.gen.ts'
export { post50Errors as 'POST /workspaces/current/skills/import' } from './workspaces/errors.gen.ts'
export { post51Errors as 'POST /apps/{app_id}/workflows/draft/loop/nodes/{node_id}/run' } from './apps/errors.gen.ts'
export { post51Errors as 'POST /workspaces/current/skills/{skill_id}/assist/messages' } from './workspaces/errors.gen.ts'
export { post52Errors as 'POST /apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer/copy-from-roster' } from './apps/errors.gen.ts'
export { post53Errors as 'POST /apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer/impact' } from './apps/errors.gen.ts'
export { post53Errors as 'POST /workspaces/current/skills/{skill_id}/files/check' } from './workspaces/errors.gen.ts'
export { post54Errors as 'POST /apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer/save-to-roster' } from './apps/errors.gen.ts'
export { post54Errors as 'POST /workspaces/current/skills/{skill_id}/publish' } from './workspaces/errors.gen.ts'
export { post55Errors as 'POST /apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer/validate' } from './apps/errors.gen.ts'
export { post55Errors as 'POST /workspaces/current/skills/{skill_id}/restore' } from './workspaces/errors.gen.ts'
export { post56Errors as 'POST /apps/{app_id}/workflows/draft/nodes/{node_id}/run' } from './apps/errors.gen.ts'
export { post56Errors as 'POST /workspaces/current/skills' } from './workspaces/errors.gen.ts'
export { post57Errors as 'POST /apps/{app_id}/workflows/draft/nodes/{node_id}/trigger/run' } from './apps/errors.gen.ts'
export { post58Errors as 'POST /apps/{app_id}/workflows/draft/run' } from './apps/errors.gen.ts'
export { post59Errors as 'POST /apps/{app_id}/workflows/draft/trigger/run' } from './apps/errors.gen.ts'
export { post5Errors as 'POST /account/change-email' } from './account/errors.gen.ts'
export { post5Errors as 'POST /agent/{agent_id}/build-draft/apply' } from './agent/errors.gen.ts'
export { post5Errors as 'POST /apps/{app_id}/advanced-chat/workflows/draft/human-input/nodes/{node_id}/form/run' } from './apps/errors.gen.ts'
export { post5Errors as 'POST /datasets/init' } from './datasets/errors.gen.ts'
export { post5Errors as 'POST /installed-apps/{installed_app_id}/completion-messages' } from './installed-apps/errors.gen.ts'
export { post5Errors as 'POST /knowledge-fs/spaces/{control_space_id}/background-tasks/{task_kind}/{task_id}/retry' } from './knowledge-fs/errors.gen.ts'
export { post5Errors as 'POST /trial-apps/{app_id}/files/upload' } from './trial-apps/errors.gen.ts'
export { post60Errors as 'POST /apps/{app_id}/workflows/draft/trigger/run-all' } from './apps/errors.gen.ts'
export { post61Errors as 'POST /apps/{app_id}/workflows/draft' } from './apps/errors.gen.ts'
export { post62Errors as 'POST /apps/{app_id}/workflows/publish' } from './apps/errors.gen.ts'
export { post63Errors as 'POST /apps/{app_id}/workflows/{workflow_id}/restore' } from './apps/errors.gen.ts'
export { post64Errors as 'POST /apps/{resource_id}/api-keys' } from './apps/errors.gen.ts'
export { post6Errors as 'POST /agent/{agent_id}/build-draft/checkout' } from './agent/errors.gen.ts'
export { post6Errors as 'POST /apps/{app_id}/advanced-chat/workflows/draft/iteration/nodes/{node_id}/run' } from './apps/errors.gen.ts'
export { post6Errors as 'POST /datasets/notion-indexing-estimate' } from './datasets/errors.gen.ts'
export { post6Errors as 'POST /installed-apps/{installed_app_id}/conversations/{c_id}/name' } from './installed-apps/errors.gen.ts'
export { post6Errors as 'POST /knowledge-fs/spaces/{control_space_id}/documents/reindex' } from './knowledge-fs/errors.gen.ts'
export { post6Errors as 'POST /snippets/{snippet_id}/workflows/draft/nodes/{node_id}/agent-composer/save-to-roster' } from './snippets/errors.gen.ts'
export { post6Errors as 'POST /trial-apps/{app_id}/remote-files/upload' } from './trial-apps/errors.gen.ts'
export { post7Errors as 'POST /account/delete' } from './account/errors.gen.ts'
export { post7Errors as 'POST /agent/{agent_id}/chat-messages/{task_id}/stop' } from './agent/errors.gen.ts'
export { post7Errors as 'POST /apps/{app_id}/advanced-chat/workflows/draft/loop/nodes/{node_id}/run' } from './apps/errors.gen.ts'
export { post7Errors as 'POST /installed-apps/{installed_app_id}/messages/{message_id}/feedbacks' } from './installed-apps/errors.gen.ts'
export { post7Errors as 'POST /knowledge-fs/spaces/{control_space_id}/documents' } from './knowledge-fs/errors.gen.ts'
export { post7Errors as 'POST /rag/pipelines/{pipeline_id}/customized/publish' } from './rag/errors.gen.ts'
export { post7Errors as 'POST /snippets/{snippet_id}/workflows/draft/nodes/{node_id}/agent-composer/validate' } from './snippets/errors.gen.ts'
export { post7Errors as 'POST /trial-apps/{app_id}/text-to-audio' } from './trial-apps/errors.gen.ts'
export { post80Errors as 'POST /workspaces/custom-config/webapp-logo/upload' } from './workspaces/errors.gen.ts'
export { post83Errors as 'POST /workspaces/switch' } from './workspaces/errors.gen.ts'
export { post8Errors as 'POST /account/education' } from './account/errors.gen.ts'
export { post8Errors as 'POST /agent/{agent_id}/composer/validate' } from './agent/errors.gen.ts'
export { post8Errors as 'POST /apps/{app_id}/advanced-chat/workflows/draft/run' } from './apps/errors.gen.ts'
export { post8Errors as 'POST /installed-apps/{installed_app_id}/saved-messages' } from './installed-apps/errors.gen.ts'
export { post8Errors as 'POST /knowledge-fs/spaces/{control_space_id}/golden-questions/bulk-import' } from './knowledge-fs/errors.gen.ts'
export { post8Errors as 'POST /rag/pipelines/{pipeline_id}/workflow-runs/tasks/{task_id}/stop' } from './rag/errors.gen.ts'
export { post8Errors as 'POST /trial-apps/{app_id}/workflows/run' } from './trial-apps/errors.gen.ts'
export { post9Errors as 'POST /account/init' } from './account/errors.gen.ts'
export { post9Errors as 'POST /agent/{agent_id}/config/files' } from './agent/errors.gen.ts'
export { post9Errors as 'POST /apps/{app_id}/agent/config/files' } from './apps/errors.gen.ts'
export { post9Errors as 'POST /installed-apps/{installed_app_id}/text-to-audio' } from './installed-apps/errors.gen.ts'
export { post9Errors as 'POST /knowledge-fs/spaces/{control_space_id}/golden-questions/evidence-matches' } from './knowledge-fs/errors.gen.ts'
export { post9Errors as 'POST /rag/pipelines/{pipeline_id}/workflows/draft/datasource/nodes/{node_id}/run' } from './rag/errors.gen.ts'
export { post9Errors as 'POST /trial-apps/{app_id}/workflows/tasks/{task_id}/stop' } from './trial-apps/errors.gen.ts'
export { postErrors as 'POST /account/avatar' } from './account/errors.gen.ts'
export { postErrors as 'POST /activate' } from './activate/errors.gen.ts'
export { postErrors as 'POST /agent/{agent_id}/api-enable' } from './agent/errors.gen.ts'
export { postErrors as 'POST /api-key-auth/data-source/binding' } from './api-key-auth/errors.gen.ts'
export { postErrors as 'POST /datasets/api-keys' } from './datasets/errors.gen.ts'
export { postErrors as 'POST /email-code-login/validity' } from './email-code-login/errors.gen.ts'
export { postErrors as 'POST /email-register/send-email' } from './email-register/errors.gen.ts'
export { postErrors as 'POST /files/upload' } from './files/errors.gen.ts'
export { postErrors as 'POST /forgot-password/resets' } from './forgot-password/errors.gen.ts'
export { postErrors as 'POST /form/human_input/{form_token}' } from './form/errors.gen.ts'
export { postErrors as 'POST /installed-apps/{installed_app_id}/audio-to-text' } from './installed-apps/errors.gen.ts'
export { postErrors as 'POST /knowledge-fs/query-stream' } from './knowledge-fs/errors.gen.ts'
export { postErrors as 'POST /login' } from './login/errors.gen.ts'
export { postErrors as 'POST /remote-files/upload' } from './remote-files/errors.gen.ts'
export { postErrors as 'POST /reset-password' } from './reset-password/errors.gen.ts'
export { postErrors as 'POST /rule-code-generate' } from './rule-code-generate/errors.gen.ts'
export { postErrors as 'POST /rule-generate' } from './rule-generate/errors.gen.ts'
export { postErrors as 'POST /rule-structured-output-generate' } from './rule-structured-output-generate/errors.gen.ts'
export { postErrors as 'POST /trial-apps/{app_id}/audio-to-text' } from './trial-apps/errors.gen.ts'
export { postErrors as 'POST /website/crawl' } from './website/errors.gen.ts'
export { put20Errors as 'PUT /workspaces/current/skills/{skill_id}/files' } from './workspaces/errors.gen.ts'
export { put2Errors as 'PUT /agent/{agent_id}/composer' } from './agent/errors.gen.ts'
export { put2Errors as 'PUT /apps/{app_id}/server' } from './apps/errors.gen.ts'
export { put2Errors as 'PUT /knowledge-fs/spaces/{control_space_id}/external-access' } from './knowledge-fs/errors.gen.ts'
export { put2Errors as 'PUT /workspaces/current/members/{member_id}/update-role' } from './workspaces/errors.gen.ts'
export { put3Errors as 'PUT /agent/{agent_id}' } from './agent/errors.gen.ts'
export { put3Errors as 'PUT /apps/{app_id}/workflow/comments/{comment_id}/replies/{reply_id}' } from './apps/errors.gen.ts'
export { put3Errors as 'PUT /knowledge-fs/spaces/{control_space_id}/members' } from './knowledge-fs/errors.gen.ts'
export { put4Errors as 'PUT /apps/{app_id}/workflow/comments/{comment_id}' } from './apps/errors.gen.ts'
export { put4Errors as 'PUT /knowledge-fs/spaces/{control_space_id}/sources/{source_id}/sync-policy' } from './knowledge-fs/errors.gen.ts'
export { put5Errors as 'PUT /apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer' } from './apps/errors.gen.ts'
export { put5Errors as 'PUT /knowledge-fs/spaces/{control_space_id}/tags' } from './knowledge-fs/errors.gen.ts'
export { put6Errors as 'PUT /apps/{app_id}/workflows/draft/variables/{variable_id}/reset' } from './apps/errors.gen.ts'
export { putErrors as 'PUT /agent/{agent_id}/build-draft' } from './agent/errors.gen.ts'
export { putErrors as 'PUT /apps/{app_id}/network-access-group' } from './apps/errors.gen.ts'
export { putErrors as 'PUT /knowledge-fs/spaces/{control_space_id}/app-bindings' } from './knowledge-fs/errors.gen.ts'
export { putErrors as 'PUT /rag/pipelines/{pipeline_id}/workflows/draft/variables/{variable_id}/reset' } from './rag/errors.gen.ts'
export { putErrors as 'PUT /snippets/{snippet_id}/workflows/draft/nodes/{node_id}/agent-composer' } from './snippets/errors.gen.ts'
export { putErrors as 'PUT /workspaces/current/agents/{agent_id}/skills' } from './workspaces/errors.gen.ts'
@@ -0,0 +1,23 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zRecommendedAppNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('recommended_app_not_found'),
status: z.literal(404),
}),
))()
export const get2Errors = {
recommended_app_not_found: { status: 404, data: zRecommendedAppNotFoundError },
}
@@ -0,0 +1,68 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zFileExtensionBlockedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('file_extension_blocked'),
status: z.literal(400),
}),
))()
const zFilenameNotExistsError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('filename_not_exists_error'),
status: z.literal(400),
}),
))()
const zNoFileUploadedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('no_file_uploaded'),
status: z.literal(400),
}),
))()
const zTooManyFilesError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('too_many_files'),
status: z.literal(400),
}),
))()
const zFileTooLargeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('file_too_large'),
status: z.literal(413),
}),
))()
const zUnsupportedFileTypeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('unsupported_file_type'),
status: z.literal(415),
}),
))()
export const postErrors = {
file_extension_blocked: { status: 400, data: zFileExtensionBlockedError },
file_too_large: { status: 413, data: zFileTooLargeError },
filename_not_exists_error: { status: 400, data: zFilenameNotExistsError },
no_file_uploaded: { status: 400, data: zNoFileUploadedError },
too_many_files: { status: 400, data: zTooManyFilesError },
unsupported_file_type: { status: 415, data: zUnsupportedFileTypeError },
}
@@ -0,0 +1,93 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zEmailSendIpLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_send_ip_limit'),
status: z.literal(429),
}),
))()
const zPasswordResetRateLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('password_reset_rate_limit_exceeded'),
status: z.literal(429),
}),
))()
const zAccountNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_not_found'),
status: z.literal(400),
}),
))()
const zInvalidOrExpiredTokenError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_or_expired_token'),
status: z.literal(400),
}),
))()
const zPasswordMismatchError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('password_mismatch'),
status: z.literal(400),
}),
))()
const zEmailCodeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_code_error'),
status: z.literal(400),
}),
))()
const zInvalidEmailError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_email'),
status: z.literal(400),
}),
))()
const zEmailPasswordResetLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_password_reset_limit'),
status: z.literal(429),
}),
))()
export const postErrors = {
account_not_found: { status: 400, data: zAccountNotFoundError },
invalid_or_expired_token: { status: 400, data: zInvalidOrExpiredTokenError },
password_mismatch: { status: 400, data: zPasswordMismatchError },
}
export const post2Errors = {
email_code_error: { status: 400, data: zEmailCodeError },
email_password_reset_limit: { status: 429, data: zEmailPasswordResetLimitError },
invalid_email: { status: 400, data: zInvalidEmailError },
invalid_or_expired_token: { status: 400, data: zInvalidOrExpiredTokenError },
}
export const post3Errors = {
email_send_ip_limit: { status: 429, data: zEmailSendIpLimitError },
password_reset_rate_limit_exceeded: { status: 429, data: zPasswordResetRateLimitExceededError },
}
@@ -0,0 +1,45 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zHumanInputFormSubmittedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('human_input_form_submitted'),
status: z.literal(412),
}),
))()
const zInvalidFormDataError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_form_data'),
status: z.literal(400),
}),
))()
const zHumanInputFormExpiredError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('human_input_form_expired'),
status: z.literal(412),
}),
))()
export const getErrors = {
human_input_form_submitted: { status: 412, data: zHumanInputFormSubmittedError },
}
export const postErrors = {
human_input_form_expired: { status: 412, data: zHumanInputFormExpiredError },
human_input_form_submitted: { status: 412, data: zHumanInputFormSubmittedError },
invalid_form_data: { status: 400, data: zInvalidFormDataError },
}
@@ -0,0 +1,486 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zInvalidCursorError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_cursor'),
status: z.literal(400),
}),
))()
const zWebAppAccessUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('web_app_access_unavailable'),
status: z.literal(503),
}),
))()
const zAccessDeniedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('access_denied'),
status: z.literal(403),
}),
))()
const zInstalledAppNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('installed_app_not_found'),
status: z.literal(404),
}),
))()
const zInstalledAppUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('installed_app_unavailable'),
status: z.literal(404),
}),
))()
const zAppUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_unavailable'),
status: z.literal(400),
}),
))()
const zCompletionRequestError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('completion_request_error'),
status: z.literal(400),
}),
))()
const zModelCurrentlyNotSupportError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('model_currently_not_support'),
status: z.literal(400),
}),
))()
const zNoAudioUploadedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('no_audio_uploaded'),
status: z.literal(400),
}),
))()
const zProviderNotInitializeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_initialize'),
status: z.literal(400),
}),
))()
const zProviderNotSupportSpeechToTextError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_support_speech_to_text'),
status: z.literal(400),
}),
))()
const zProviderQuotaExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_quota_exceeded'),
status: z.literal(400),
}),
))()
const zSpeechToTextDisabledError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('speech_to_text_disabled'),
status: z.literal(400),
}),
))()
const zAgentVersionNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_version_not_found_error'),
status: z.literal(404),
}),
))()
const zAudioTooLargeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('audio_too_large'),
status: z.literal(413),
}),
))()
const zUnsupportedAudioTypeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('unsupported_audio_type'),
status: z.literal(415),
}),
))()
const zNotChatAppError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('not_chat_app'),
status: z.literal(400),
}),
))()
const zRateLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('rate_limit_error'),
status: z.literal(429),
}),
))()
const zNotCompletionAppError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('not_completion_app'),
status: z.literal(400),
}),
))()
const zConversationCursorNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('conversation_cursor_not_found'),
status: z.literal(404),
}),
))()
const zConversationNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('conversation_not_found'),
status: z.literal(404),
}),
))()
const zConversationNameRequiredError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('conversation_name_required'),
status: z.literal(400),
}),
))()
const zConversationFirstMessageNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('conversation_first_message_not_found'),
status: z.literal(404),
}),
))()
const zMessageCursorNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('message_cursor_not_found'),
status: z.literal(404),
}),
))()
const zMessageFeedbackRatingRequiredError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('message_feedback_rating_required'),
status: z.literal(400),
}),
))()
const zMessageNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('message_not_found'),
status: z.literal(404),
}),
))()
const zAppMoreLikeThisDisabledError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_more_like_this_disabled'),
status: z.literal(403),
}),
))()
const zAppSuggestedQuestionsAfterAnswerDisabledError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_suggested_questions_after_answer_disabled'),
status: z.literal(403),
}),
))()
const zProviderNotSupportTextToSpeechError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_support_text_to_speech'),
status: z.literal(400),
}),
))()
const zNotWorkflowAppError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('not_workflow_app'),
status: z.literal(400),
}),
))()
export const postErrors = {
access_denied: { status: 403, data: zAccessDeniedError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
audio_too_large: { status: 413, data: zAudioTooLargeError },
completion_request_error: { status: 400, data: zCompletionRequestError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
no_audio_uploaded: { status: 400, data: zNoAudioUploadedError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_not_support_speech_to_text: { status: 400, data: zProviderNotSupportSpeechToTextError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
speech_to_text_disabled: { status: 400, data: zSpeechToTextDisabledError },
unsupported_audio_type: { status: 415, data: zUnsupportedAudioTypeError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const post2Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
not_chat_app: { status: 400, data: zNotChatAppError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const post3Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_chat_app: { status: 400, data: zNotChatAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
rate_limit_error: { status: 429, data: zRateLimitError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const post4Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
not_completion_app: { status: 400, data: zNotCompletionAppError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const post5Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_completion_app: { status: 400, data: zNotCompletionAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const post6Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
conversation_first_message_not_found: {
status: 404,
data: zConversationFirstMessageNotFoundError,
},
conversation_name_required: { status: 400, data: zConversationNameRequiredError },
conversation_not_found: { status: 404, data: zConversationNotFoundError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
not_chat_app: { status: 400, data: zNotChatAppError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const patchErrors = {
access_denied: { status: 403, data: zAccessDeniedError },
conversation_not_found: { status: 404, data: zConversationNotFoundError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
not_chat_app: { status: 400, data: zNotChatAppError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const patch2Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
conversation_not_found: { status: 404, data: zConversationNotFoundError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
not_chat_app: { status: 400, data: zNotChatAppError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const delete_Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
conversation_not_found: { status: 404, data: zConversationNotFoundError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
not_chat_app: { status: 400, data: zNotChatAppError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const getErrors = {
access_denied: { status: 403, data: zAccessDeniedError },
conversation_cursor_not_found: { status: 404, data: zConversationCursorNotFoundError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
not_chat_app: { status: 400, data: zNotChatAppError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const post7Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
message_feedback_rating_required: { status: 400, data: zMessageFeedbackRatingRequiredError },
message_not_found: { status: 404, data: zMessageNotFoundError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const get2Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
app_more_like_this_disabled: { status: 403, data: zAppMoreLikeThisDisabledError },
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
message_not_found: { status: 404, data: zMessageNotFoundError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_completion_app: { status: 400, data: zNotCompletionAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const get3Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
app_suggested_questions_after_answer_disabled: {
status: 403,
data: zAppSuggestedQuestionsAfterAnswerDisabledError,
},
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
conversation_not_found: { status: 404, data: zConversationNotFoundError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
message_not_found: { status: 404, data: zMessageNotFoundError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_chat_app: { status: 400, data: zNotChatAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const get4Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
conversation_not_found: { status: 404, data: zConversationNotFoundError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
message_cursor_not_found: { status: 404, data: zMessageCursorNotFoundError },
not_chat_app: { status: 400, data: zNotChatAppError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const get5Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
app_unavailable: { status: 400, data: zAppUnavailableError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const get6Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
app_unavailable: { status: 400, data: zAppUnavailableError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const delete2Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
not_completion_app: { status: 400, data: zNotCompletionAppError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const get7Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
not_completion_app: { status: 400, data: zNotCompletionAppError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const post8Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
not_completion_app: { status: 400, data: zNotCompletionAppError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const post9Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_not_support_text_to_speech: { status: 400, data: zProviderNotSupportTextToSpeechError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const post10Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
completion_request_error: { status: 400, data: zCompletionRequestError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_workflow_app: { status: 400, data: zNotWorkflowAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
rate_limit_error: { status: 429, data: zRateLimitError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const post11Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
not_workflow_app: { status: 400, data: zNotWorkflowAppError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const get8Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
installed_app_unavailable: { status: 404, data: zInstalledAppUnavailableError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const patch3Errors = {
access_denied: { status: 403, data: zAccessDeniedError },
installed_app_not_found: { status: 404, data: zInstalledAppNotFoundError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
export const get9Errors = {
invalid_cursor: { status: 400, data: zInvalidCursorError },
web_app_access_unavailable: { status: 503, data: zWebAppAccessUnavailableError },
}
@@ -613,8 +613,6 @@ export type TextToAudioPayload = {
voice?: string | null
}
export type AudioBinaryResponse = Blob | File
export type ProviderNotSupportTextToSpeechError = ErrorResponse & {
code: 'provider_not_support_text_to_speech'
status: 400
@@ -1675,7 +1673,7 @@ export type PostInstalledAppsByInstalledAppIdTextToAudioError =
PostInstalledAppsByInstalledAppIdTextToAudioErrors[keyof PostInstalledAppsByInstalledAppIdTextToAudioErrors]
export type PostInstalledAppsByInstalledAppIdTextToAudioResponses = {
200: AudioBinaryResponse
200: Blob | File
}
export type PostInstalledAppsByInstalledAppIdTextToAudioResponse =
@@ -475,13 +475,6 @@ export const zTextToAudioPayload = z.object({
voice: z.string().nullish(),
})
/**
* AudioBinaryResponse
*/
export const zAudioBinaryResponse = z.custom<Blob | File>(
(value) => value instanceof Blob || value instanceof File,
)
/**
* ProviderNotSupportTextToSpeechError
*
@@ -1640,7 +1633,9 @@ export const zPostInstalledAppsByInstalledAppIdTextToAudioPath = z.object({
/**
* Success
*/
export const zPostInstalledAppsByInstalledAppIdTextToAudioResponse = zAudioBinaryResponse
export const zPostInstalledAppsByInstalledAppIdTextToAudioResponse = z.custom<Blob | File>(
(value) => value instanceof Blob || value instanceof File,
)
export const zPostInstalledAppsByInstalledAppIdWorkflowsRunBody = zWorkflowRunPayload
@@ -0,0 +1,50 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zCompletionRequestError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('completion_request_error'),
status: z.literal(400),
}),
))()
const zModelCurrentlyNotSupportError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('model_currently_not_support'),
status: z.literal(400),
}),
))()
const zProviderNotInitializeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_initialize'),
status: z.literal(400),
}),
))()
const zProviderQuotaExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_quota_exceeded'),
status: z.literal(400),
}),
))()
export const post2Errors = {
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,95 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zAccountBannedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_banned'),
status: z.literal(400),
}),
))()
const zAccountInFreezeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_in_freeze'),
status: z.literal(400),
}),
))()
const zAccountNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_not_found'),
status: z.literal(400),
}),
))()
const zEmailDomainSuspendedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_domain_suspended'),
status: z.literal(400),
}),
))()
const zInvalidAccountPasswordError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_account_password'),
status: z.literal(400),
}),
))()
const zInvalidEmailError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_email'),
status: z.literal(400),
}),
))()
const zLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('limit_exceeded'),
status: z.literal(400),
}),
))()
const zAuthenticationFailedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('authentication_failed'),
status: z.literal(401),
}),
))()
const zEmailCodeLoginLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_code_login_limit'),
status: z.literal(429),
}),
))()
export const postErrors = {
account_banned: { status: 400, data: zAccountBannedError },
account_in_freeze: { status: 400, data: zAccountInFreezeError },
account_not_found: { status: 400, data: zAccountNotFoundError },
authentication_failed: { status: 401, data: zAuthenticationFailedError },
email_code_login_limit: { status: 429, data: zEmailCodeLoginLimitError },
email_domain_suspended: { status: 400, data: zEmailDomainSuspendedError },
invalid_account_password: { status: 400, data: zInvalidAccountPasswordError },
invalid_email: { status: 400, data: zInvalidEmailError },
limit_exceeded: { status: 400, data: zLimitExceededError },
}
@@ -0,0 +1,23 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zDatasetAccessDeniedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('dataset_access_denied'),
status: z.literal(403),
}),
))()
export const get2Errors = {
dataset_access_denied: { status: 403, data: zDatasetAccessDeniedError },
}
+155
View File
@@ -0,0 +1,155 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zDatasetNameDuplicateError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('dataset_name_duplicate'),
status: z.literal(409),
}),
))()
const zPipelineNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('pipeline_not_found'),
status: z.literal(404),
}),
))()
const zDraftWorkflowNotExistError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('draft_workflow_not_exist'),
status: z.literal(404),
}),
))()
const zDraftWorkflowNotSyncError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('draft_workflow_not_sync'),
status: z.literal(409),
}),
))()
const zRateLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('rate_limit_error'),
status: z.literal(429),
}),
))()
export const post2Errors = {
dataset_name_duplicate: { status: 409, data: zDatasetNameDuplicateError },
}
export const get4Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const post7Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get6Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const post8Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get7Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get8Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get9Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get10Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get11Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const post9Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const post10Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get12Errors = {
draft_workflow_not_exist: { status: 404, data: zDraftWorkflowNotExistError },
pipeline_not_found: { status: 404, data: zPipelineNotFoundError },
}
export const post11Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const post12Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get13Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const post13Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const delete2Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get14Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get15Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get16Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const post14Errors = {
pipeline_not_found: { status: 404, data: zPipelineNotFoundError },
rate_limit_error: { status: 429, data: zRateLimitError },
}
export const get17Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const putErrors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const delete3Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get18Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const patch2Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const delete4Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get19Errors = {
draft_workflow_not_exist: { status: 404, data: zDraftWorkflowNotExistError },
pipeline_not_found: { status: 404, data: zPipelineNotFoundError },
}
export const get20Errors = {
draft_workflow_not_exist: { status: 404, data: zDraftWorkflowNotExistError },
pipeline_not_found: { status: 404, data: zPipelineNotFoundError },
}
export const post15Errors = {
draft_workflow_not_sync: { status: 409, data: zDraftWorkflowNotSyncError },
pipeline_not_found: { status: 404, data: zPipelineNotFoundError },
}
export const get21Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const post16Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const post17Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const post18Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get22Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get23Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const post19Errors = {
pipeline_not_found: { status: 404, data: zPipelineNotFoundError },
rate_limit_error: { status: 429, data: zRateLimitError },
}
export const post20Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const delete5Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const patch3Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
export const get24Errors = { pipeline_not_found: { status: 404, data: zPipelineNotFoundError } }
@@ -0,0 +1,104 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zFileExtensionBlockedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('file_extension_blocked'),
status: z.literal(400),
}),
))()
const zRemoteFileAccessDeniedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_access_denied'),
status: z.literal(400),
}),
))()
const zRemoteFileInvalidUrlError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_invalid_url'),
status: z.literal(400),
}),
))()
const zRemoteFileUrlBlockedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_url_blocked'),
status: z.literal(400),
}),
))()
const zRemoteFileNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_not_found'),
status: z.literal(404),
}),
))()
const zFileTooLargeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('file_too_large'),
status: z.literal(413),
}),
))()
const zUnsupportedFileTypeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('unsupported_file_type'),
status: z.literal(415),
}),
))()
const zRemoteFileInvalidResponseError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_invalid_response'),
status: z.literal(502),
}),
))()
const zRemoteFileUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_unavailable'),
status: z.literal(502),
}),
))()
export const postErrors = {
file_extension_blocked: { status: 400, data: zFileExtensionBlockedError },
file_too_large: { status: 413, data: zFileTooLargeError },
remote_file_access_denied: { status: 400, data: zRemoteFileAccessDeniedError },
remote_file_invalid_response: { status: 502, data: zRemoteFileInvalidResponseError },
remote_file_invalid_url: { status: 400, data: zRemoteFileInvalidUrlError },
remote_file_not_found: { status: 404, data: zRemoteFileNotFoundError },
remote_file_unavailable: { status: 502, data: zRemoteFileUnavailableError },
remote_file_url_blocked: { status: 400, data: zRemoteFileUrlBlockedError },
unsupported_file_type: { status: 415, data: zUnsupportedFileTypeError },
}
export const getErrors = {
remote_file_access_denied: { status: 400, data: zRemoteFileAccessDeniedError },
remote_file_invalid_response: { status: 502, data: zRemoteFileInvalidResponseError },
remote_file_invalid_url: { status: 400, data: zRemoteFileInvalidUrlError },
remote_file_not_found: { status: 404, data: zRemoteFileNotFoundError },
remote_file_unavailable: { status: 502, data: zRemoteFileUnavailableError },
remote_file_url_blocked: { status: 400, data: zRemoteFileUrlBlockedError },
}
@@ -0,0 +1,50 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zAccountBannedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_banned'),
status: z.literal(400),
}),
))()
const zAccountInFreezeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_in_freeze'),
status: z.literal(400),
}),
))()
const zEmailDomainSuspendedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_domain_suspended'),
status: z.literal(400),
}),
))()
const zPasswordResetRateLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('password_reset_rate_limit_exceeded'),
status: z.literal(429),
}),
))()
export const postErrors = {
account_banned: { status: 400, data: zAccountBannedError },
account_in_freeze: { status: 400, data: zAccountInFreezeError },
email_domain_suspended: { status: 400, data: zEmailDomainSuspendedError },
password_reset_rate_limit_exceeded: { status: 429, data: zPasswordResetRateLimitExceededError },
}
@@ -0,0 +1,50 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zCompletionRequestError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('completion_request_error'),
status: z.literal(400),
}),
))()
const zModelCurrentlyNotSupportError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('model_currently_not_support'),
status: z.literal(400),
}),
))()
const zProviderNotInitializeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_initialize'),
status: z.literal(400),
}),
))()
const zProviderQuotaExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_quota_exceeded'),
status: z.literal(400),
}),
))()
export const postErrors = {
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
@@ -0,0 +1,50 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zCompletionRequestError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('completion_request_error'),
status: z.literal(400),
}),
))()
const zModelCurrentlyNotSupportError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('model_currently_not_support'),
status: z.literal(400),
}),
))()
const zProviderNotInitializeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_initialize'),
status: z.literal(400),
}),
))()
const zProviderQuotaExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_quota_exceeded'),
status: z.literal(400),
}),
))()
export const postErrors = {
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
@@ -0,0 +1,50 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zCompletionRequestError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('completion_request_error'),
status: z.literal(400),
}),
))()
const zModelCurrentlyNotSupportError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('model_currently_not_support'),
status: z.literal(400),
}),
))()
const zProviderNotInitializeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_initialize'),
status: z.literal(400),
}),
))()
const zProviderQuotaExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_quota_exceeded'),
status: z.literal(400),
}),
))()
export const postErrors = {
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
@@ -0,0 +1,135 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zDraftWorkflowNotExistError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('draft_workflow_not_exist'),
status: z.literal(404),
}),
))()
const zDraftWorkflowNotSyncError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('draft_workflow_not_sync'),
status: z.literal(409),
}),
))()
const zAgentNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_not_found_error'),
status: z.literal(404),
}),
))()
const zAgentVersionNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_version_not_found_error'),
status: z.literal(404),
}),
))()
const zAgentSoulLockedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_soul_locked_error'),
status: z.literal(400),
}),
))()
const zInvalidComposerConfigError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_composer_config_error'),
status: z.literal(400),
}),
))()
const zPlaintextSecretNotAllowedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('plaintext_secret_not_allowed_error'),
status: z.literal(400),
}),
))()
const zAgentNameConflictError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_name_conflict_error'),
status: z.literal(409),
}),
))()
const zAgentVersionConflictError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_version_conflict_error'),
status: z.literal(409),
}),
))()
export const get7Errors = {
draft_workflow_not_exist: { status: 404, data: zDraftWorkflowNotExistError },
}
export const post4Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_version_conflict_error: { status: 409, data: zAgentVersionConflictError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
invalid_composer_config_error: { status: 400, data: zInvalidComposerConfigError },
}
export const post6Errors = {
agent_name_conflict_error: { status: 409, data: zAgentNameConflictError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_soul_locked_error: { status: 400, data: zAgentSoulLockedError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
invalid_composer_config_error: { status: 400, data: zInvalidComposerConfigError },
plaintext_secret_not_allowed_error: { status: 400, data: zPlaintextSecretNotAllowedError },
}
export const post7Errors = {
agent_soul_locked_error: { status: 400, data: zAgentSoulLockedError },
invalid_composer_config_error: { status: 400, data: zInvalidComposerConfigError },
plaintext_secret_not_allowed_error: { status: 400, data: zPlaintextSecretNotAllowedError },
}
export const get9Errors = {
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
}
export const putErrors = {
agent_name_conflict_error: { status: 409, data: zAgentNameConflictError },
agent_not_found_error: { status: 404, data: zAgentNotFoundError },
agent_soul_locked_error: { status: 400, data: zAgentSoulLockedError },
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
invalid_composer_config_error: { status: 400, data: zInvalidComposerConfigError },
plaintext_secret_not_allowed_error: { status: 400, data: zPlaintextSecretNotAllowedError },
}
export const get14Errors = {
draft_workflow_not_exist: { status: 404, data: zDraftWorkflowNotExistError },
}
export const get15Errors = {
draft_workflow_not_exist: { status: 404, data: zDraftWorkflowNotExistError },
}
export const post10Errors = {
draft_workflow_not_sync: { status: 409, data: zDraftWorkflowNotSyncError },
}
@@ -0,0 +1,522 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zAppUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_unavailable'),
status: z.literal(400),
}),
))()
const zAppSiteUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_site_unavailable'),
status: z.literal(403),
}),
))()
const zAppNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_not_found'),
status: z.literal(404),
}),
))()
const zCompletionRequestError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('completion_request_error'),
status: z.literal(400),
}),
))()
const zModelCurrentlyNotSupportError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('model_currently_not_support'),
status: z.literal(400),
}),
))()
const zNoAudioUploadedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('no_audio_uploaded'),
status: z.literal(400),
}),
))()
const zProviderNotInitializeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_initialize'),
status: z.literal(400),
}),
))()
const zProviderNotSupportSpeechToTextError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_support_speech_to_text'),
status: z.literal(400),
}),
))()
const zProviderQuotaExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_quota_exceeded'),
status: z.literal(400),
}),
))()
const zSpeechToTextDisabledError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('speech_to_text_disabled'),
status: z.literal(400),
}),
))()
const zTrialAppFeatureDisabledError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('trial_app_feature_disabled'),
status: z.literal(403),
}),
))()
const zTrialAppLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('trial_app_limit_exceeded'),
status: z.literal(403),
}),
))()
const zTrialAppNotAllowedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('trial_app_not_allowed'),
status: z.literal(403),
}),
))()
const zAgentVersionNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_version_not_found_error'),
status: z.literal(404),
}),
))()
const zAudioTooLargeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('audio_too_large'),
status: z.literal(413),
}),
))()
const zUnsupportedAudioTypeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('unsupported_audio_type'),
status: z.literal(415),
}),
))()
const zNotChatAppError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('not_chat_app'),
status: z.literal(400),
}),
))()
const zRateLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('rate_limit_error'),
status: z.literal(429),
}),
))()
const zNotCompletionAppError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('not_completion_app'),
status: z.literal(400),
}),
))()
const zNeedAddIdsError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('need_add_ids'),
status: z.literal(400),
}),
))()
const zRecommendedAppNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('recommended_app_not_found'),
status: z.literal(404),
}),
))()
const zRosterAgentPackageExportFailedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('roster_agent_package_export_failed'),
status: z.literal(500),
}),
))()
const zFileExtensionBlockedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('file_extension_blocked'),
status: z.literal(400),
}),
))()
const zFilenameNotExistsError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('filename_not_exists_error'),
status: z.literal(400),
}),
))()
const zNoFileUploadedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('no_file_uploaded'),
status: z.literal(400),
}),
))()
const zTooManyFilesError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('too_many_files'),
status: z.literal(400),
}),
))()
const zFileTooLargeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('file_too_large'),
status: z.literal(413),
}),
))()
const zUnsupportedFileTypeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('unsupported_file_type'),
status: z.literal(415),
}),
))()
const zAppSuggestedQuestionsAfterAnswerDisabledError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_suggested_questions_after_answer_disabled'),
status: z.literal(403),
}),
))()
const zRemoteFileAccessDeniedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_access_denied'),
status: z.literal(400),
}),
))()
const zRemoteFileInvalidUrlError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_invalid_url'),
status: z.literal(400),
}),
))()
const zRemoteFileUrlBlockedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_url_blocked'),
status: z.literal(400),
}),
))()
const zRemoteFileNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_not_found'),
status: z.literal(404),
}),
))()
const zRemoteFileInvalidResponseError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_invalid_response'),
status: z.literal(502),
}),
))()
const zRemoteFileUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_unavailable'),
status: z.literal(502),
}),
))()
const zAppOwnerUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_owner_unavailable'),
status: z.literal(403),
}),
))()
const zProviderNotSupportTextToSpeechError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_support_text_to_speech'),
status: z.literal(400),
}),
))()
const zNotWorkflowAppError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('not_workflow_app'),
status: z.literal(400),
}),
))()
export const getErrors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const get2Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const get3Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const get4Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const get5Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const get6Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const get7Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const get8Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const get9Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const get10Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const postErrors = {
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
audio_too_large: { status: 413, data: zAudioTooLargeError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
no_audio_uploaded: { status: 400, data: zNoAudioUploadedError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_not_support_speech_to_text: { status: 400, data: zProviderNotSupportSpeechToTextError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
speech_to_text_disabled: { status: 400, data: zSpeechToTextDisabledError },
trial_app_feature_disabled: { status: 403, data: zTrialAppFeatureDisabledError },
trial_app_limit_exceeded: { status: 403, data: zTrialAppLimitExceededError },
trial_app_not_allowed: { status: 403, data: zTrialAppNotAllowedError },
unsupported_audio_type: { status: 415, data: zUnsupportedAudioTypeError },
}
export const post2Errors = {
not_chat_app: { status: 400, data: zNotChatAppError },
trial_app_feature_disabled: { status: 403, data: zTrialAppFeatureDisabledError },
trial_app_not_allowed: { status: 403, data: zTrialAppNotAllowedError },
}
export const post3Errors = {
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_chat_app: { status: 400, data: zNotChatAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
rate_limit_error: { status: 429, data: zRateLimitError },
trial_app_feature_disabled: { status: 403, data: zTrialAppFeatureDisabledError },
trial_app_limit_exceeded: { status: 403, data: zTrialAppLimitExceededError },
trial_app_not_allowed: { status: 403, data: zTrialAppNotAllowedError },
}
export const post4Errors = {
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_completion_app: { status: 400, data: zNotCompletionAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
rate_limit_error: { status: 429, data: zRateLimitError },
trial_app_feature_disabled: { status: 403, data: zTrialAppFeatureDisabledError },
trial_app_limit_exceeded: { status: 403, data: zTrialAppLimitExceededError },
trial_app_not_allowed: { status: 403, data: zTrialAppNotAllowedError },
}
export const get11Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
need_add_ids: { status: 400, data: zNeedAddIdsError },
}
export const get12Errors = {
recommended_app_not_found: { status: 404, data: zRecommendedAppNotFoundError },
roster_agent_package_export_failed: { status: 500, data: zRosterAgentPackageExportFailedError },
}
export const post5Errors = {
file_extension_blocked: { status: 400, data: zFileExtensionBlockedError },
file_too_large: { status: 413, data: zFileTooLargeError },
filename_not_exists_error: { status: 400, data: zFilenameNotExistsError },
no_file_uploaded: { status: 400, data: zNoFileUploadedError },
too_many_files: { status: 400, data: zTooManyFilesError },
trial_app_feature_disabled: { status: 403, data: zTrialAppFeatureDisabledError },
trial_app_limit_exceeded: { status: 403, data: zTrialAppLimitExceededError },
trial_app_not_allowed: { status: 403, data: zTrialAppNotAllowedError },
unsupported_file_type: { status: 415, data: zUnsupportedFileTypeError },
}
export const get13Errors = {
app_suggested_questions_after_answer_disabled: {
status: 403,
data: zAppSuggestedQuestionsAfterAnswerDisabledError,
},
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_chat_app: { status: 400, data: zNotChatAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
trial_app_feature_disabled: { status: 403, data: zTrialAppFeatureDisabledError },
trial_app_limit_exceeded: { status: 403, data: zTrialAppLimitExceededError },
trial_app_not_allowed: { status: 403, data: zTrialAppNotAllowedError },
}
export const get14Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const post6Errors = {
file_extension_blocked: { status: 400, data: zFileExtensionBlockedError },
file_too_large: { status: 413, data: zFileTooLargeError },
remote_file_access_denied: { status: 400, data: zRemoteFileAccessDeniedError },
remote_file_invalid_response: { status: 502, data: zRemoteFileInvalidResponseError },
remote_file_invalid_url: { status: 400, data: zRemoteFileInvalidUrlError },
remote_file_not_found: { status: 404, data: zRemoteFileNotFoundError },
remote_file_unavailable: { status: 502, data: zRemoteFileUnavailableError },
remote_file_url_blocked: { status: 400, data: zRemoteFileUrlBlockedError },
trial_app_feature_disabled: { status: 403, data: zTrialAppFeatureDisabledError },
trial_app_limit_exceeded: { status: 403, data: zTrialAppLimitExceededError },
trial_app_not_allowed: { status: 403, data: zTrialAppNotAllowedError },
unsupported_file_type: { status: 415, data: zUnsupportedFileTypeError },
}
export const get15Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_owner_unavailable: { status: 403, data: zAppOwnerUnavailableError },
app_site_unavailable: { status: 403, data: zAppSiteUnavailableError },
}
export const post7Errors = {
agent_version_not_found_error: { status: 404, data: zAgentVersionNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_not_support_text_to_speech: { status: 400, data: zProviderNotSupportTextToSpeechError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
trial_app_feature_disabled: { status: 403, data: zTrialAppFeatureDisabledError },
trial_app_limit_exceeded: { status: 403, data: zTrialAppLimitExceededError },
trial_app_not_allowed: { status: 403, data: zTrialAppNotAllowedError },
}
export const post8Errors = {
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_workflow_app: { status: 400, data: zNotWorkflowAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
rate_limit_error: { status: 429, data: zRateLimitError },
trial_app_feature_disabled: { status: 403, data: zTrialAppFeatureDisabledError },
trial_app_limit_exceeded: { status: 403, data: zTrialAppLimitExceededError },
trial_app_not_allowed: { status: 403, data: zTrialAppNotAllowedError },
}
export const post9Errors = {
not_workflow_app: { status: 400, data: zNotWorkflowAppError },
trial_app_feature_disabled: { status: 403, data: zTrialAppFeatureDisabledError },
trial_app_limit_exceeded: { status: 403, data: zTrialAppLimitExceededError },
trial_app_not_allowed: { status: 403, data: zTrialAppNotAllowedError },
}
export const get16Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const get17Errors = {
app_not_found: { status: 404, data: zAppNotFoundError },
app_site_unavailable: { status: 403, data: zAppSiteUnavailableError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
@@ -711,8 +711,6 @@ export type TextToSpeechRequest = {
voice?: string | null
}
export type AudioBinaryResponse = Blob | File
export type ProviderNotSupportTextToSpeechError = ErrorResponse & {
code: 'provider_not_support_text_to_speech'
status: 400
@@ -2193,7 +2191,7 @@ export type PostTrialAppsByAppIdTextToAudioError =
PostTrialAppsByAppIdTextToAudioErrors[keyof PostTrialAppsByAppIdTextToAudioErrors]
export type PostTrialAppsByAppIdTextToAudioResponses = {
200: AudioBinaryResponse
200: Blob | File
}
export type PostTrialAppsByAppIdTextToAudioResponse =
@@ -603,13 +603,6 @@ export const zTextToSpeechRequest = z.object({
voice: z.string().nullish(),
})
/**
* AudioBinaryResponse
*/
export const zAudioBinaryResponse = z.custom<Blob | File>(
(value) => value instanceof Blob || value instanceof File,
)
/**
* ProviderNotSupportTextToSpeechError
*
@@ -2463,7 +2456,9 @@ export const zPostTrialAppsByAppIdTextToAudioPath = z.object({
/**
* Success
*/
export const zPostTrialAppsByAppIdTextToAudioResponse = zAudioBinaryResponse
export const zPostTrialAppsByAppIdTextToAudioResponse = z.custom<Blob | File>(
(value) => value instanceof Blob || value instanceof File,
)
export const zGetTrialAppsByAppIdWorkflowsPath = z.object({
app_id: z.uuid(),
@@ -0,0 +1,23 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zCrawlFailedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('crawl_failed'),
status: z.literal(500),
}),
))()
export const getErrors = { crawl_failed: { status: 500, data: zCrawlFailedError } }
export const postErrors = { crawl_failed: { status: 500, data: zCrawlFailedError } }
@@ -0,0 +1,50 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zCompletionRequestError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('completion_request_error'),
status: z.literal(400),
}),
))()
const zModelCurrentlyNotSupportError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('model_currently_not_support'),
status: z.literal(400),
}),
))()
const zProviderNotInitializeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_initialize'),
status: z.literal(400),
}),
))()
const zProviderQuotaExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_quota_exceeded'),
status: z.literal(400),
}),
))()
export const post3Errors = {
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
@@ -0,0 +1,351 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zInvalidRequestError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_request'),
status: z.literal(400),
}),
))()
const zInvalidRoleError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_role'),
status: z.literal(400),
}),
))()
const zLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('limit_exceeded'),
status: z.literal(400),
}),
))()
const zEmailCodeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_code_error'),
status: z.literal(400),
}),
))()
const zInvalidEmailError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_email'),
status: z.literal(400),
}),
))()
const zInvalidOrExpiredTokenError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_or_expired_token'),
status: z.literal(400),
}),
))()
const zNotOwnerError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('not_owner'),
status: z.literal(400),
}),
))()
const zOwnerTransferLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('owner_transfer_limit'),
status: z.literal(429),
}),
))()
const zEmailSendIpLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_send_ip_limit'),
status: z.literal(429),
}),
))()
const zOwnerTransferRateLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('owner_transfer_rate_limit_exceeded'),
status: z.literal(429),
}),
))()
const zCannotOperateSelfError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('cannot_operate_self'),
status: z.literal(400),
}),
))()
const zForbiddenError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('forbidden'),
status: z.literal(403),
}),
))()
const zMemberNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('member_not_found'),
status: z.literal(404),
}),
))()
const zCannotTransferOwnerToSelfError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('cannot_transfer_owner_to_self'),
status: z.literal(400),
}),
))()
const zMemberNotInTenantError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('member_not_in_tenant'),
status: z.literal(400),
}),
))()
const zRoleAlreadyAssignedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('role_already_assigned'),
status: z.literal(400),
}),
))()
const zPluginError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('plugin_error'),
status: z.literal(400),
}),
))()
const zFilenameMissingError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('filename_missing'),
status: z.literal(400),
}),
))()
const zNoFileUploadedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('no_file_uploaded'),
status: z.literal(400),
}),
))()
const zCurrentWorkspaceArchivedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('current_workspace_archived'),
status: z.literal(409),
}),
))()
const zFilenameNotExistsError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('filename_not_exists_error'),
status: z.literal(400),
}),
))()
const zTooManyFilesError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('too_many_files'),
status: z.literal(400),
}),
))()
const zFileTooLargeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('file_too_large'),
status: z.literal(413),
}),
))()
const zUnsupportedFileTypeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('unsupported_file_type'),
status: z.literal(415),
}),
))()
const zAccountNotLinkTenantError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_not_link_tenant'),
status: z.literal(403),
}),
))()
export const putErrors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const post12Errors = {
invalid_role: { status: 400, data: zInvalidRoleError },
limit_exceeded: { status: 400, data: zLimitExceededError },
}
export const post13Errors = {
email_code_error: { status: 400, data: zEmailCodeError },
invalid_email: { status: 400, data: zInvalidEmailError },
invalid_or_expired_token: { status: 400, data: zInvalidOrExpiredTokenError },
not_owner: { status: 400, data: zNotOwnerError },
owner_transfer_limit: { status: 429, data: zOwnerTransferLimitError },
}
export const post14Errors = {
email_send_ip_limit: { status: 429, data: zEmailSendIpLimitError },
not_owner: { status: 400, data: zNotOwnerError },
owner_transfer_rate_limit_exceeded: { status: 429, data: zOwnerTransferRateLimitExceededError },
}
export const post15Errors = {
cannot_transfer_owner_to_self: { status: 400, data: zCannotTransferOwnerToSelfError },
invalid_email: { status: 400, data: zInvalidEmailError },
invalid_or_expired_token: { status: 400, data: zInvalidOrExpiredTokenError },
member_not_in_tenant: { status: 400, data: zMemberNotInTenantError },
not_owner: { status: 400, data: zNotOwnerError },
}
export const put2Errors = {
cannot_operate_self: { status: 400, data: zCannotOperateSelfError },
forbidden: { status: 403, data: zForbiddenError },
invalid_role: { status: 400, data: zInvalidRoleError },
member_not_found: { status: 404, data: zMemberNotFoundError },
role_already_assigned: { status: 400, data: zRoleAlreadyAssignedError },
}
export const delete4Errors = {
cannot_operate_self: { status: 400, data: zCannotOperateSelfError },
forbidden: { status: 403, data: zForbiddenError },
member_not_found: { status: 404, data: zMemberNotFoundError },
}
export const get27Errors = { plugin_error: { status: 400, data: zPluginError } }
export const get29Errors = { plugin_error: { status: 400, data: zPluginError } }
export const get30Errors = { plugin_error: { status: 400, data: zPluginError } }
export const get31Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post29Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post30Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post31Errors = { plugin_error: { status: 400, data: zPluginError } }
export const get32Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post32Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post33Errors = { plugin_error: { status: 400, data: zPluginError } }
export const get33Errors = { plugin_error: { status: 400, data: zPluginError } }
export const get34Errors = { plugin_error: { status: 400, data: zPluginError } }
export const get35Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post34Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post36Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post37Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post38Errors = { plugin_error: { status: 400, data: zPluginError } }
export const get38Errors = { plugin_error: { status: 400, data: zPluginError } }
export const get39Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post39Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post40Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post41Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post43Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post44Errors = { plugin_error: { status: 400, data: zPluginError } }
export const get40Errors = { plugin_error: { status: 400, data: zPluginError } }
export const post49Errors = {
filename_missing: { status: 400, data: zFilenameMissingError },
no_file_uploaded: { status: 400, data: zNoFileUploadedError },
}
export const post50Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const post51Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const post53Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const get81Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const get82Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const patch5Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const put20Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const post54Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const post55Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const patch6Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const delete16Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const patch7Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const post56Errors = { invalid_request: { status: 400, data: zInvalidRequestError } }
export const get88Errors = {
current_workspace_archived: { status: 409, data: zCurrentWorkspaceArchivedError },
}
export const post80Errors = {
file_too_large: { status: 413, data: zFileTooLargeError },
filename_not_exists_error: { status: 400, data: zFilenameNotExistsError },
no_file_uploaded: { status: 400, data: zNoFileUploadedError },
too_many_files: { status: 400, data: zTooManyFilesError },
unsupported_file_type: { status: 415, data: zUnsupportedFileTypeError },
}
export const post83Errors = {
account_not_link_tenant: { status: 403, data: zAccountNotLinkTenantError },
}
@@ -215,16 +215,19 @@ import {
zGetWorkspacesCurrentRbacWorkspaceAgentsAccessPoliciesByPolicyIdMemberBindingsResponse,
zGetWorkspacesCurrentRbacWorkspaceAgentsAccessPoliciesByPolicyIdRoleBindingsPath,
zGetWorkspacesCurrentRbacWorkspaceAgentsAccessPoliciesByPolicyIdRoleBindingsResponse,
zGetWorkspacesCurrentRbacWorkspaceAgentsAccessPolicyQuery,
zGetWorkspacesCurrentRbacWorkspaceAgentsAccessPolicyResponse,
zGetWorkspacesCurrentRbacWorkspaceAppsAccessPoliciesByPolicyIdMemberBindingsPath,
zGetWorkspacesCurrentRbacWorkspaceAppsAccessPoliciesByPolicyIdMemberBindingsResponse,
zGetWorkspacesCurrentRbacWorkspaceAppsAccessPoliciesByPolicyIdRoleBindingsPath,
zGetWorkspacesCurrentRbacWorkspaceAppsAccessPoliciesByPolicyIdRoleBindingsResponse,
zGetWorkspacesCurrentRbacWorkspaceAppsAccessPolicyQuery,
zGetWorkspacesCurrentRbacWorkspaceAppsAccessPolicyResponse,
zGetWorkspacesCurrentRbacWorkspaceDatasetsAccessPoliciesByPolicyIdMemberBindingsPath,
zGetWorkspacesCurrentRbacWorkspaceDatasetsAccessPoliciesByPolicyIdMemberBindingsResponse,
zGetWorkspacesCurrentRbacWorkspaceDatasetsAccessPoliciesByPolicyIdRoleBindingsPath,
zGetWorkspacesCurrentRbacWorkspaceDatasetsAccessPoliciesByPolicyIdRoleBindingsResponse,
zGetWorkspacesCurrentRbacWorkspaceDatasetsAccessPolicyQuery,
zGetWorkspacesCurrentRbacWorkspaceDatasetsAccessPolicyResponse,
zGetWorkspacesCurrentSkillsBySkillIdExportPath,
zGetWorkspacesCurrentSkillsBySkillIdExportResponse,
@@ -448,6 +451,7 @@ import {
zPostWorkspacesCurrentSkillsBySkillIdRestoreResponse,
zPostWorkspacesCurrentSkillsFilesUploadBody,
zPostWorkspacesCurrentSkillsFilesUploadResponse,
zPostWorkspacesCurrentSkillsImportBody,
zPostWorkspacesCurrentSkillsImportResponse,
zPostWorkspacesCurrentSkillsResponse,
zPostWorkspacesCurrentToolProviderApiAddBody,
@@ -3557,6 +3561,11 @@ export const get72 = oc
path: '/workspaces/current/rbac/workspace/agents/access-policy',
tags: ['console'],
})
.input(
z
.object({ query: zGetWorkspacesCurrentRbacWorkspaceAgentsAccessPolicyQuery.optional() })
.optional(),
)
.output(zGetWorkspacesCurrentRbacWorkspaceAgentsAccessPolicyResponse)
export const accessPolicy4 = {
@@ -3644,6 +3653,11 @@ export const get75 = oc
path: '/workspaces/current/rbac/workspace/apps/access-policy',
tags: ['console'],
})
.input(
z
.object({ query: zGetWorkspacesCurrentRbacWorkspaceAppsAccessPolicyQuery.optional() })
.optional(),
)
.output(zGetWorkspacesCurrentRbacWorkspaceAppsAccessPolicyResponse)
export const accessPolicy5 = {
@@ -3731,6 +3745,11 @@ export const get78 = oc
path: '/workspaces/current/rbac/workspace/datasets/access-policy',
tags: ['console'],
})
.input(
z
.object({ query: zGetWorkspacesCurrentRbacWorkspaceDatasetsAccessPolicyQuery.optional() })
.optional(),
)
.output(zGetWorkspacesCurrentRbacWorkspaceDatasetsAccessPolicyResponse)
export const accessPolicy6 = {
@@ -3798,6 +3817,7 @@ export const post50 = oc
successStatus: 201,
tags: ['console'],
})
.input(z.object({ body: zPostWorkspacesCurrentSkillsImportBody }))
.output(zPostWorkspacesCurrentSkillsImportResponse)
.errors({ invalid_request: { status: 400, data: zInvalidRequestError } })
@@ -495,8 +495,6 @@ export type WorkspacePermissionResponse = {
workspace_id: string
}
export type BinaryFileResponse = Blob | File
export type PluginError = ErrorResponse & {
code: 'plugin_error'
status: 400
@@ -4760,7 +4758,7 @@ export type GetWorkspacesCurrentPluginAssetError =
GetWorkspacesCurrentPluginAssetErrors[keyof GetWorkspacesCurrentPluginAssetErrors]
export type GetWorkspacesCurrentPluginAssetResponses = {
200: BinaryFileResponse
200: Blob | File
}
export type GetWorkspacesCurrentPluginAssetResponse =
@@ -4896,7 +4894,7 @@ export type GetWorkspacesCurrentPluginIconError =
GetWorkspacesCurrentPluginIconErrors[keyof GetWorkspacesCurrentPluginIconErrors]
export type GetWorkspacesCurrentPluginIconResponses = {
200: BinaryFileResponse
200: Blob | File
}
export type GetWorkspacesCurrentPluginIconResponse =
@@ -6735,7 +6733,12 @@ export type GetWorkspacesCurrentRbacWorkspaceAgentsAccessPoliciesByPolicyIdRoleB
export type GetWorkspacesCurrentRbacWorkspaceAgentsAccessPolicyData = {
body?: never
path?: never
query?: never
query?: {
language?: 'en' | 'ja' | 'zh'
limit?: number
page?: number
reverse?: boolean
}
url: '/workspaces/current/rbac/workspace/agents/access-policy'
}
@@ -6825,7 +6828,12 @@ export type GetWorkspacesCurrentRbacWorkspaceAppsAccessPoliciesByPolicyIdRoleBin
export type GetWorkspacesCurrentRbacWorkspaceAppsAccessPolicyData = {
body?: never
path?: never
query?: never
query?: {
language?: 'en' | 'ja' | 'zh'
limit?: number
page?: number
reverse?: boolean
}
url: '/workspaces/current/rbac/workspace/apps/access-policy'
}
@@ -6918,7 +6926,12 @@ export type GetWorkspacesCurrentRbacWorkspaceDatasetsAccessPoliciesByPolicyIdRol
export type GetWorkspacesCurrentRbacWorkspaceDatasetsAccessPolicyData = {
body?: never
path?: never
query?: never
query?: {
language?: 'en' | 'ja' | 'zh'
limit?: number
page?: number
reverse?: boolean
}
url: '/workspaces/current/rbac/workspace/datasets/access-policy'
}
@@ -7009,7 +7022,9 @@ export type PostWorkspacesCurrentSkillsFilesUploadResponse =
PostWorkspacesCurrentSkillsFilesUploadResponses[keyof PostWorkspacesCurrentSkillsFilesUploadResponses]
export type PostWorkspacesCurrentSkillsImportData = {
body?: never
body: {
file: Blob | File
}
path?: never
query?: never
url: '/workspaces/current/skills/import'
@@ -7290,7 +7305,7 @@ export type GetWorkspacesCurrentSkillsBySkillIdFilesContentError =
GetWorkspacesCurrentSkillsBySkillIdFilesContentErrors[keyof GetWorkspacesCurrentSkillsBySkillIdFilesContentErrors]
export type GetWorkspacesCurrentSkillsBySkillIdFilesContentResponses = {
200: BinaryFileResponse
200: Blob | File
}
export type GetWorkspacesCurrentSkillsBySkillIdFilesContentResponse =
+34 -10
View File
@@ -503,13 +503,6 @@ export const zWorkspacePermissionResponse = z.object({
workspace_id: z.string(),
})
/**
* BinaryFileResponse
*/
export const zBinaryFileResponse = z.custom<Blob | File>(
(value) => value instanceof Blob || value instanceof File,
)
/**
* PluginError
*
@@ -5220,7 +5213,9 @@ export const zGetWorkspacesCurrentPluginAssetQuery = z.object({
/**
* Success
*/
export const zGetWorkspacesCurrentPluginAssetResponse = zBinaryFileResponse
export const zGetWorkspacesCurrentPluginAssetResponse = z.custom<Blob | File>(
(value) => value instanceof Blob || value instanceof File,
)
export const zPostWorkspacesCurrentPluginAutoUpgradeChangeBody = zParserAutoUpgradeChange
@@ -5268,7 +5263,9 @@ export const zGetWorkspacesCurrentPluginIconQuery = z.object({
/**
* Success
*/
export const zGetWorkspacesCurrentPluginIconResponse = zBinaryFileResponse
export const zGetWorkspacesCurrentPluginIconResponse = z.custom<Blob | File>(
(value) => value instanceof Blob || value instanceof File,
)
export const zPostWorkspacesCurrentPluginInstallGithubBody = zParserGithubInstall
@@ -6073,6 +6070,13 @@ export const zGetWorkspacesCurrentRbacWorkspaceAgentsAccessPoliciesByPolicyIdRol
export const zGetWorkspacesCurrentRbacWorkspaceAgentsAccessPoliciesByPolicyIdRoleBindingsResponse =
zRoleBindingsResponse
export const zGetWorkspacesCurrentRbacWorkspaceAgentsAccessPolicyQuery = z.object({
language: z.enum(['en', 'ja', 'zh']).optional(),
limit: z.int().gte(1).lte(99999).optional(),
page: z.int().gte(1).optional(),
reverse: z.boolean().optional(),
})
/**
* Success
*/
@@ -6113,6 +6117,13 @@ export const zGetWorkspacesCurrentRbacWorkspaceAppsAccessPoliciesByPolicyIdRoleB
export const zGetWorkspacesCurrentRbacWorkspaceAppsAccessPoliciesByPolicyIdRoleBindingsResponse =
zRoleBindingsResponse
export const zGetWorkspacesCurrentRbacWorkspaceAppsAccessPolicyQuery = z.object({
language: z.enum(['en', 'ja', 'zh']).optional(),
limit: z.int().gte(1).lte(99999).optional(),
page: z.int().gte(1).optional(),
reverse: z.boolean().optional(),
})
/**
* Success
*/
@@ -6154,6 +6165,13 @@ export const zGetWorkspacesCurrentRbacWorkspaceDatasetsAccessPoliciesByPolicyIdR
export const zGetWorkspacesCurrentRbacWorkspaceDatasetsAccessPoliciesByPolicyIdRoleBindingsResponse =
zRoleBindingsResponse
export const zGetWorkspacesCurrentRbacWorkspaceDatasetsAccessPolicyQuery = z.object({
language: z.enum(['en', 'ja', 'zh']).optional(),
limit: z.int().gte(1).lte(99999).optional(),
page: z.int().gte(1).optional(),
reverse: z.boolean().optional(),
})
/**
* Success
*/
@@ -6187,6 +6205,10 @@ export const zPostWorkspacesCurrentSkillsFilesUploadBody = z.object({
*/
export const zPostWorkspacesCurrentSkillsFilesUploadResponse = zSkillFileUploadResponse
export const zPostWorkspacesCurrentSkillsImportBody = z.object({
file: z.custom<Blob | File>((value) => value instanceof Blob || value instanceof File),
})
/**
* Skill imported
*/
@@ -6306,7 +6328,9 @@ export const zGetWorkspacesCurrentSkillsBySkillIdFilesContentQuery = z.object({
/**
* Skill file content
*/
export const zGetWorkspacesCurrentSkillsBySkillIdFilesContentResponse = zBinaryFileResponse
export const zGetWorkspacesCurrentSkillsBySkillIdFilesContentResponse = z.custom<Blob | File>(
(value) => value instanceof Blob || value instanceof File,
)
export const zGetWorkspacesCurrentSkillsBySkillIdFilesPreviewPath = z.object({
skill_id: z.string(),
File diff suppressed because it is too large. Load diff
+601
View File
@@ -0,0 +1,601 @@
// This file is auto-generated by scripts/add-orpc-error-maps.ts
import * as z from 'zod'
const zErrorResponse = /* @__PURE__ */ (() =>
z.object({
code: z.string(),
details: z.record(z.string(), z.unknown()).optional(),
message: z.string(),
params: z.string().optional(),
status: z.int(),
}))()
const zAccountBannedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('account_banned'),
status: z.literal(400),
}),
))()
const zAgentNotPublishedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('agent_not_published'),
status: z.literal(400),
}),
))()
const zAppMoreLikeThisDisabledError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_more_like_this_disabled'),
status: z.literal(403),
}),
))()
const zAppSuggestedQuestionsAfterAnswerDisabledError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_suggested_questions_after_answer_disabled'),
status: z.literal(403),
}),
))()
const zAppUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('app_unavailable'),
status: z.literal(400),
}),
))()
const zAudioTooLargeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('audio_too_large'),
status: z.literal(413),
}),
))()
const zAuthenticationFailedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('authentication_failed'),
status: z.literal(401),
}),
))()
const zCompletionRequestError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('completion_request_error'),
status: z.literal(400),
}),
))()
const zEmailCodeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_code_error'),
status: z.literal(400),
}),
))()
const zEmailPasswordResetLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_password_reset_limit'),
status: z.literal(429),
}),
))()
const zEmailSendIpLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('email_send_ip_limit'),
status: z.literal(429),
}),
))()
const zFileExtensionBlockedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('file_extension_blocked'),
status: z.literal(400),
}),
))()
const zFileTooLargeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('file_too_large'),
status: z.literal(413),
}),
))()
const zFilenameNotExistsError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('filename_not_exists_error'),
status: z.literal(400),
}),
))()
const zHumanInputFormExpiredError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('human_input_form_expired'),
status: z.literal(412),
}),
))()
const zHumanInputFormSubmittedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('human_input_form_submitted'),
status: z.literal(412),
}),
))()
const zInvalidEmailError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_email'),
status: z.literal(400),
}),
))()
const zInvalidFormDataError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_form_data'),
status: z.literal(400),
}),
))()
const zInvalidOrExpiredTokenError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_or_expired_token'),
status: z.literal(400),
}),
))()
const zInvalidParamError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_param'),
status: z.literal(400),
}),
))()
const zInvalidUploadTokenError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('invalid_upload_token'),
status: z.literal(403),
}),
))()
const zMalformedUploadTokenError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('malformed_upload_token'),
status: z.literal(400),
}),
))()
const zModelCurrentlyNotSupportError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('model_currently_not_support'),
status: z.literal(400),
}),
))()
const zNoAudioUploadedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('no_audio_uploaded'),
status: z.literal(400),
}),
))()
const zNoFileUploadedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('no_file_uploaded'),
status: z.literal(400),
}),
))()
const zNotChatAppError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('not_chat_app'),
status: z.literal(400),
}),
))()
const zNotCompletionAppError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('not_completion_app'),
status: z.literal(400),
}),
))()
const zNotWorkflowAppError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('not_workflow_app'),
status: z.literal(400),
}),
))()
const zPasswordMismatchError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('password_mismatch'),
status: z.literal(400),
}),
))()
const zPasswordResetRateLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('password_reset_rate_limit_exceeded'),
status: z.literal(429),
}),
))()
const zProviderNotInitializeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_initialize'),
status: z.literal(400),
}),
))()
const zProviderNotSupportSpeechToTextError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_not_support_speech_to_text'),
status: z.literal(400),
}),
))()
const zProviderQuotaExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('provider_quota_exceeded'),
status: z.literal(400),
}),
))()
const zRateLimitError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('rate_limit_error'),
status: z.literal(429),
}),
))()
const zRemoteFileAccessDeniedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_access_denied'),
status: z.literal(400),
}),
))()
const zRemoteFileInvalidResponseError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_invalid_response'),
status: z.literal(502),
}),
))()
const zRemoteFileInvalidUrlError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_invalid_url'),
status: z.literal(400),
}),
))()
const zRemoteFileNotFoundError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_not_found'),
status: z.literal(404),
}),
))()
const zRemoteFileUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_unavailable'),
status: z.literal(502),
}),
))()
const zRemoteFileUrlBlockedError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('remote_file_url_blocked'),
status: z.literal(400),
}),
))()
const zSpeechToTextDisabledError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('speech_to_text_disabled'),
status: z.literal(400),
}),
))()
const zTooManyFilesError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('too_many_files'),
status: z.literal(400),
}),
))()
const zTriggerWorkflowServiceModeUnavailableError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('trigger_workflow_service_mode_unavailable'),
status: z.literal(403),
}),
))()
const zUnsupportedAudioTypeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('unsupported_audio_type'),
status: z.literal(415),
}),
))()
const zUnsupportedFileTypeError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('unsupported_file_type'),
status: z.literal(415),
}),
))()
const zUploadTokenRequiredError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('upload_token_required'),
status: z.literal(401),
}),
))()
const zWebFormRateLimitExceededError = /* @__PURE__ */ (() =>
zErrorResponse.and(
z.object({
code: z.literal('web_form_rate_limit_exceeded'),
status: z.literal(429),
}),
))()
export const postErrors = {
app_unavailable: { status: 400, data: zAppUnavailableError },
audio_too_large: { status: 413, data: zAudioTooLargeError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
no_audio_uploaded: { status: 400, data: zNoAudioUploadedError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_not_support_speech_to_text: { status: 400, data: zProviderNotSupportSpeechToTextError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
speech_to_text_disabled: { status: 400, data: zSpeechToTextDisabledError },
unsupported_audio_type: { status: 415, data: zUnsupportedAudioTypeError },
}
export const post2Errors = { not_chat_app: { status: 400, data: zNotChatAppError } }
export const post3Errors = {
agent_not_published: { status: 400, data: zAgentNotPublishedError },
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_chat_app: { status: 400, data: zNotChatAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
rate_limit_error: { status: 429, data: zRateLimitError },
}
export const post4Errors = { not_completion_app: { status: 400, data: zNotCompletionAppError } }
export const post5Errors = {
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_completion_app: { status: 400, data: zNotCompletionAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
export const post6Errors = { not_chat_app: { status: 400, data: zNotChatAppError } }
export const patchErrors = { not_chat_app: { status: 400, data: zNotChatAppError } }
export const patch2Errors = { not_chat_app: { status: 400, data: zNotChatAppError } }
export const delete_Errors = { not_chat_app: { status: 400, data: zNotChatAppError } }
export const getErrors = { not_chat_app: { status: 400, data: zNotChatAppError } }
export const post7Errors = {
account_banned: { status: 400, data: zAccountBannedError },
authentication_failed: { status: 401, data: zAuthenticationFailedError },
email_code_error: { status: 400, data: zEmailCodeError },
invalid_email: { status: 400, data: zInvalidEmailError },
}
export const post8Errors = {
authentication_failed: { status: 401, data: zAuthenticationFailedError },
}
export const post9Errors = {
file_extension_blocked: { status: 400, data: zFileExtensionBlockedError },
file_too_large: { status: 413, data: zFileTooLargeError },
filename_not_exists_error: { status: 400, data: zFilenameNotExistsError },
no_file_uploaded: { status: 400, data: zNoFileUploadedError },
too_many_files: { status: 400, data: zTooManyFilesError },
unsupported_file_type: { status: 415, data: zUnsupportedFileTypeError },
}
export const post10Errors = {
authentication_failed: { status: 401, data: zAuthenticationFailedError },
invalid_or_expired_token: { status: 400, data: zInvalidOrExpiredTokenError },
password_mismatch: { status: 400, data: zPasswordMismatchError },
}
export const post11Errors = {
email_code_error: { status: 400, data: zEmailCodeError },
email_password_reset_limit: { status: 429, data: zEmailPasswordResetLimitError },
invalid_email: { status: 400, data: zInvalidEmailError },
invalid_or_expired_token: { status: 400, data: zInvalidOrExpiredTokenError },
}
export const post12Errors = {
authentication_failed: { status: 401, data: zAuthenticationFailedError },
email_send_ip_limit: { status: 429, data: zEmailSendIpLimitError },
password_reset_rate_limit_exceeded: { status: 429, data: zPasswordResetRateLimitExceededError },
}
export const post13Errors = {
human_input_form_expired: { status: 412, data: zHumanInputFormExpiredError },
human_input_form_submitted: { status: 412, data: zHumanInputFormSubmittedError },
web_form_rate_limit_exceeded: { status: 429, data: zWebFormRateLimitExceededError },
}
export const get2Errors = {
human_input_form_expired: { status: 412, data: zHumanInputFormExpiredError },
human_input_form_submitted: { status: 412, data: zHumanInputFormSubmittedError },
web_form_rate_limit_exceeded: { status: 429, data: zWebFormRateLimitExceededError },
}
export const post14Errors = {
human_input_form_expired: { status: 412, data: zHumanInputFormExpiredError },
human_input_form_submitted: { status: 412, data: zHumanInputFormSubmittedError },
invalid_form_data: { status: 400, data: zInvalidFormDataError },
web_form_rate_limit_exceeded: { status: 429, data: zWebFormRateLimitExceededError },
}
export const post15Errors = {
file_extension_blocked: { status: 400, data: zFileExtensionBlockedError },
file_too_large: { status: 413, data: zFileTooLargeError },
filename_not_exists_error: { status: 400, data: zFilenameNotExistsError },
human_input_form_expired: { status: 412, data: zHumanInputFormExpiredError },
human_input_form_submitted: { status: 412, data: zHumanInputFormSubmittedError },
invalid_upload_token: { status: 403, data: zInvalidUploadTokenError },
malformed_upload_token: { status: 400, data: zMalformedUploadTokenError },
no_file_uploaded: { status: 400, data: zNoFileUploadedError },
remote_file_access_denied: { status: 400, data: zRemoteFileAccessDeniedError },
remote_file_invalid_response: { status: 502, data: zRemoteFileInvalidResponseError },
remote_file_invalid_url: { status: 400, data: zRemoteFileInvalidUrlError },
remote_file_not_found: { status: 404, data: zRemoteFileNotFoundError },
remote_file_unavailable: { status: 502, data: zRemoteFileUnavailableError },
remote_file_url_blocked: { status: 400, data: zRemoteFileUrlBlockedError },
too_many_files: { status: 400, data: zTooManyFilesError },
unsupported_file_type: { status: 415, data: zUnsupportedFileTypeError },
upload_token_required: { status: 401, data: zUploadTokenRequiredError },
}
export const post16Errors = {
account_banned: { status: 400, data: zAccountBannedError },
authentication_failed: { status: 401, data: zAuthenticationFailedError },
}
export const get4Errors = {
app_more_like_this_disabled: { status: 403, data: zAppMoreLikeThisDisabledError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_completion_app: { status: 400, data: zNotCompletionAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
export const get5Errors = {
app_suggested_questions_after_answer_disabled: {
status: 403,
data: zAppSuggestedQuestionsAfterAnswerDisabledError,
},
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_chat_app: { status: 400, data: zNotChatAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
export const get6Errors = { not_chat_app: { status: 400, data: zNotChatAppError } }
export const get7Errors = { app_unavailable: { status: 400, data: zAppUnavailableError } }
export const get8Errors = {
agent_not_published: { status: 400, data: zAgentNotPublishedError },
app_unavailable: { status: 400, data: zAppUnavailableError },
}
export const post19Errors = {
file_extension_blocked: { status: 400, data: zFileExtensionBlockedError },
file_too_large: { status: 413, data: zFileTooLargeError },
remote_file_access_denied: { status: 400, data: zRemoteFileAccessDeniedError },
remote_file_invalid_response: { status: 502, data: zRemoteFileInvalidResponseError },
remote_file_invalid_url: { status: 400, data: zRemoteFileInvalidUrlError },
remote_file_not_found: { status: 404, data: zRemoteFileNotFoundError },
remote_file_unavailable: { status: 502, data: zRemoteFileUnavailableError },
remote_file_url_blocked: { status: 400, data: zRemoteFileUrlBlockedError },
unsupported_file_type: { status: 415, data: zUnsupportedFileTypeError },
}
export const get10Errors = {
remote_file_access_denied: { status: 400, data: zRemoteFileAccessDeniedError },
remote_file_invalid_response: { status: 502, data: zRemoteFileInvalidResponseError },
remote_file_invalid_url: { status: 400, data: zRemoteFileInvalidUrlError },
remote_file_not_found: { status: 404, data: zRemoteFileNotFoundError },
remote_file_unavailable: { status: 502, data: zRemoteFileUnavailableError },
remote_file_url_blocked: { status: 400, data: zRemoteFileUrlBlockedError },
}
export const delete2Errors = { not_completion_app: { status: 400, data: zNotCompletionAppError } }
export const get11Errors = { not_completion_app: { status: 400, data: zNotCompletionAppError } }
export const post20Errors = { not_completion_app: { status: 400, data: zNotCompletionAppError } }
export const post21Errors = {
app_unavailable: { status: 400, data: zAppUnavailableError },
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
}
export const get14Errors = { invalid_param: { status: 400, data: zInvalidParamError } }
export const get16Errors = { invalid_param: { status: 400, data: zInvalidParamError } }
export const post22Errors = {
completion_request_error: { status: 400, data: zCompletionRequestError },
model_currently_not_support: { status: 400, data: zModelCurrentlyNotSupportError },
not_workflow_app: { status: 400, data: zNotWorkflowAppError },
provider_not_initialize: { status: 400, data: zProviderNotInitializeError },
provider_quota_exceeded: { status: 400, data: zProviderQuotaExceededError },
rate_limit_error: { status: 429, data: zRateLimitError },
trigger_workflow_service_mode_unavailable: {
status: 403,
data: zTriggerWorkflowServiceModeUnavailableError,
},
}
export const post23Errors = { not_workflow_app: { status: 400, data: zNotWorkflowAppError } }
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
@@ -2,23 +2,23 @@
Scope: endpoints emitted by `api/dev/generate_swagger_specs.py` into the generated `console`, `openapi`, `service`, and `web` specs.
The current Flask-RESTX generator still emits these response entries under `application/json`. The schema model names below record the actual runtime response intent so contract generation does not treat them as missing annotations.
This inventory records non-JSON runtime responses and their schema intent. Legacy declarations may still use JSON placeholders. Explicit binary declarations emit `string` with `format: binary` under the advertised media types while preserving JSON error responses.
## Binary And Audio
| Spec | Method | Path | Runtime response | Schema |
| ------- | ------ | ----------------------------------------------------------------------- | ---------------------------------------------- | --------------------- |
| console | POST | `/apps/{app_id}/text-to-audio` | Audio stream, usually `audio/mpeg` | `AudioBinaryResponse` |
| console | POST | `/installed-apps/{installed_app_id}/text-to-audio` | Audio stream, usually `audio/mpeg` | `AudioBinaryResponse` |
| console | POST | `/trial-apps/{app_id}/text-to-audio` | Audio stream, usually `audio/mpeg` | `AudioBinaryResponse` |
| console | POST | `/installed-apps/{installed_app_id}/text-to-audio` | Supported provider audio media types | `string (binary)` |
| console | POST | `/trial-apps/{app_id}/text-to-audio` | Supported provider audio media types | `string (binary)` |
| web | POST | `/text-to-audio` | Audio stream, usually `audio/mpeg` | `AudioBinaryResponse` |
| service | POST | `/text-to-audio` | Audio stream, usually `audio/mpeg` | `AudioBinaryResponse` |
| console | POST | `/datasets/{dataset_id}/documents/download-zip` | `application/zip` attachment | `BinaryFileResponse` |
| service | POST | `/datasets/{dataset_id}/documents/download-zip` | `application/zip` attachment | `BinaryFileResponse` |
| service | GET | `/files/{file_id}/preview` | Original file MIME type, optionally attachment | `BinaryFileResponse` |
| console | GET | `/workspaces/current/plugin/icon` | Plugin asset MIME type | `BinaryFileResponse` |
| console | GET | `/workspaces/current/plugin/asset` | `application/octet-stream` | `BinaryFileResponse` |
| console | GET | `/workspaces/current/skills/{skill_id}/files/content` | Skill file MIME type, optionally attachment | `BinaryFileResponse` |
| console | GET | `/workspaces/current/plugin/icon` | Plugin asset MIME type | `string (binary)` |
| console | GET | `/workspaces/current/plugin/asset` | `application/octet-stream` | `string (binary)` |
| console | GET | `/workspaces/current/skills/{skill_id}/files/content` | Skill file MIME type, optionally attachment | `string (binary)` |
| console | GET | `/workspaces/current/tool-provider/builtin/{provider}/icon` | Tool icon MIME type | `BinaryFileResponse` |
| console | GET | `/workspaces/current/trigger-provider/{provider}/icon` | Trigger icon response | `BinaryFileResponse` |
| console | GET | `/workspaces/{tenant_id}/model-providers/{provider}/{icon_type}/{lang}` | Model provider icon MIME type | `BinaryFileResponse` |
@@ -289,8 +289,10 @@ const normalizeEnterpriseOpenApi = () => {
return document
}
export const enterpriseDocument = normalizeEnterpriseOpenApi()
export default defineConfig({
input: normalizeEnterpriseOpenApi(),
input: enterpriseDocument,
output: {
module: { extension: '.ts' },
entryFile: false,
@@ -288,8 +288,10 @@ const normalizeEnterpriseOpenApi = () => {
return document
}
export const enterpriseDocument = normalizeEnterpriseOpenApi()
export default defineConfig({
input: normalizeEnterpriseOpenApi(),
input: enterpriseDocument,
output: {
module: { extension: '.ts' },
entryFile: false,
+4 -3
View File
@@ -27,10 +27,11 @@
},
"scripts": {
"gen-api-contract": "uv run --project ../../api ../../api/dev/generate_swagger_specs.py --output-dir openapi && uv run --project ../../api ../../api/dev/generate_fastopenapi_specs.py --output-dir openapi && node -e \"if (process.env.CI) fs.rmSync('generated/api', { recursive: true, force: true })\" && openapi-ts -f openapi-ts.api.config.ts && node scripts/add-orpc-error-maps.ts && vp fmt generated/api",
"gen-enterprise-contract": "openapi-ts -f openapi-ts.enterprise.config.ts",
"gen-enterprise-app-deploy-contract": "openapi-ts -f openapi-ts.enterprise-app-deploy.config.ts",
"gen-enterprise-contract": "openapi-ts -f openapi-ts.enterprise.config.ts && node scripts/snapshot-enterprise-openapi.ts enterprise",
"gen-enterprise-app-deploy-contract": "openapi-ts -f openapi-ts.enterprise-app-deploy.config.ts && node scripts/snapshot-enterprise-openapi.ts enterprise-app-deploy",
"test": "vp test",
"type-check": "tsrs --noEmit"
"type-check": "tsrs --noEmit",
"compose:console": "node scripts/compose-console-openapi.mjs"
},
"dependencies": {
"@orpc/contract": "catalog:",
@@ -118,9 +118,107 @@ const patchContractFile = (directory: string, errorMaps: Map<string, OrpcErrorEn
return insertions.length
}
/** Copy only error-schema dependencies, with pure construction so unused maps can disappear. */
function errorSchemas(source: string, names: Set<string>, fileName: string) {
const file = ts.createSourceFile(fileName, source, ts.ScriptTarget.Latest, true)
const declarations = new Map<string, ts.VariableDeclaration>()
for (const statement of file.statements) {
if (ts.isVariableStatement(statement)) {
for (const declaration of statement.declarationList.declarations)
if (ts.isIdentifier(declaration.name)) declarations.set(declaration.name.text, declaration)
}
}
const needed = new Set<string>()
function select(name: string) {
if (needed.has(name)) return
const declaration = declarations.get(name)
if (!declaration?.initializer) throw new Error(`Missing error schema ${name} in ${fileName}`)
needed.add(name)
function visit(node: ts.Node) {
if (ts.isIdentifier(node) && declarations.has(node.text)) select(node.text)
ts.forEachChild(node, visit)
}
visit(declaration.initializer)
}
for (const name of names) select(name)
return [...declarations]
.filter(([name]) => needed.has(name))
.map(
([name, declaration]) =>
`const ${name}${declaration.type ? `: ${declaration.type.getText(file)}` : ''} = /* @__PURE__ */ (() => ${declaration.initializer!.getText(file)})();`,
)
.join('\n\n')
}
// Separate named maps let OpenAPI clients retain only an operation's error validators.
const consoleErrors: string[] = []
function writeErrorMaps(job: (typeof apiJobs)[number], errorMaps: Map<string, OrpcErrorEntry[]>) {
const directory = path.join(contractsDir, job.outputPath)
const orpcPath = path.join(directory, 'orpc.gen.ts')
const zodPath = path.join(directory, 'zod.gen.ts')
if (!fs.existsSync(orpcPath) || !fs.existsSync(zodPath)) return
const file = ts.createSourceFile(
orpcPath,
fs.readFileSync(orpcPath, 'utf8'),
ts.ScriptTarget.Latest,
true,
)
const resolveZodName = zodNameResolver(exportedNames(fs.readFileSync(zodPath, 'utf8')), zodPath)
const used = new Set<string>()
const declarations: string[] = []
const routes = new Map<string, string>()
for (const [route, item] of Object.entries(job.document.paths ?? {})) {
for (const [method, operation] of Object.entries(item)) {
if (
operation &&
typeof operation === 'object' &&
'operationId' in operation &&
typeof operation.operationId === 'string'
)
routes.set(operation.operationId, `${method.toUpperCase()} ${route}`)
}
}
for (const statement of file.statements) {
if (!ts.isVariableStatement(statement)) continue
for (const declaration of statement.declarationList.declarations) {
if (!declaration.initializer || !ts.isIdentifier(declaration.name)) continue
const id = routeOperationId(declaration.initializer)
const entries = id ? errorMaps.get(id) : undefined
if (!id || !entries) continue
const name = `${declaration.name.text}Errors`
const expression = renderErrors(entries, resolveZodName, used).slice('.errors('.length, -1)
declarations.push(`export const ${name} = ${expression}\n`)
const relative = path
.relative(path.join(contractsDir, 'generated/api/console'), directory)
.replaceAll('\\', '/')
if (!relative.startsWith('..')) {
const route = routes.get(id)
if (!route) throw new Error(`Missing route for ${id}`)
consoleErrors.push(
`export { ${name} as ${JSON.stringify(route)} } from './${relative}/errors.gen.ts'`,
)
}
}
}
if (declarations.length)
fs.writeFileSync(
path.join(directory, 'errors.gen.ts'),
`// This file is auto-generated by scripts/add-orpc-error-maps.ts\nimport * as z from 'zod'\n\n${errorSchemas(fs.readFileSync(zodPath, 'utf8'), used, zodPath)}\n\n${declarations.join('\n')}`,
)
}
let patched = 0
for (const job of apiJobs) {
if (job.plugins) continue // the console entry job writes loaders, not contracts
patched += patchContractFile(path.join(contractsDir, job.outputPath), orpcErrorMaps(job.document))
const errors = orpcErrorMaps(job.document)
if (!process.argv.includes('--errors-only'))
patched += patchContractFile(path.join(contractsDir, job.outputPath), errors)
writeErrorMaps(job, errors)
}
process.stdout.write(`declared error maps on ${patched} contracts\n`)
fs.writeFileSync(
path.join(contractsDir, 'generated/api/console/errors.gen.ts'),
`// This file is auto-generated by scripts/add-orpc-error-maps.ts\n${consoleErrors.sort().join('\n')}\n`,
)
process.stdout.write(
`declared error maps on ${patched} contracts; exported ${consoleErrors.length} console maps\n`,
)
@@ -0,0 +1,88 @@
import { execFileSync } from 'node:child_process'
import { readFileSync } from 'node:fs'
import { resolve } from 'node:path'
const methods = new Set(['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'])
/** Namespace local components so independently versioned specifications cannot overwrite each other. */
export function composeConsoleDocuments(sources) {
const result = {
openapi: '3.1.0',
info: { title: 'Dify Console client', version: '1' },
paths: {},
components: {},
}
for (const { name, document, stripPrefix = '' } of sources) {
if (!/^3\.[01]\./.test(document.openapi) || !document.paths)
throw new Error(`Invalid OpenAPI source: ${name}`)
function rewrite(value) {
if (Array.isArray(value)) return value.map(rewrite)
if (!value || typeof value !== 'object') return value
return Object.fromEntries(
Object.entries(value).map(([key, child]) => {
if (key === '$ref') {
if (typeof child !== 'string' || !child.startsWith('#/components/'))
throw new Error(`Unsupported reference in ${name}: ${child}`)
return [key, child.replace(/^(#\/components\/[^/]+\/)/, `$1${name}_`)]
}
return [key, rewrite(child)]
}),
)
}
for (const [group, components] of Object.entries(document.components ?? {})) {
const target = (result.components[group] ??= {})
for (const [key, component] of Object.entries(components)) {
const qualified = `${name}_${key}`
if (Object.hasOwn(target, qualified)) throw new Error(`Duplicate component: ${qualified}`)
target[qualified] = rewrite(component)
}
}
for (const [rawPath, rawItem] of Object.entries(document.paths)) {
const path =
stripPrefix && rawPath.startsWith(`${stripPrefix}/`)
? rawPath.slice(stripPrefix.length)
: rawPath
const item = rewrite(rawItem)
if (Object.hasOwn(result.paths, path)) throw new Error(`Duplicate Console path: ${path}`)
for (const [method, operation] of Object.entries(item)) {
if (!methods.has(method)) continue
// Redirect-only browser navigation endpoints are not oRPC procedures.
if (!Object.keys(operation.responses ?? {}).some((status) => /^2\d\d$/.test(status))) {
delete item[method]
continue
}
operation.operationId = `${name}_${method}_${path}`
// Preserve source-level servers when operations do not override them.
if (!operation.servers && !item.servers && document.servers)
operation.servers = document.servers
}
if (Object.keys(item).some((method) => methods.has(method))) result.paths[path] = item
}
}
return result
}
export function loadConsoleDocument(root = resolve(import.meta.dirname, '..')) {
const community = JSON.parse(
execFileSync('uv', ['run', '--project', 'api', 'api/dev/cached_console_openapi.py'], {
cwd: resolve(root, '../..'),
encoding: 'utf8',
maxBuffer: 64 * 1024 * 1024,
timeout: 100000,
}),
)
const snapshots = [
['enterprise', 'generated/enterprise/openapi.gen.json'],
['appDeploy', 'generated/enterprise-app-deploy/openapi.gen.json'],
].map(([name, path]) => ({
name,
document: JSON.parse(readFileSync(resolve(root, path), 'utf8')),
}))
return composeConsoleDocuments([
{ name: 'console', document: community.console },
{ name: 'fast', document: community.fast, stripPrefix: '/console/api' },
...snapshots,
])
}
if (import.meta.main) process.stdout.write(`${JSON.stringify(loadConsoleDocument())}\n`)
@@ -0,0 +1,70 @@
import { writeFileSync } from 'node:fs'
import { resolve } from 'node:path'
const surface = process.argv[2]
if (!['enterprise', 'enterprise-app-deploy'].includes(surface ?? ''))
throw new Error('Expected enterprise or enterprise-app-deploy')
const { enterpriseDocument } = await import(`../openapi-ts.${surface}.config.ts`)
const { contract } = await import(`../generated/${surface}/orpc.gen.ts`)
const document = structuredClone(enterpriseDocument)
const prefix = surface === 'enterprise' ? ['enterprise'] : ['enterprise', 'appDeploy']
let operations = 0
function visit(node: Record<string, unknown>, members: string[]) {
const definition = node['~orpc'] as { route: { method: string; path: string } } | undefined
if (!definition) {
for (const [key, child] of Object.entries(node))
visit(child as Record<string, unknown>, [...members, key])
return
}
const { method, path } = definition.route
const operation = document.paths?.[path]?.[method.toLowerCase()]
if (!operation)
throw new Error(`The enterprise spec does not match the generated contract: ${method} ${path}`)
operation['x-client-path'] = members
operations++
}
visit(contract, prefix)
const methods = new Set(['get', 'post', 'patch', 'put', 'delete'])
for (const item of Object.values(document.paths ?? {}) as Record<string, unknown>[]) {
for (const [method, operation] of Object.entries(item)) {
if (methods.has(method) && !(operation as Record<string, unknown>)['x-client-path'])
throw new Error(`An enterprise operation has no generated client member: ${method}`)
}
}
if (!operations) throw new Error('The enterprise contract is empty')
// Export only the schemas reachable from the public Console surface, not unrelated enterprise APIs.
const snapshot: Record<string, unknown> = {
openapi: document.openapi,
info: { title: `Dify ${surface} Console`, version: '1' },
paths: document.paths,
components: {},
}
const referenced = new Set<string>()
function includeReferences(value: unknown) {
if (!value || typeof value !== 'object') return
const ref = (value as { $ref?: string }).$ref
if (ref && !referenced.has(ref)) {
if (!ref.startsWith('#/components/')) throw new Error(`Unsupported reference: ${ref}`)
referenced.add(ref)
const keys = ref
.slice(2)
.split('/')
.map((key) => key.replaceAll('~1', '/').replaceAll('~0', '~'))
let source = document
let target = snapshot
for (const key of keys.slice(0, -1)) {
source = source[key]
target = (target[key] ??= {}) as Record<string, unknown>
}
const key = keys.at(-1)!
if (!source || !(key in source)) throw new Error(`Missing schema: ${ref}`)
target[key] = source[key]
includeReferences(source[key])
}
for (const child of Object.values(value)) includeReferences(child)
}
includeReferences(snapshot.paths)
writeFileSync(
resolve(import.meta.dirname, `../generated/${surface}/openapi.gen.json`),
`${JSON.stringify(snapshot, null, 2)}\n`,
)
+1
View File
@@ -35,6 +35,7 @@
"@types/node": "catalog:",
"@typescript/native": "catalog:",
"tsrs": "catalog:",
"typescript": "catalog:",
"vite": "catalog:",
"vite-plus": "catalog:"
},
@@ -0,0 +1,4 @@
dist/
node_modules/
reports/
*.tgz
@@ -0,0 +1,18 @@
# Changelog
## 0.1.0-beta.0
Initial experimental release. Requires TypeScript 7.1.0-beta for native content mapping and Node.js 24+ for tooling.
- Import OpenAPI 3.0/3.1 YAML or JSON-backed `.openapi` documents with inferred request and response types.
- Import `.openapi-source` command descriptors to infer from backend-exported OpenAPI in memory, with compiler and bundler dependency tracking.
- Export only `api` and `query`, with statically tree-shakable namespaces and typed document context.
- Support explicit `x-client-path` operation names without changing HTTP serialization or per-operation sidecars.
- Integrate with Vite, Next.js Turbopack/Webpack and Node module hooks, preserving independent document transports and sidecars.
- Support local schema references, recursive types, JSON, explicit multipart alternatives, binary bodies and raw SSE responses.
- Preserve download filenames from Content-Disposition, JSON wire strings for binary-formatted response fields and require explicit media selection for non-default alternatives.
- Resolve API/query types lazily, omit redundant schema representations and cache serialized mapper results across compiler processes, with invalidation for document, implementation and sidecar changes.
- Add statically selected operation query defaults and typed error maps, with lazy error validators and Vite/Next sidecar tracking.
The beta API and compiler protocol may change between prereleases. See the README for supported scope and compatibility limits.
+22
View File
@@ -0,0 +1,22 @@
# Open Source License
Dify is licensed under a modified version of the Apache License 2.0, with the following additional conditions:
1. Dify may be utilized commercially, including as a backend service for other applications or as an application development platform for enterprises. Should the conditions below be met, a commercial license must be obtained from the producer:
a. Multi-tenant service: Unless explicitly authorized by Dify in writing, you may not use the Dify source code to operate a multi-tenant environment.
- Tenant Definition: Within the context of Dify, one tenant corresponds to one workspace. The workspace provides a separated area for each tenant's data and configurations.
b. LOGO and copyright information: In the process of using Dify's frontend, you may not remove or modify the LOGO or copyright information in the Dify console or applications. This restriction is inapplicable to uses of Dify that do not involve its frontend.
- Frontend Definition: For the purposes of this license, the "frontend" of Dify includes all components located in the `web/` directory when running Dify from the raw source code, or the "web" image when running Dify with Docker.
2. As a contributor, you should agree that:
a. The producer can adjust the open-source agreement to be more strict or relaxed as deemed necessary.
b. Your contributed code may be used for commercial purposes, including but not limited to its cloud business operations.
Apart from the specific conditions mentioned above, all other rights and restrictions follow the Apache License 2.0. Detailed information about the Apache License 2.0 can be found at http://www.apache.org/licenses/LICENSE-2.0.
The interactive design of this product is protected by appearance patent.
© 2025 LangGenius, Inc.
+489
View File
@@ -0,0 +1,489 @@
# @dify/openapi-content-mapper
Import OpenAPI documents as typed, tree-shakable API calls and TanStack Query helpers using **TypeScript 7.1 Content Mappers**. No generated SDK source or declaration files need to be committed.
**Experimental beta:** the compiler integration targets TypeScript `7.1.0-beta`. The API and compiler protocol may change between prereleases. This package is ESM-only.
## Compatibility
| Environment | Supported setup |
| --------------------- | ---------------------------------------------------------------------- |
| Compiler | TypeScript `7.1.0-beta`, with `--runExternalCode` |
| Editor | TypeScript 7 extension, workspace compiler and content mappers enabled |
| Build/runtime tooling | Node.js 24+ |
| Vite | Official Vite 8.3.5; optional peer dependency |
| Next.js | Next.js 16.4.2, Turbopack and Webpack with the loader below |
| Browser runtime | Modern Fetch, Headers, FormData, Blob and ReadableStream APIs |
| Specification | OpenAPI 3.0/3.1, local JSON Pointer references |
## Install and try
After the beta is published:
```sh
npm install @dify/openapi-content-mapper@beta
npm install --save-dev typescript@7.1.0-beta vite@8.3.5
```
Before publication, install a locally packed release candidate with `npm install /path/to/dify-openapi-content-mapper-0.1.0-beta.0.tgz`. See [Development and release] for packaging and verification.
Create `pets.openapi.yaml`:
```yaml
openapi: 3.1.0
info:
title: Pets
version: '1'
servers:
- url: https://api.example.com
paths:
/pets/{petId}:
get:
parameters:
- name: petId
in: path
required: true
schema:
type: integer
responses:
'200':
description: A pet
content:
application/json:
schema:
type: object
required: [id, name]
properties:
id:
type: integer
name:
type: string
```
Configure `tsconfig.json`:
```json
{
"compilerOptions": {
"strict": true,
"target": "ES2022",
"module": "ESNext",
"moduleResolution": "Bundler",
"noEmit": true
},
"contentMappers": [
{
"package": "@dify/openapi-content-mapper",
"extensions": [".yaml", ".yml", ".openapi"]
}
]
}
```
Configure `vite.config.ts`:
```ts
import { openapi } from '@dify/openapi-content-mapper/vite'
import { defineConfig } from 'vite'
export default defineConfig({ plugins: [openapi()] })
```
Then call the API:
```ts
import { api, query } from './pets.openapi.yaml'
const pet = await api.pets.byPetId.get({ params: { petId: 1 } })
pet.name // string
const options = query.pets.byPetId.get.queryOptions({
input: { params: { petId: 1 } },
})
// Pass options to useQuery(), queryClient.fetchQuery(), etc.
```
Run `npx tsc --runExternalCode --noEmit`. The compiler supplies types; the Vite plugin supplies runtime modules. Both are required for this setup.
For VS Code, install Microsoft's TypeScript 7 extension (`TypeScriptTeam.native-preview`), select the workspace TypeScript 7.1 compiler, trust the workspace and enable content mappers. Open a consuming `.ts` file so the language server discovers its config.
### Compiler cache
Successful mapper results are cached in the current user's temporary directory under `dify-openapi-content-mapper-<user>`, retaining up to 64 documents. Content, implementation and configuration-sidecar presence changes invalidate the cache; sidecar contents are checked by TypeScript. The cache can be deleted safely. Corrupt entries or unavailable storage fall back to transformation, and no cache files are shipped to the browser.
### Existing JSON files
The TS 7.1 beta cannot register mappers for built-in `.json` imports, including `.openapi.json`. Store JSON in a file ending in `.openapi`, or symlink an existing JSON file:
```sh
ln -s pets.json pets.openapi
```
Import `./pets.openapi`. On platforms where symlinks are unavailable, use a regular `.openapi` file containing JSON. Vite and Node preserve the logical extension of symlinks.
### Local backend sources without generated specification files
Use an authored `pets.openapi-source` descriptor when the backend can export its
OpenAPI document to stdout. The descriptor contains the command, not the schema:
```json
{
"command": ["python", "export_openapi.py"],
"cwd": "../backend",
"inputs": ["**/*.py", "pyproject.toml"],
"exclude": ["tests/**"],
"optionalInputs": [".env"],
"env": ["API_EDITION"],
"timeoutMs": 60000
}
```
`cwd` is relative to the descriptor; input glob patterns are relative to `cwd`.
Declare every source/configuration input and any environment variables that affect
exported schemas. Input globs must match existing paths; `exclude` removes glob
matches that cannot affect the contract. `optionalInputs` lists exact paths that
may not exist yet, such as `.env`; their creation, changes and removal invalidate
the source. Dependency scanning excludes
`node_modules`, `.venv`, `.git` and `__pycache__`. Commands run without a shell;
`node` uses the current Node executable. Write exactly one OpenAPI JSON document to
stdout and send diagnostics to stderr. No running backend is needed if the exporter
can construct its schemas without starting services.
Register both the extension and the source in the consuming tsconfig:
```json
{
"contentMappers": [
{
"package": "@dify/openapi-content-mapper",
"extensions": [".openapi-source", ".openapi", ".yaml", ".yml"],
"options": { "sources": ["./pets.openapi-source"] }
}
]
}
```
Source entries are relative to this tsconfig's directory; inherited configurations
should declare them in the consuming project. Registration lets TypeScript watch
backend inputs and invalidate incremental builds even when the descriptor is
unchanged. Keep the descriptor in a package with an SDK dependency so its inferred
types can resolve the SDK. Then import it normally:
```ts
import { api, query } from './pets.openapi-source'
```
Vite and Node recognize `.openapi-source` automatically. Add a matching loader rule
for Next.js, as for an ordinary `.openapi` file. Existing document imports continue
to work alongside command sources. Configuration, queries and errors use the same
adjacent sidecars, such as `pets.openapi-source.config.ts`.
The editor, type checker and runtime adapters execute the same command-source
resolver. Exported OpenAPI content is cached in process memory until its declared
inputs change; the mapper's temporary cache stores derived types, not a committed
specification. Each new process needs the backend export environment. The exporter
and schema do not ship to the browser. Definitions from a command source have no
schema-file location; file imports retain their existing source navigation.
The repository Console exporter additionally shares its in-memory result between
compiler, editor and build processes through a local POSIX helper. It starts on
demand and exits after two idle minutes. A private Unix socket and empty lifecycle
lock are the only IPC files; OpenAPI content is never written to disk. The helper
is specific to the Console source, not enabled for arbitrary exporter commands.
On changes, a fresh child imports the current controllers from source, with safe
model dependencies preloaded. Changing a preloaded dependency, adding/removing a
Python file, changing `.env`, or changing the environment invalidates that state.
Python bytecode caches are bypassed to handle rapid same-size edits. Export errors
are surfaced rather than serving the old contract. Refreshes interrupted by more
source edits are retried. Backend tests are excluded from Console source inputs.
Native threads are checked before forking; unsafe snapshots and platforms without
fork use a fresh-process export instead. Those refreshes still incur cold startup.
To stop the local helper early, run from the same directory and environment used
by the source descriptor:
```sh
uv run --project api api/dev/cached_console_openapi.py --stop
```
The uncached reference exporter remains `api/dev/export_console_openapi.py`.
Command-source JSON is transformed directly, avoiding the YAML syntax tree and
source mappings needed only for file-backed documents.
### Navigate to backend implementations
An operation can carry optional development metadata:
```json
"x-source-location": { "file": "/checkout/api/controllers/pets.py", "line": 42 }
```
`line` is one-based. Relative paths resolve against the imported OpenAPI file or
`.openapi-source` descriptor. The mapper adds an **Open backend implementation**
link to the method's hover documentation, for both `api` and `query`. This works
with command sources and imported OpenAPI files. Metadata is excluded from runtime
operation descriptors and browser bundles.
For F12 / Cmd+click and Go to Implementation, install the optional local
[VS Code extension]. It uses the same hover link to find the
backend target. Without source metadata, normal schema navigation is preserved;
the extension skips backend files that are not present locally.
The Dify Console stdout exporter adds these locations automatically, including
unwrapping decorated handlers. This affects only the local in-memory export;
live API schemas and retained Enterprise snapshots are unchanged.
## API and transport
Documents export only `api` and `query`; operation IDs are not exports. `/pets/{petId}` becomes `pets.byPetId`, hyphenated segments become camelCase and HTTP methods are leaf functions. Colon actions such as `/chat:run` become `chat.run`. `key` is reserved as a route segment for query helpers. Unresolvable member collisions fail during compilation.
An operation may set `x-client-path` to an explicit array such as `["enterprise", "access", "getEnvironmentApi"]` to preserve an existing public API. This replaces its entire client member path, including the method leaf, and also determines its query key. HTTP methods, URLs and per-operation sidecar keys still use the OpenAPI operation. Colliding or reserved member names fail during compilation.
The first argument contains `params`, `query`, `headers`, `cookie`, `body` and `contentType` as declared by the specification. The optional second argument accepts `client`, `signal`, additional transport `headers`, `credentials` and document `context`.
```ts
import { createClient } from '@dify/openapi-content-mapper'
import { api } from './pets.openapi.yaml'
const transport = createClient({
baseUrl: 'https://api.example.com/v1',
headers: { Authorization: 'Bearer …' },
fetch: globalThis.fetch,
})
await api.pets.byPetId.get(
{ params: { petId: 1 } },
{ client: transport, signal: AbortSignal.timeout(5000) },
)
```
A client override takes precedence over document configuration. Otherwise the document's `servers` URL is used; relative server URLs require a browser origin or an explicit absolute `baseUrl` in Node. The exported shared `client` also supports `setConfig()`, but request-specific credentials should use independent clients.
Successful calls return decoded response data. Non-2xx responses throw `ApiError` with `response` and decoded `data`; network and cancellation failures propagate. Responses are not runtime-validated and schema defaults are not filled in. JSON binary-formatted fields remain strings; binary response media return Blob objects (File with the response filename when Content-Disposition is present); SSE returns a raw `ReadableStream<Uint8Array>`.
Wildcard response media follow the most specific matching declaration for the response status: `*/*` and `application/*` return Blob, while `text/*` returns text. An explicit `application/json` or `text/event-stream` declaration takes precedence over a wildcard. HTTP errors are decoded from their actual Content-Type.
With one request media type, `contentType` can be omitted. With multiple media types, only `application/json` is implicit; other alternatives require an explicit matching `contentType`. Multipart accepts flat objects with scalar, Blob/File or repeated array fields, plus explicit JSON part encodings. Fetch supplies its boundary. Optional request bodies may be omitted entirely.
### Document configuration
Place `pets.openapi.yaml.config.ts` next to `pets.openapi.yaml`:
```ts
import type { RuntimeConfig } from '@dify/openapi-content-mapper'
import { createClient } from '@dify/openapi-content-mapper'
export type Context = { token?: string }
const runtime: RuntimeConfig<Context> = {
createClient: ({ context }) =>
createClient({
baseUrl: 'https://api.example.com',
headers: context?.token ? { Authorization: `Bearer ${context.token}` } : {},
}),
queryKeyPrefix: ['pets'],
}
export default runtime
```
Both `api` and `query` infer `Context`. The factory runs per call. An optional `onError(error)` hook observes failures; avoid throwing from it if you want the original error to propagate. Restart the development server after adding or removing a sidecar; edits to existing files follow normal HMR.
### Per-operation query defaults and typed errors
Export defaults from `<document>.queries.ts` under the exact `METHOD /path` name:
```ts
// pets.openapi.queries.ts
import type { experimental_RouterUtilsDefaults } from '@orpc/tanstack-query'
import type { api } from './pets.openapi'
const list: experimental_RouterUtilsDefaults<typeof api.pets.get> = {
queryOptions: { staleTime: 30_000, retry: false },
}
export { list as 'GET /pets' }
```
Defaults use oRPC's query helpers, including mutation callbacks and infinite queries.
Caller options override defaults, including callbacks; they are not composed. Return
cache invalidation promises from mutation callbacks when the mutation must remain
pending until refresh completes. Keep policy dependencies independent of a complete
runtime router: importing or enumerating a whole client can retain unrelated operations.
An optional `<document>.errors.ts` exports oRPC error maps with the same names:
```ts
// pets.openapi.errors.ts
import type { ErrorMap } from '@orpc/contract'
import { conflictSchema } from './error-schemas'
const conflicts = {
CONFLICT: { status: 409, data: conflictSchema },
} satisfies ErrorMap
export { conflicts as 'POST /pets' }
```
The `data` validator can use any Standard Schema implementation. API calls and query
helpers infer the map's error union, so `safe` and `isDefinedError` narrow the code and
validated payload. HTTP status and schema validation must match before an error is
marked defined. Network/cancellation failures keep their identity. Bare HTTP errors
with a `code` envelope are converted to `ORPCError` when an error map is configured;
existing transport `ORPCError`s are preserved and validated.
Each operation imports its own defaults and lazy error module. Error validators load
on HTTP failure, and unused maps/defaults can be removed by the bundler. Vite
application builds group retained error modules by document to avoid a tiny chunk per
operation, while keeping validators lazy and respecting custom chunk groups. Strict library exports and legacy manual chunk
configurations keep the bundler's existing chunking behavior. A validator
chunk that fails to load leaves the original HTTP error undefined. Serve the emitted
chunks together with the entry bundle. Keep validators free of module-level side
effects; schema construction must be removable when its map is unused. Named
re-exports and `export *` are supported; sidecars are inspected without executing them.
Vite and Next track sidecar changes; Node imports follow normal module caching.
Sidecar star re-exports use the consuming bundler's resolver. Vite supports aliases and TypeScript extension resolution (such as `./defaults.js` resolving to `defaults.ts`); Next.js Webpack requires the same `experimental.extensionAlias` configuration as ordinary imports for that convention. For Turbopack, use explicit relative source paths such as `./defaults.ts`: its loader resolver does not support those aliases. Native Node execution retains Node's ESM resolution rules and requires executable import paths.
### Query helpers and bundles
Import `query` directly for `queryOptions`, `mutationOptions`, `queryKey` and namespace `key()` helpers. Give each document a distinct `queryKeyPrefix` when routes overlap. For an application-level entry, preserve direct ESM re-exports:
```ts
export { api as apiClient, query as apiQuery } from './pets.openapi.yaml'
```
Static calls retain only used operations. Dynamic indexing, enumeration or passing whole namespaces to opaque functions can retain other operations. The runtime does not bundle response schemas or the YAML parser.
### Comparison with oRPC
This package consumes OpenAPI directly and prunes statically used operations while keeping oRPC-shaped calls and reusing its TanStack Query helpers. It requires the TS 7.1 beta toolchain. Per-operation defaults and error maps are opt-in; arbitrary oRPC Links and interceptors still require an application transport adapter.
## Other runtime adapters
### Node.js
```sh
node --import @dify/openapi-content-mapper/register app.ts
```
The hook loads YAML, `.openapi` and `.openapi-source` files; Node's native TypeScript support loads configuration sidecars. Native execution does not replace the separate type check.
### Next.js
For `pets.openapi` linked to `pets.json`, configure `next.config.mjs`:
```js
const loader = {
loader: '@dify/openapi-content-mapper/loader',
// Optional; relative to the resolved specification, not this config file.
options: {
runtime: './pets.openapi.config.ts',
sidecars: './pets.openapi',
},
}
export default {
turbopack: {
rules: {
'*pets.json': { loaders: [loader], as: '*.js' },
'*openapi-namespace.js': { loaders: ['@dify/openapi-content-mapper/loader'], as: '*.js' },
},
},
webpack(config) {
config.module.rules.push({
test: /pets\.json$/,
type: 'javascript/auto',
use: [loader],
})
config.module.rules.push({
test: /openapi-namespace\.js$/,
type: 'javascript/auto',
use: ['@dify/openapi-content-mapper/loader'],
})
return config
},
}
```
Merge these rules into existing configuration. Match the resolved JSON filename for symlinks; match the actual `.openapi` or YAML filename for regular files. Apply the loader to `openapi-namespace.js` too, without document-specific options. Each document carries its own runtime and sidecar bindings into its child namespaces, so multiple documents can use different transports in one build. Omit `options.runtime` to discover `<resolved specification filename>.config.ts`. Set `options.sidecars` to the logical document path (relative to the resolved specification) when its `.queries.ts` and `.errors.ts` files live beside a symlink. Without this option they are discovered beside the resolved specification. Next.js runtime options do not change compiler context discovery, which uses the imported document's adjacent sidecar.
The loader uses a tiny shared resource for child namespaces so the full specification is not copied into every bundler module. Adapters use internal subpaths (`runtime`, `query-runtime`, `namespace`, `mapper`); application code should use the root, `vite`, `loader` and `register` entry points.
## Limitations
External references, Swagger 2, URL-encoded forms, advanced parameter serialization, nested multipart file dictionaries and YAML aliases are unsupported. Inline schema inference has a 24-step fallback; local referenced schemas use recursive aliases. Unsupported request serialization fails explicitly. Missing or inaccurate OpenAPI declarations cannot be repaired by inference.
Existing oRPC Links and interceptors require explicit transport adapters; query policies and typed errors require the per-operation sidecars above. Browser Fetch governs cookie headers. Supported schema features include required/optional properties, enum/const, arrays and dictionaries, `oneOf`, `anyOf`, `allOf`, and nullable types.
## Repository setup
The Dify workspace configures TypeScript 7.1, VS Code, Vite and Next.js to support
future OpenAPI imports. Production Console and Marketplace calls continue to use
their existing oRPC clients. Application transports, query-policy migration and
business call-site changes are deferred.
The repository Console source descriptor lives in
`examples/repository/console.openapi-source`. Its command exports community Console
and FastOpenAPI schemas from local Python code into memory, then composes them with
the retained Enterprise and App Deploy snapshots. Community specifications and the
composed document are not committed or written during workspace installation.
Ordinary installation and production application builds do not execute the exporter;
consuming the experimental Console source requires Python dependencies:
```sh
uv sync --project api --frozen
pnpm --filter @dify/openapi-content-mapper build
pnpm --filter @dify/openapi-content-mapper check:console
```
No running API, database or private source checkout is needed. CI installs the
Python environment before the standalone Console checks. `compose:console` now
prints the composed OpenAPI JSON to stdout instead of creating a file.
The package uses `vp pack` and builds through `prepare` during workspace installation,
like `@langgenius/dev-proxy`. Web's `prebuild` and `prebuild:vinext` hooks also build
the SDK so production builds work after an installation with `--ignore-scripts`,
including the unchanged Docker build flow.
The Console audit checks every generated procedure against a reviewed per-operation
type-difference baseline. Standalone fixtures verify bundle pruning, error maps and
workspace editor support without importing a production mapper client. The broader
`test:repository` suite also needs the ignored API specifications generated with
`pnpm --dir packages/contracts gen-api-contract`.
Regenerate existing oRPC contracts when backend schemas change. Enterprise snapshot
regeneration still uses the matching source checkout through
`DIFY_ENTERPRISE_SERVER`; those snapshots remain tracked because community checkouts
cannot regenerate them. Inspect the comparison report before accepting intentional
baseline changes with `compare:orpc -- --console --update-baseline`.
## Development and release
From the repository root, build and verify the package:
```sh
pnpm --filter @dify/openapi-content-mapper build
pnpm --filter @dify/openapi-content-mapper type-check
pnpm --filter @dify/openapi-content-mapper test
OPENAPI_PACKAGE_TARBALL=/tmp/dify-openapi-content-mapper.tgz \
pnpm --filter @dify/openapi-content-mapper test:package
```
The independent package check packs and installs the tarball outside the monorepo, then exercises its declarations, compiler mapper, Node runtime and official Vite adapter. It requires network access and performs no publication. Full application and Next.js builds run in CI.
Update the package version and [CHANGELOG] together before release. Use pnpm to pack: it resolves workspace `catalog:` dependencies, while `prepack` cleans and rebuilds `dist`. The package contains compiled ESM/declarations, README, changelog and license; consumers do not build it during installation.
A maintainer with npm access can publish the same verified artifact after confirming its name, version, license and registry:
```sh
npm publish /tmp/dify-openapi-content-mapper.tgz --access public --tag beta
```
The default tag is `beta`. Publication is manual; merging changes or creating a Dify release does not publish the package. Verify new compiler versions before changing the supported TS 7.1 beta protocol.
## License
This package retains the repository's modified Apache 2.0 terms, including its additional conditions. See [LICENSE]; it is not licensed under unmodified Apache-2.0 or MIT.
[CHANGELOG]: CHANGELOG.md
[Development and release]: #development-and-release
[LICENSE]: LICENSE
[VS Code extension]: ./vscode/README.md
@@ -0,0 +1,11 @@
import { createClient } from '@dify/openapi-content-mapper'
import { api } from './pets.openapi.yaml'
export const client = createClient({ baseUrl: 'http://127.0.0.1:4317' })
// Hover, complete operation names, or deliberately introduce an invalid field here.
export async function example() {
const pet = await api.pets.byPetId.get({ params: { petId: 1 } }, { client })
const pets = await api.pets.get({ query: { status: 'available' } }, { client })
return { pet, pets }
}
@@ -0,0 +1,80 @@
import assert from 'node:assert/strict'
import { once } from 'node:events'
import { createServer } from 'node:http'
import { ApiError, createClient } from '@dify/openapi-content-mapper'
import { api as jsonApi } from './pets.openapi'
import { api } from './pets.openapi.yaml'
async function main() {
const pets = [{ id: 1, name: 'Mochi', status: 'available' }]
const server = createServer(async (req, res) => {
const url = new URL(req.url!, 'http://localhost')
res.setHeader('Content-Type', 'application/json')
if (req.method === 'GET' && url.pathname === '/pets') {
res.end(
JSON.stringify(
pets.filter(
(pet) =>
!url.searchParams.has('status') || pet.status === url.searchParams.get('status'),
),
),
)
return
}
if (req.method === 'POST' && url.pathname === '/pets') {
let body = ''
for await (const chunk of req) body += chunk
const input = JSON.parse(body)
const pet = { id: pets.length + 1, name: input.name, status: input.status ?? 'available' }
pets.push(pet)
res.writeHead(201).end(JSON.stringify(pet))
return
}
const pet = pets.find((pet) => url.pathname === `/pets/${pet.id}`)
if (pet && req.method === 'DELETE') {
pets.splice(pets.indexOf(pet), 1)
res.writeHead(204).end()
return
}
res.writeHead(pet ? 200 : 404).end(JSON.stringify(pet ?? { message: 'Pet not found' }))
})
server.listen(0, '127.0.0.1')
await once(server, 'listening')
try {
const address = server.address()
assert(address && typeof address !== 'string')
const client = createClient({ baseUrl: `http://127.0.0.1:${address.port}` })
assert.equal(
(await jsonApi.pets.byPetId.get({ params: { petId: 1 } }, { client })).name,
'Mochi',
)
// oxlint-disable-next-line no-console -- The executable demo reports HTTP results.
console.log('GET:', await api.pets.byPetId.get({ params: { petId: 1 } }, { client }))
// oxlint-disable-next-line no-console -- The executable demo reports HTTP results.
console.log('POST:', await api.pets.post({ body: { name: '雪团' } }, { client }))
// oxlint-disable-next-line no-console -- The executable demo reports HTTP results.
console.log('QUERY:', await api.pets.get({ query: { status: 'available' } }, { client }))
assert.equal(await api.pets.byPetId.delete({ params: { petId: 2 } }, { client }), undefined)
try {
await api.pets.byPetId.get({ params: { petId: 404 } }, { client })
assert.fail('Expected 404')
} catch (error) {
assert(error instanceof ApiError)
assert.equal(error.response.status, 404)
// oxlint-disable-next-line no-console -- The executable demo reports HTTP results.
console.log('ERROR:', error.response.status, error.data)
}
// oxlint-disable-next-line no-console -- The executable demo reports HTTP results.
console.log('Passed: direct YAML import → typed SDK → real local HTTP server')
} finally {
server.closeAllConnections()
await new Promise<void>((resolve, reject) =>
server.close((error) => (error ? reject(error) : resolve())),
)
}
}
main().catch((error) => {
console.error(error)
process.exitCode = 1
})
@@ -0,0 +1,2 @@
// TS 7.1 reserves .json. This .openapi symlink points at the original pets.json.
export { api } from './pets.openapi'
@@ -0,0 +1,160 @@
{
"openapi": "3.1.0",
"info": {
"title": "Petstore inference demo",
"version": "1.0.0"
},
"paths": {
"/pets": {
"get": {
"operationId": "listPets",
"parameters": [
{
"name": "limit",
"in": "query",
"schema": {
"type": "integer"
}
},
{
"name": "status",
"in": "query",
"schema": {
"type": "string",
"enum": ["available", "adopted"]
}
}
],
"responses": {
"200": {
"description": "Pets",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"$ref": "#/components/schemas/Pet"
}
}
}
}
}
}
},
"post": {
"operationId": "createPet",
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["name"],
"properties": {
"name": {
"type": "string"
},
"status": {
"type": "string",
"enum": ["available", "adopted"]
}
}
}
}
}
},
"responses": {
"201": {
"description": "Created",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
}
}
}
},
"/pets/{petId}": {
"parameters": [
{
"$ref": "#/components/parameters/PetId"
}
],
"get": {
"operationId": "getPet",
"responses": {
"200": {
"description": "Found",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/Pet"
}
}
}
},
"404": {
"description": "Missing",
"content": {
"application/json": {
"schema": {
"type": "object",
"required": ["message"],
"properties": {
"message": {
"type": "string"
}
}
}
}
}
}
}
},
"delete": {
"operationId": "deletePet",
"responses": {
"204": {
"description": "Deleted"
}
}
}
}
},
"components": {
"parameters": {
"PetId": {
"name": "petId",
"in": "path",
"required": true,
"schema": {
"type": "integer"
}
}
},
"schemas": {
"Pet": {
"type": "object",
"required": ["id", "name", "status"],
"properties": {
"id": {
"type": "integer"
},
"name": {
"type": "string"
},
"status": {
"type": "string",
"enum": ["available", "adopted"]
},
"nickname": {
"type": ["string", "null"]
}
}
}
}
}
}
@@ -0,0 +1 @@
pets.json
@@ -0,0 +1,98 @@
openapi: 3.1.0
info:
title: Petstore inference demo
version: 1.0.0
paths:
/pets:
get:
operationId: listPets
parameters:
- name: limit
in: query
schema:
type: integer
- name: status
in: query
schema:
type: string
enum: [available, adopted]
responses:
'200':
description: Pets
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/Pet'
post:
operationId: createPet
requestBody:
required: true
content:
application/json:
schema:
type: object
required: [name]
properties:
name:
type: string
status:
type: string
enum: [available, adopted]
responses:
'201':
description: Created
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
/pets/{petId}:
parameters:
- $ref: '#/components/parameters/PetId'
get:
operationId: getPet
responses:
'200':
description: Found
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
'404':
description: Missing
content:
application/json:
schema:
type: object
required: [message]
properties:
message:
type: string
delete:
operationId: deletePet
responses:
'204':
description: Deleted
components:
parameters:
PetId:
name: petId
in: path
required: true
schema:
type: integer
schemas:
Pet:
type: object
required: [id, name, status]
properties:
id:
type: integer
name:
type: string
status:
type: string
enum: [available, adopted]
nickname:
type: [string, 'null']
@@ -0,0 +1,7 @@
import { query as consoleQuery } from './pets.openapi.yaml'
export const petQueryOptions = consoleQuery.pets.byPetId.get.queryOptions({
input: { params: { petId: 1 } },
})
export const createPetMutationOptions = consoleQuery.pets.post.mutationOptions()
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
"types": ["node"],
"strict": true,
"noEmit": true,
"skipLibCheck": true
},
"contentMappers": [
{
"package": "../..",
"extensions": [".yaml", ".yml", ".openapi"]
}
],
"include": ["*.ts"]
}
@@ -0,0 +1,25 @@
import { api as consoleClient, query as consoleQuery } from './console.openapi-source'
import { api as knowledgeClient } from './knowledge-fs.openapi'
// Hover over `result`, `total`, or a query option to see inferred types.
// Type `consoleClient.datasets.` to explore the actual console endpoints.
// Hover `get` for its backend link; the optional navigation extension also enables F12.
export async function listDatasets() {
const result = await consoleClient.datasets.get({ query: { page: 1, limit: 20 } })
const total: number = result.total
return { total, datasets: result.data }
}
export const datasetsQuery = consoleQuery.datasets.get.queryOptions({
input: { query: { page: 1 } },
})
export async function uploadFile(file: File) {
return consoleClient.files.upload.post({ body: { file, source: 'datasets' } })
}
export async function health() {
const result = await knowledgeClient.health.get()
const runtime: 'cloudflare-workers' | 'node-docker' = result.runtime
return { runtime, ok: result.ok }
}
@@ -0,0 +1,16 @@
{
"command": ["node", "packages/contracts/scripts/compose-console-openapi.mjs"],
"cwd": "../../../..",
"inputs": [
"api/**/*.py",
"api/pyproject.toml",
"api/uv.lock",
"packages/contracts/scripts/compose-console-openapi.mjs",
"packages/contracts/generated/enterprise/openapi.gen.json",
"packages/contracts/generated/enterprise-app-deploy/openapi.gen.json"
],
"env": ["UV_PROJECT_ENVIRONMENT"],
"exclude": ["api/tests/**"],
"optionalInputs": [".env"],
"timeoutMs": 90000
}
@@ -0,0 +1 @@
../../../../api/knowledge-fs-contract/knowledge-fs.openapi.json
@@ -0,0 +1,22 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["ES2022", "DOM", "DOM.Iterable"],
"module": "NodeNext",
"moduleResolution": "NodeNext",
"types": ["node"],
"strict": true,
"noEmit": true,
"skipLibCheck": true
},
"contentMappers": [
{
"package": "../..",
"extensions": [".yaml", ".yml", ".openapi", ".openapi-source"],
"options": {
"sources": ["./console.openapi-source"]
}
}
],
"include": ["*.ts"]
}
@@ -0,0 +1,560 @@
/* oxlint-disable antfu/no-import-dist -- Audit the built native mapper against generated repository contracts. */
import assert from 'node:assert/strict'
import { spawnSync } from 'node:child_process'
import { createHash } from 'node:crypto'
import {
globSync,
mkdirSync,
mkdtempSync,
readFileSync,
rmSync,
symlinkSync,
writeFileSync,
} from 'node:fs'
import { join, relative, resolve } from 'node:path'
import { pathToFileURL } from 'node:url'
import { loadConsoleDocument } from '../../contracts/scripts/compose-console-openapi.mjs'
import { describeOperations } from '../dist/operation.js'
import { createRouter } from '../dist/tooling/router.js'
/* oxlint-enable antfu/no-import-dist */
const root = resolve(import.meta.dirname, '..')
const repo = resolve(root, '../..')
const specDir = process.env.DIFY_OPENAPI_DIR ?? resolve(root, '../contracts/openapi')
const enforceAlignment = process.argv.includes('--check')
const consoleOnly = process.argv.includes('--console')
const updateBaseline = process.argv.includes('--update-baseline')
const output = resolve(
process.argv.slice(2).find((arg) => !arg.startsWith('--')) ??
join(root, 'reports/orpc-comparison.json'),
)
const documents = consoleOnly
? ['console-client']
: ['console', 'fastopenapi-console', 'service', 'openapi', 'web', 'inner', 'knowledge-fs']
const report = {
scope:
'All repository OpenAPI operations versus existing generated/api oRPC procedures; static schema input/output types, not validation, errors or transport execution.',
documents: [],
matched: [],
unmatchedOpenApi: [],
unmatchedOrpc: [],
compilerErrors: [],
}
const key = (surface, method, path) => `${surface} ${method.toUpperCase()} ${path}`
report.sourceRevision = spawnSync('git', ['rev-parse', 'HEAD'], {
cwd: repo,
encoding: 'utf8',
}).stdout.trim()
report.compilerVersion = spawnSync(
process.execPath,
[join(root, 'node_modules/typescript/bin/tsc'), '--version'],
{ encoding: 'utf8' },
).stdout.trim()
report.generatedFiles = [...globSync(join(repo, 'packages/contracts/generated/api/**/*.ts'))]
.sort()
.map((file) => ({
file: relative(repo, file),
sha256: createHash('sha256').update(readFileSync(file)).digest('hex'),
}))
report.sdkTypeSourceSha256 = createHash('sha256')
.update(readFileSync(join(root, 'src/types.ts')))
.digest('hex')
const contracts = new Map()
const contractFiles = consoleOnly
? [
...globSync(join(repo, 'packages/contracts/generated/api/console/**/orpc.gen.ts')),
join(repo, 'packages/contracts/generated/enterprise/orpc.gen.ts'),
join(repo, 'packages/contracts/generated/enterprise-app-deploy/orpc.gen.ts'),
]
: [...globSync(join(repo, 'packages/contracts/generated/api/**/orpc.gen.ts'))]
for (const file of contractFiles.sort()) {
// oxlint-disable-next-line antfu/no-top-level-await -- This CLI must load contract metadata before generating the audit.
const exports = await import(pathToFileURL(file))
const surface = consoleOnly
? 'console'
: relative(join(repo, 'packages/contracts/generated/api'), file).split('/')[0]
for (const [name, value] of Object.entries(exports)) {
const def = value?.['~orpc']
if (!def) continue
const id = key(surface, def.route.method, def.route.path)
assert(!contracts.has(id), `Duplicate generated procedure: ${id}`)
contracts.set(id, {
id,
file: relative(repo, file),
name,
hasInputSchema: !!def.inputSchema,
hasOutputSchema: !!def.outputSchema,
})
}
}
function* routes(node, members = []) {
for (const [method, operation] of node.methods) yield { operation, members: [...members, method] }
for (const [name, child] of node.children) yield* routes(child, [...members, name])
}
function deref(schema, spec) {
while (schema?.$ref?.startsWith('#/'))
schema = schema.$ref
.slice(2)
.split('/')
.reduce((v, k) => v?.[k.replaceAll('~1', '/').replaceAll('~0', '~')], spec)
return schema
}
const dir = mkdtempSync(join(root, 'integration/.compare-'))
const lines = []
const assertions = new Map()
const add = (text) => lines.push(text)
const check = (row, name, expression, expected = true) => {
add(`const c${row}_${name}: ${expression} = ${expected};`)
assertions.set(lines.length, { row, name, expected })
report.matched[row].checks[name] = expected
}
try {
add("type Schema = { '~standard': { types?: { input: unknown; output: unknown } } };")
add("type Contract = { '~orpc': { inputSchema?: Schema; outputSchema?: Schema } };")
add(
"type Input<T extends Contract> = NonNullable<NonNullable<T['~orpc']['inputSchema']>['~standard']['types']>['input'];",
)
add(
"type Output<T extends Contract> = NonNullable<NonNullable<T['~orpc']['outputSchema']>['~standard']['types']>['output'];",
)
add(
"type WireOutput<T extends Contract> = NonNullable<NonNullable<T['~orpc']['outputSchema']>['~standard']['types']>['input'];",
)
add('type NormalizeVoid<T> = T extends void ? undefined : T;')
add('type Ext<A,B> = [A] extends [B] ? true : false;')
add('type Any<T> = 0 extends (1 & T) ? true : false;')
add('type Unknown<T> = unknown extends T ? true : false;')
add('type Never<T> = [T] extends [never] ? true : false;')
add(
'type Field<T,K extends PropertyKey> = T extends unknown ? K extends keyof T ? T[K] : undefined : never;',
)
add(
"type RenameHeader<T> = T extends { header: infer H } ? Omit<T,'header'|'headers'> & { headers: H } : T extends { header?: infer H } ? Omit<T,'header'|'headers'> & { headers?: H } : T;",
)
add(
"type SplitBody<T, B = T extends {body: infer Body} ? Body : never> = [B] extends [never] ? T : B extends unknown ? Omit<T,'body'> & {body:B} : never;",
)
add("type WithoutContentType<T> = T extends unknown ? Omit<T, 'contentType'> : never;")
for (const [docIndex, name] of documents.entries()) {
const file =
name === 'knowledge-fs'
? join(repo, 'api/knowledge-fs-contract/knowledge-fs.openapi.json')
: join(specDir, `${name}-openapi.json`)
const bytes = consoleOnly ? JSON.stringify(loadConsoleDocument()) : readFileSync(file)
const spec = JSON.parse(bytes)
const inventory = [...routes(createRouter(describeOperations(spec)))]
report.documents.push({
name,
operations: inventory.length,
sha256: createHash('sha256').update(bytes).digest('hex'),
})
if (!consoleOnly) symlinkSync(file, join(dir, `${name}.openapi`))
const specifier = consoleOnly
? join(repo, 'packages/openapi-content-mapper/examples/repository/console.openapi-source')
: `./${name}.openapi`
add(`import { api as api${docIndex} } from ${JSON.stringify(specifier)};`)
for (const { operation, members } of inventory) {
const surface = consoleOnly || name === 'fastopenapi-console' ? 'console' : name
const path =
name === 'fastopenapi-console'
? operation.path.replace(/^\/console\/api(?=\/|$)/, '') || '/'
: operation.path
const id = key(surface, operation.method, path)
const contract = contracts.get(id)
if (!contract) {
report.unmatchedOpenApi.push({
document: name,
method: operation.method,
path: operation.path,
reason: ['inner', 'knowledge-fs'].includes(name)
? 'No generated/api oRPC surface exists'
: 'No generated procedure for method and path',
responseStatuses: Object.keys(
spec.paths[operation.path][operation.method].responses ?? {},
),
})
continue
}
contracts.delete(id)
const row = report.matched.length
const op = spec.paths[operation.path][operation.method]
const responses = Object.entries(op.responses ?? {})
.filter(([status]) => /^2\d\d$/.test(status))
.map(([status, r]) => ({ status, ...deref(r, spec) }))
const content = deref(op.requestBody, spec)?.content ?? {}
report.matched.push({
id,
document: name,
path: operation.path,
method: operation.method,
sdkMembers: members,
contract,
traits: {
requestMedia: Object.keys(content),
responseMedia: [...new Set(responses.flatMap((r) => Object.keys(r.content ?? {})))],
successStatuses: responses.map((r) => r.status),
jsonBinaryResponse: responses.some((r) => {
const schema = deref(r.content?.['application/json']?.schema, spec)
return schema?.type === 'string' && schema.format === 'binary'
}),
opaqueResponse: responses.some(
(r) =>
!['204', '205'].includes(r.status) &&
(!r.content || Object.values(r.content).some((m) => !m.schema)),
),
},
checks: {},
})
add(
`import type { ${contract.name} as proc${row} } from ${JSON.stringify(resolve(repo, contract.file))};`,
)
add(
`type S${row} = typeof api${docIndex}${members.map((k) => `[${JSON.stringify(k)}]`).join('')};`,
)
add(`type NI${row} = Parameters<S${row}>[0]; type NO${row} = Awaited<ReturnType<S${row}>>;`)
add(`type OI${row} = Input<typeof proc${row}>; type OO${row} = Output<typeof proc${row}>;`)
for (const [label, a, b] of [
['inputSdkToOrpc', `NI${row}`, `OI${row}`],
['inputOrpcToSdk', `OI${row}`, `NI${row}`],
['outputSdkToOrpc', `NO${row}`, `OO${row}`],
['outputOrpcToSdk', `OO${row}`, `NO${row}`],
])
check(row, label, `Ext<${a},${b}>`)
for (const [label, t] of [
['sdkInput', `NI${row}`],
['orpcInput', `OI${row}`],
['sdkOutput', `NO${row}`],
['orpcOutput', `OO${row}`],
]) {
for (const guard of ['Any', 'Unknown', 'Never'])
check(row, `${label}${guard}`, `${guard}<${t}>`, false)
}
check(row, 'renamedHeaderSdkToOrpc', `Ext<RenameHeader<NI${row}>,OI${row}>`)
check(row, 'renamedHeaderOrpcToSdk', `Ext<OI${row},RenameHeader<NI${row}>>`)
check(row, 'sdkOutputString', `Ext<NO${row},string>`)
check(row, 'orpcOutputBlob', `Ext<OO${row},Blob>`)
check(row, 'sdkAcceptsOmittedInput', `Ext<undefined,NI${row}>`)
check(row, 'wireOutputSdkToOrpc', `Ext<NO${row},WireOutput<typeof proc${row}>>`)
check(row, 'wireOutputOrpcToSdk', `Ext<WireOutput<typeof proc${row}>,NO${row}>`)
check(row, 'normalizedVoidSdkToOrpc', `Ext<NormalizeVoid<NO${row}>,NormalizeVoid<OO${row}>>`)
check(row, 'normalizedVoidOrpcToSdk', `Ext<NormalizeVoid<OO${row}>,NormalizeVoid<NO${row}>>`)
for (const field of ['body', 'query', 'params', 'headers', 'header', 'cookie']) {
check(
row,
`${field}SdkToOrpc`,
`Ext<Field<NI${row},'${field}'>,Field<OI${row},'${field}'>>`,
)
check(
row,
`${field}OrpcToSdk`,
`Ext<Field<OI${row},'${field}'>,Field<NI${row},'${field}'>>`,
)
}
if (report.matched[row].traits.responseMedia.includes('text/event-stream')) {
check(
row,
'nonStreamSdkToOrpc',
`Ext<Exclude<NO${row},ReadableStream<Uint8Array>>,Exclude<OO${row},string>>`,
)
check(
row,
'nonStreamOrpcToSdk',
`Ext<Exclude<OO${row},string>,Exclude<NO${row},ReadableStream<Uint8Array>>>`,
)
}
if (report.matched[row].traits.responseMedia.includes('text/event-stream')) {
check(
row,
'nonStreamWireSdkToOrpc',
`Ext<Exclude<NO${row},ReadableStream<Uint8Array>>,Exclude<WireOutput<typeof proc${row}>,string>>`,
)
check(
row,
'nonStreamWireOrpcToSdk',
`Ext<Exclude<WireOutput<typeof proc${row}>,string>,Exclude<NO${row},ReadableStream<Uint8Array>>>`,
)
}
if (Object.keys(content).includes('multipart/form-data')) {
check(row, 'withoutContentTypeSdkToOrpc', `Ext<WithoutContentType<NI${row}>,OI${row}>`)
check(
row,
'withoutContentTypeOrpcToSdk',
`Ext<SplitBody<OI${row}>,WithoutContentType<NI${row}>>`,
)
check(
row,
'multipartSdkToOrpc',
`Ext<WithoutContentType<Extract<NI${row},{contentType?:'multipart/form-data'}>>,OI${row}>`,
)
check(
row,
'multipartOrpcToSdk',
`Ext<OI${row},WithoutContentType<Extract<NI${row},{contentType?:'multipart/form-data'}>>>`,
)
}
}
}
report.unmatchedOrpc = [...contracts.values()]
writeFileSync(join(dir, 'check.ts'), lines.join('\n'))
writeFileSync(
join(dir, 'tsconfig.json'),
JSON.stringify({
compilerOptions: {
strict: true,
noEmit: true,
skipLibCheck: true,
target: 'ES2022',
module: 'NodeNext',
allowImportingTsExtensions: true,
types: ['node'],
lib: ['ES2022', 'DOM'],
},
contentMappers: [
{
package: root,
extensions: ['.openapi', '.openapi-source'],
options: {
sources: consoleOnly
? [
join(
repo,
'packages/openapi-content-mapper/examples/repository/console.openapi-source',
),
]
: [],
},
},
],
include: ['*.ts'],
}),
)
const started = performance.now()
const result = spawnSync(
process.execPath,
[
join(root, 'node_modules/typescript/bin/tsc'),
'--runExternalCode',
'--pretty',
'false',
'-p',
dir,
],
{ cwd: root, encoding: 'utf8', timeout: 180000, maxBuffer: 32 * 1024 * 1024 },
)
assert.ifError(result.error)
assert(
[0, 2].includes(result.status),
`Compiler failed: ${result.status} ${result.signal}\n${result.stdout}\n${result.stderr}`,
)
for (const diagnostic of result.stdout.split('\n').filter(Boolean)) {
const m = /check\.ts\((\d+),\d+\): error TS(\d+): (.*)/.exec(diagnostic)
const assertion = m && assertions.get(Number(m[1]))
if (
assertion &&
m[2] === '2322' &&
/^Type '(?:true|false)' is not assignable to type '(?:true|false)'\.$/.test(m[3])
)
report.matched[assertion.row].checks[assertion.name] = !assertion.expected
else report.compilerErrors.push({ diagnostic, source: m ? lines[Number(m[1]) - 1] : undefined })
}
if (result.stderr.trim()) report.compilerErrors.push({ diagnostic: result.stderr })
for (const row of report.matched) {
const c = row.checks
row.inputCategory =
c.inputSdkToOrpc && c.inputOrpcToSdk
? 'compatible'
: !row.contract.hasInputSchema && c.orpcInputUnknown && c.sdkAcceptsOmittedInput
? 'no-input-schema'
: c.renamedHeaderSdkToOrpc && c.renamedHeaderOrpcToSdk
? 'header-vs-headers'
: c.withoutContentTypeSdkToOrpc && c.withoutContentTypeOrpcToSdk
? 'multipart-selection'
: c.multipartSdkToOrpc && c.multipartOrpcToSdk
? 'multipart-selection'
: 'schema-difference'
row.outputCategory =
c.outputSdkToOrpc && c.outputOrpcToSdk
? 'compatible'
: c.normalizedVoidSdkToOrpc && c.normalizedVoidOrpcToSdk
? 'void-vs-undefined'
: c.nonStreamSdkToOrpc && c.nonStreamOrpcToSdk
? 'raw-stream-vs-string'
: c.nonStreamWireSdkToOrpc && c.nonStreamWireOrpcToSdk
? 'raw-stream-and-parsed-defaults'
: c.wireOutputSdkToOrpc && c.wireOutputOrpcToSdk
? 'parsed-vs-wire-output'
: row.traits.jsonBinaryResponse && c.sdkOutputString && c.orpcOutputBlob
? 'json-binary-vs-blob'
: row.traits.opaqueResponse && c.sdkOutputUnknown
? 'undocumented-output'
: 'schema-difference'
}
// Produce real assignability diagnostics for differences that remain after the
// explicit representation checks. These are evidence, not inferred labels.
if (!report.compilerErrors.length) {
const detailLines = [...lines]
for (const [line, { row, name }] of assertions)
detailLines[line - 1] = detailLines[line - 1].replace(
/= (?:true|false);$/,
`= ${report.matched[row].checks[name]};`,
)
const details = new Map()
for (const [i, row] of report.matched.entries()) {
for (const [category, a, b] of [
['input', `NI${i}`, `OI${i}`],
['output', `NO${i}`, `OO${i}`],
['wireOutput', `NO${i}`, `WireOutput<typeof proc${i}>`],
]) {
if (
category === 'wireOutput'
? row.outputCategory !== 'schema-difference'
: row[`${category}Category`] !== 'schema-difference' &&
row[`${category}Category`] !== 'parsed-vs-wire-output'
)
continue
for (const [direction, from, to] of [
['sdkToOrpc', a, b],
['orpcToSdk', b, a],
]) {
detailLines.push(`const detail${i}_${category}_${direction}: ${to} = null! as ${from};`)
details.set(detailLines.length, { row: i, category, direction })
}
}
}
writeFileSync(join(dir, 'check.ts'), detailLines.join('\n'))
const diagnostics = spawnSync(
process.execPath,
[
join(root, 'node_modules/typescript/bin/tsc'),
'--runExternalCode',
'--pretty',
'false',
'-p',
dir,
],
{ cwd: root, encoding: 'utf8', timeout: 180000, maxBuffer: 64 * 1024 * 1024 },
)
assert.ifError(diagnostics.error)
assert(
[0, 2].includes(diagnostics.status),
`Diagnostic compilation failed: ${diagnostics.status}`,
)
for (const block of diagnostics.stdout
.split(/(?=^.*check\.ts\(\d+,\d+\): error TS)/m)
.filter(Boolean)) {
const match = /check\.ts\((\d+),\d+\): error TS(\d+): ([\s\S]*)/.exec(block)
const detail = match && details.get(Number(match[1]))
if (!detail || !['2322', '2741', '2739', '2559'].includes(match[2]))
report.compilerErrors.push({ diagnostic: block })
else
(report.matched[detail.row].diagnostics ??= []).push({
category: detail.category,
direction: detail.direction,
message: match[3].trim(),
})
}
if (diagnostics.stderr.trim()) report.compilerErrors.push({ diagnostic: diagnostics.stderr })
}
report.categories = { input: {}, output: {} }
for (const row of report.matched)
for (const kind of ['input', 'output']) {
const category = row[`${kind}Category`]
report.categories[kind][category] = (report.categories[kind][category] ?? 0) + 1
}
report.compilerMilliseconds = Math.round(performance.now() - started)
report.valid = report.compilerErrors.length === 0
report.summary = {
matched: report.matched.length,
fullyAssignable: report.matched.filter((r) =>
['inputSdkToOrpc', 'inputOrpcToSdk', 'outputSdkToOrpc', 'outputOrpcToSdk'].every(
(k) => r.checks[k],
),
).length,
inputMismatch: report.matched.filter(
(r) => !r.checks.inputSdkToOrpc || !r.checks.inputOrpcToSdk,
).length,
outputMismatch: report.matched.filter(
(r) => !r.checks.outputSdkToOrpc || !r.checks.outputOrpcToSdk,
).length,
unmatchedOpenApi: report.unmatchedOpenApi.length,
unmatchedOrpc: report.unmatchedOrpc.length,
compilerErrors: report.compilerErrors.length,
}
report.summary.topLevelAnyOrNever = report.matched.filter((r) =>
Object.entries(r.checks).some(([k, v]) => /Any$|Never$/.test(k) && v),
).length
report.summary.inputAndOutputMismatch = report.matched.filter(
(r) =>
(!r.checks.inputSdkToOrpc || !r.checks.inputOrpcToSdk) &&
(!r.checks.outputSdkToOrpc || !r.checks.outputOrpcToSdk),
).length
report.coverage = report.documents.map((d) => ({
document: d.name,
total: d.operations,
compared: report.matched.filter((r) => r.document === d.name).length,
}))
const acceptedInputs = new Set(['compatible', 'no-input-schema', 'multipart-selection'])
const acceptedOutputs = new Set([
'compatible',
'parsed-vs-wire-output',
'undocumented-output',
'raw-stream-vs-string',
'raw-stream-and-parsed-defaults',
'json-binary-vs-blob',
])
report.summary.unexplainedDifferences = report.matched.filter(
(row) => !acceptedInputs.has(row.inputCategory) || !acceptedOutputs.has(row.outputCategory),
).length
mkdirSync(resolve(output, '..'), { recursive: true })
writeFileSync(output, `${JSON.stringify(report, null, 2)}\n`)
process.stdout.write(
JSON.stringify(
{
...report.summary,
categories: report.categories,
compilerMilliseconds: report.compilerMilliseconds,
report: output,
},
null,
2,
),
)
assert.equal(
report.compilerErrors.length,
0,
'Unexpected compiler errors invalidate this audit; see report',
)
if (consoleOnly) {
const baselinePath = join(root, 'integration/console-type-differences.json')
const differences = Object.fromEntries(
report.matched
.filter((row) => row.inputCategory !== 'compatible' || row.outputCategory !== 'compatible')
.map((row) => [row.id, [row.inputCategory, row.outputCategory]])
.sort(([a], [b]) => a.localeCompare(b)),
)
if (updateBaseline) writeFileSync(baselinePath, `${JSON.stringify(differences, null, 2)}\n`)
else
assert.deepEqual(
differences,
JSON.parse(readFileSync(baselinePath, 'utf8')),
'Console type differences changed; inspect the report before updating the reviewed baseline',
)
}
if (enforceAlignment) {
assert.equal(report.summary.topLevelAnyOrNever, 0, 'Vacuous types invalidate compatibility')
assert.equal(
report.summary.unexplainedDifferences,
0,
'Unexpected oRPC type differences; see report',
)
assert.equal(report.summary.unmatchedOrpc, 0, 'Every generated procedure must be compared')
if (consoleOnly)
assert.equal(
report.summary.unmatchedOpenApi,
0,
'Every Console operation must have a contract',
)
}
} finally {
rmSync(dir, { recursive: true, force: true })
}
@@ -0,0 +1,76 @@
/* oxlint-disable vitest/no-import-node-test -- Verify the repository editor setup through the native language server. */
import assert from 'node:assert/strict'
import { mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs'
import { join, resolve } from 'node:path'
import { test } from 'node:test'
import { pathToFileURL } from 'node:url'
import { rpcProcess } from '../test/rpc.mjs'
/* oxlint-enable vitest/no-import-node-test */
const root = resolve(import.meta.dirname, '..')
const repo = resolve(root, '../..')
const web = join(repo, 'web')
test('workspace TS 7.1 resolves composed Console completions and request types from backend sources', async () => {
const settings = JSON.parse(readFileSync(join(repo, '.vscode/settings.example.json'), 'utf8'))
assert.equal(settings['js/ts.contentMappers.enabled'], true)
const compiler = join(repo, settings['js/ts.tsdk.path'], 'bin/tsc')
const directory = mkdtempSync(join(web, '.console-editor-'))
const document = join(
repo,
'packages/openapi-content-mapper/examples/repository/console.openapi-source',
)
const source = [
`import { api as consoleClient, query as consoleQuery } from ${JSON.stringify(document)};`,
"const options = consoleQuery.knowledgeFs.spaces.byControlSpaceId.metadata.get.queryOptions({ input: { params: { control_space_id: 'space' } } });",
'consoleClient.enterprise.appDeploy.accessService.',
].join('\n')
writeFileSync(join(directory, 'index.ts'), source)
writeFileSync(
join(directory, 'tsconfig.json'),
JSON.stringify({
extends: '../tsconfig.json',
contentMappers: [
{
package: '@dify/openapi-content-mapper',
extensions: ['.openapi-source'],
options: { sources: [document] },
},
],
include: ['index.ts', '../next-env.d.ts', '../global.d.ts', '../types/**/*.d.ts'],
}),
)
const rpc = rpcProcess(process.execPath, [compiler, '--lsp', '--stdio'], repo, 60000)
const uri = pathToFileURL(join(directory, 'index.ts')).href
try {
await rpc.request('initialize', {
processId: process.pid,
rootUri: pathToFileURL(repo).href,
initializationOptions: { runExternalCode: true },
workspaceFolders: [{ uri: pathToFileURL(repo).href, name: 'dify' }],
capabilities: {
general: { positionEncodings: ['utf-16'] },
textDocument: { hover: { contentFormat: ['plaintext'] } },
},
})
rpc.notify('initialized', {})
rpc.notify('textDocument/didOpen', {
textDocument: { uri, languageId: 'typescript', version: 1, text: source },
})
const completions = await rpc.request('textDocument/completion', {
textDocument: { uri },
position: { line: 2, character: source.split('\n')[2].length },
})
const labels = (completions.items ?? completions).map((item) => item.label)
assert(labels.includes('getEnvironmentApi'), JSON.stringify(labels))
assert(labels.includes('updateEnvironmentApi'))
const position = { line: 1, character: source.split('\n')[1].indexOf('.get.') + 2 }
const hover = await rpc.request('textDocument/hover', { textDocument: { uri }, position })
assert.match(JSON.stringify(hover), /control_space_id/)
await rpc.request('shutdown')
rpc.notify('exit')
} finally {
rpc.close()
rmSync(directory, { recursive: true, force: true })
}
})
@@ -0,0 +1,97 @@
/* oxlint-disable vitest/no-import-node-test, antfu/no-import-dist -- Verify the composed migration surface against the existing public contract. */
import assert from 'node:assert/strict'
import { existsSync } from 'node:fs'
import { test } from 'node:test'
import { consoleRouterContract } from '../../contracts/console.ts'
import {
composeConsoleDocuments,
loadConsoleDocument,
} from '../../contracts/scripts/compose-console-openapi.mjs'
import { describeOperations } from '../dist/operation.js'
import { createRouter } from '../dist/tooling/router.js'
/* oxlint-enable vitest/no-import-node-test, antfu/no-import-dist */
const files = [
'console-openapi.json',
'fastopenapi-console-openapi.json',
'console-client-openapi.json',
].map((name) => new URL(`../../contracts/openapi/${name}`, import.meta.url))
test('every existing Console member retains its name, HTTP method and route', (t) => {
const before = files.map((file) => existsSync(file))
const document = loadConsoleDocument()
assert.deepEqual(loadConsoleDocument(), document, 'In-memory composition must be deterministic')
assert.deepEqual(
files.map((file) => existsSync(file)),
before,
'Export must not create OpenAPI files',
)
const operations = describeOperations(document)
const router = createRouter(operations)
const visited = new Set()
function walk(node, path = []) {
const definition = node['~orpc']
if (!definition) {
for (const [key, child] of Object.entries(node)) walk(child, [...path, key])
return
}
let current = router
for (const member of path.slice(0, -1)) current = current?.children.get(member)
const operation = current?.methods.get(path.at(-1))
assert(operation, `Missing client member: ${path.join('.')}`)
assert.equal(operation.path, definition.route.path, path.join('.'))
assert.equal(operation.method.toUpperCase(), definition.route.method, path.join('.'))
assert(!visited.has(operation), `Two members resolve to the same operation: ${path.join('.')}`)
visited.add(operation)
}
walk(consoleRouterContract)
assert.equal(
visited.size,
operations.size,
'The composed client must not introduce unmatched operations',
)
t.diagnostic(
`${visited.size} Console operations, including Enterprise, App Deploy and FastOpenAPI`,
)
})
test('composition isolates schemas and rejects ambiguous routes and external references', () => {
const source = (path, type) => ({
openapi: '3.1.0',
paths: {
[path]: {
get: {
responses: {
200: {
content: { 'application/json': { schema: { $ref: '#/components/schemas/Value' } } },
},
},
},
},
},
components: { schemas: { Value: { type } } },
})
const composed = composeConsoleDocuments([
{ name: 'a', document: source('/a', 'string') },
{ name: 'b', document: source('/b', 'number') },
])
assert.equal(composed.components.schemas.a_Value.type, 'string')
assert.equal(
composed.paths['/b'].get.responses[200].content['application/json'].schema.$ref,
'#/components/schemas/b_Value',
)
assert.throws(
() =>
composeConsoleDocuments([
{ name: 'a', document: source('/a', 'string') },
{ name: 'b', document: source('/a', 'number') },
]),
/Duplicate Console path/,
)
const external = source('/a', 'string')
external.components.schemas.Value = { $ref: 'external.json#/Value' }
assert.throws(
() => composeConsoleDocuments([{ name: 'a', document: external }]),
/Unsupported reference/,
)
})
@@ -0,0 +1,704 @@
{
"console GET /account/delete/verify": ["no-input-schema", "compatible"],
"console GET /account/education": ["no-input-schema", "compatible"],
"console GET /account/education/verify": ["no-input-schema", "compatible"],
"console GET /account/integrates": ["no-input-schema", "compatible"],
"console GET /account/profile": ["no-input-schema", "compatible"],
"console GET /agent": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/api-access": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/api-keys": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/build-draft": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/chat-messages": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/composer": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/composer/candidates": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/config/files": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/config/manifest": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/config/skills": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/config/skills/{name}/files/content": [
"compatible",
"undocumented-output"
],
"console GET /agent/{agent_id}/config/skills/{name}/inspect": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /agent/{agent_id}/logs/{conversation_id}/messages": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /agent/{agent_id}/messages/{message_id}": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/sandbox/files": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/trace": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/{agent_id}/versions/{version_id}": ["compatible", "parsed-vs-wire-output"],
"console GET /agent/invite-options": ["compatible", "parsed-vs-wire-output"],
"console GET /api-based-extension": ["no-input-schema", "compatible"],
"console GET /api-key-auth/data-source": ["no-input-schema", "compatible"],
"console GET /app-dsl-version": ["no-input-schema", "compatible"],
"console GET /apps": ["compatible", "parsed-vs-wire-output"],
"console GET /apps/{app_id}/agent/config/files": ["compatible", "parsed-vs-wire-output"],
"console GET /apps/{app_id}/agent/config/manifest": ["compatible", "parsed-vs-wire-output"],
"console GET /apps/{app_id}/agent/config/skills": ["compatible", "parsed-vs-wire-output"],
"console GET /apps/{app_id}/agent/config/skills/{name}/files/content": [
"compatible",
"undocumented-output"
],
"console GET /apps/{app_id}/agent/config/skills/{name}/inspect": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /apps/{app_id}/annotation-reply/{action}/status/{job_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /apps/{app_id}/annotations/batch-import-status/{job_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /apps/{app_id}/chat-messages": ["compatible", "parsed-vs-wire-output"],
"console GET /apps/{app_id}/messages/{message_id}": ["compatible", "parsed-vs-wire-output"],
"console GET /apps/{app_id}/trace": ["compatible", "parsed-vs-wire-output"],
"console GET /apps/{app_id}/workflow-runs/{workflow_run_id}/agent-nodes/{node_id}/sandbox/files": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer/candidates": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /apps/{app_id}/workflows/draft/runs/{run_id}/node-outputs": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /apps/{app_id}/workflows/draft/runs/{run_id}/node-outputs/{node_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /apps/{app_id}/workflows/published/runs/{run_id}/node-outputs": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /apps/{app_id}/workflows/published/runs/{run_id}/node-outputs/{node_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /apps/{resource_id}/api-keys": ["compatible", "parsed-vs-wire-output"],
"console GET /apps/starred": ["compatible", "parsed-vs-wire-output"],
"console GET /auth/plugin/datasource/default-list": ["no-input-schema", "parsed-vs-wire-output"],
"console GET /auth/plugin/datasource/list": ["no-input-schema", "parsed-vs-wire-output"],
"console GET /billing/invoices": ["no-input-schema", "compatible"],
"console GET /data-source/integrates": ["no-input-schema", "compatible"],
"console GET /datasets/{dataset_id}/documents": ["compatible", "parsed-vs-wire-output"],
"console GET /datasets/{dataset_id}/documents/{document_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /datasets/{dataset_id}/documents/{document_id}/summary-status": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /datasets/{dataset_id}/metadata": ["compatible", "parsed-vs-wire-output"],
"console GET /datasets/{resource_id}/api-keys": ["compatible", "parsed-vs-wire-output"],
"console GET /datasets/api-base-info": ["no-input-schema", "compatible"],
"console GET /datasets/api-keys": ["no-input-schema", "parsed-vs-wire-output"],
"console GET /datasets/knowledge-fs-upgrade-jobs": ["no-input-schema", "compatible"],
"console GET /datasets/metadata/built-in": ["no-input-schema", "compatible"],
"console GET /datasets/process-rule": ["compatible", "parsed-vs-wire-output"],
"console GET /datasets/retrieval-setting": ["no-input-schema", "compatible"],
"console GET /enterprise/sso/oauth2/login": ["no-input-schema", "compatible"],
"console GET /enterprise/sso/oidc/login": ["no-input-schema", "compatible"],
"console GET /enterprise/sso/saml/login": ["no-input-schema", "compatible"],
"console GET /features": ["no-input-schema", "compatible"],
"console GET /features/vector-space": ["no-input-schema", "parsed-vs-wire-output"],
"console GET /files/support-type": ["no-input-schema", "compatible"],
"console GET /files/upload": ["no-input-schema", "compatible"],
"console GET /init": ["no-input-schema", "compatible"],
"console GET /installed-apps/{installed_app_id}/messages": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /installed-apps/{installed_app_id}/messages/{message_id}/more-like-this": [
"compatible",
"undocumented-output"
],
"console GET /knowledge-fs/.well-known/jwks.json": ["no-input-schema", "compatible"],
"console GET /knowledge-fs/features": ["no-input-schema", "compatible"],
"console GET /knowledge-fs/research-tasks/{task_id}/events": [
"compatible",
"raw-stream-vs-string"
],
"console GET /knowledge-fs/spaces": ["compatible", "parsed-vs-wire-output"],
"console GET /knowledge-fs/spaces/{control_space_id}": ["compatible", "parsed-vs-wire-output"],
"console GET /knowledge-fs/spaces/{control_space_id}/documents/{document_id}/revisions/{revision}/chunks": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /knowledge-fs/spaces/{control_space_id}/documents/{document_id}/revisions/{revision}/chunks/{chunk_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /knowledge-fs/spaces/{control_space_id}/golden-questions": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /knowledge-fs/spaces/{control_space_id}/logical-documents": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /knowledge-fs/spaces/{control_space_id}/logical-documents/{document_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /knowledge-fs/spaces/{control_space_id}/quality/bad-cases": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /knowledge-fs/spaces/{control_space_id}/quality/bad-cases/{bad_case_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /knowledge-fs/spaces/{control_space_id}/settings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /knowledge-fs/spaces/{control_space_id}/tags": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /knowledge-fs/spaces/{control_space_id}/traces": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /knowledge-fs/spaces/{control_space_id}/traces/{trace_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /onboarding/step-by-step-tour/state": ["no-input-schema", "parsed-vs-wire-output"],
"console GET /ping": ["no-input-schema", "compatible"],
"console GET /rag/pipelines/datasource-plugins": ["no-input-schema", "parsed-vs-wire-output"],
"console GET /rag/pipelines/recommended-plugins": ["compatible", "parsed-vs-wire-output"],
"console GET /setup": ["no-input-schema", "compatible"],
"console GET /snippets/{snippet_id}/workflows/draft/nodes/{node_id}/agent-composer": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /snippets/{snippet_id}/workflows/draft/nodes/{node_id}/agent-composer/candidates": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /spec/schema-definitions": ["no-input-schema", "compatible"],
"console GET /system-features": ["no-input-schema", "compatible"],
"console GET /system-features/license": ["no-input-schema", "compatible"],
"console GET /trial-apps/{app_id}/agent-composer": ["compatible", "parsed-vs-wire-output"],
"console GET /trial-apps/{app_id}/agent/config/files": ["compatible", "parsed-vs-wire-output"],
"console GET /trial-apps/{app_id}/agent/config/skills": ["compatible", "parsed-vs-wire-output"],
"console GET /trial-apps/{app_id}/agent/config/skills/{name}/inspect": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /trial-models": ["no-input-schema", "compatible"],
"console GET /workflow-run-archives": ["no-input-schema", "compatible"],
"console GET /workspaces": ["no-input-schema", "compatible"],
"console GET /workspaces/{tenant_id}/model-providers/{provider}/{icon_type}/{lang}": [
"compatible",
"undocumented-output"
],
"console GET /workspaces/current/agent-provider/{provider_name}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/agent-providers": ["no-input-schema", "parsed-vs-wire-output"],
"console GET /workspaces/current/dataset-operators": ["no-input-schema", "compatible"],
"console GET /workspaces/current/default-model": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/endpoints/list": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/endpoints/list/plugin": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/model-providers": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/model-providers/{provider}/models": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/model-providers/{provider}/models/parameter-rules": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/model-providers/credits": ["no-input-schema", "compatible"],
"console GET /workspaces/current/model-providers/summary": ["no-input-schema", "compatible"],
"console GET /workspaces/current/models/model-types/{model_type}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/network-access-groups": [
"no-input-schema",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/network-access-groups/{group_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/network-access-groups/current-ip": [
"no-input-schema",
"compatible"
],
"console GET /workspaces/current/permission": ["no-input-schema", "compatible"],
"console GET /workspaces/current/plugin/{category}/list": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/plugin/debugging-key": ["no-input-schema", "compatible"],
"console GET /workspaces/current/plugin/fetch-manifest": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/plugin/list": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/plugin/marketplace/pkg": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/plugin/permission/fetch": ["no-input-schema", "compatible"],
"console GET /workspaces/current/rbac/access-policies": [
"no-input-schema",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/access-policies/{policy_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/agents/{agent_id}/access-policies/{policy_id}/member-bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/agents/{agent_id}/access-policies/{policy_id}/role-bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/agents/{agent_id}/access-policy": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/agents/{agent_id}/user-access-policies": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/apps/{app_id}/access-policies/{policy_id}/member-bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/apps/{app_id}/access-policies/{policy_id}/role-bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/apps/{app_id}/access-policy": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/apps/{app_id}/user-access-policies": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/datasets/{dataset_id}/access-policies/{policy_id}/member-bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/datasets/{dataset_id}/access-policies/{policy_id}/role-bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/datasets/{dataset_id}/access-policy": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/datasets/{dataset_id}/user-access-policies": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/members/{member_id}/rbac-roles": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/my-permissions": ["no-input-schema", "compatible"],
"console GET /workspaces/current/rbac/role-permissions/catalog": [
"no-input-schema",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/role-permissions/catalog/agent": [
"no-input-schema",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/role-permissions/catalog/app": [
"no-input-schema",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/role-permissions/catalog/dataset": [
"no-input-schema",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/roles": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/rbac/roles/{role_id}": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/rbac/roles/{role_id}/members": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/workspace/agents/access-policies/{policy_id}/member-bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/workspace/agents/access-policies/{policy_id}/role-bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/workspace/agents/access-policy": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/workspace/apps/access-policies/{policy_id}/member-bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/workspace/apps/access-policies/{policy_id}/role-bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/workspace/apps/access-policy": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/workspace/datasets/access-policies/{policy_id}/member-bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/workspace/datasets/access-policies/{policy_id}/role-bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/rbac/workspace/datasets/access-policy": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/skills": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/skills/{skill_id}": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/skills/{skill_id}/export": ["compatible", "undocumented-output"],
"console GET /workspaces/current/skills/{skill_id}/versions": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/skills/{skill_id}/versions/{version_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/skills/tags": ["no-input-schema", "compatible"],
"console GET /workspaces/current/summary": ["no-input-schema", "compatible"],
"console GET /workspaces/current/tool-labels": ["no-input-schema", "compatible"],
"console GET /workspaces/current/tool-provider/api/get": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/tool-provider/api/tools": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/tool-provider/builtin/{provider}/credential/info": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/tool-provider/builtin/{provider}/credential/schema/{credential_type}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/tool-provider/builtin/{provider}/credentials": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/tool-provider/builtin/{provider}/icon": [
"compatible",
"undocumented-output"
],
"console GET /workspaces/current/tool-provider/builtin/{provider}/info": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/tool-provider/builtin/{provider}/oauth/client-schema": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/tool-provider/builtin/{provider}/oauth/custom-client": [
"compatible",
"undocumented-output"
],
"console GET /workspaces/current/tool-provider/builtin/{provider}/tools": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/tool-provider/mcp/tools/{provider_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/tool-provider/mcp/update/{provider_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/tool-provider/workflow/get": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/tool-provider/workflow/tools": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/tool-providers": ["compatible", "parsed-vs-wire-output"],
"console GET /workspaces/current/tools/api": ["no-input-schema", "parsed-vs-wire-output"],
"console GET /workspaces/current/tools/builtin": ["no-input-schema", "parsed-vs-wire-output"],
"console GET /workspaces/current/tools/mcp": ["no-input-schema", "parsed-vs-wire-output"],
"console GET /workspaces/current/tools/workflow": ["no-input-schema", "parsed-vs-wire-output"],
"console GET /workspaces/current/trigger-provider/{provider}/icon": [
"compatible",
"undocumented-output"
],
"console GET /workspaces/current/trigger-provider/{provider}/info": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/trigger-provider/{provider}/oauth/client": [
"compatible",
"parsed-vs-wire-output"
],
"console GET /workspaces/current/triggers": ["no-input-schema", "parsed-vs-wire-output"],
"console GET /workspaces/custom-config": ["no-input-schema", "compatible"],
"console PATCH /knowledge-fs/spaces/{control_space_id}": ["compatible", "parsed-vs-wire-output"],
"console PATCH /knowledge-fs/spaces/{control_space_id}/documents/{document_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console PATCH /knowledge-fs/spaces/{control_space_id}/golden-questions/{question_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console PATCH /knowledge-fs/spaces/{control_space_id}/logical-documents": [
"compatible",
"parsed-vs-wire-output"
],
"console PATCH /knowledge-fs/spaces/{control_space_id}/logical-documents/{document_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console PATCH /knowledge-fs/spaces/{control_space_id}/quality/bad-cases/{bad_case_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console PATCH /knowledge-fs/spaces/{control_space_id}/settings": [
"compatible",
"parsed-vs-wire-output"
],
"console PATCH /onboarding/step-by-step-tour/state": ["compatible", "parsed-vs-wire-output"],
"console PATCH /workspaces/current/skills/{skill_id}": ["compatible", "parsed-vs-wire-output"],
"console PATCH /workspaces/current/skills/{skill_id}/files": [
"compatible",
"parsed-vs-wire-output"
],
"console PATCH /workspaces/current/skills/{skill_id}/versions/{version_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /agent": ["compatible", "parsed-vs-wire-output"],
"console POST /agent/{agent_id}/api-enable": ["compatible", "parsed-vs-wire-output"],
"console POST /agent/{agent_id}/api-keys": ["compatible", "parsed-vs-wire-output"],
"console POST /agent/{agent_id}/build-draft/checkout": ["compatible", "parsed-vs-wire-output"],
"console POST /agent/{agent_id}/config/files": ["compatible", "parsed-vs-wire-output"],
"console POST /agent/{agent_id}/config/skills/upload": ["compatible", "parsed-vs-wire-output"],
"console POST /agent/{agent_id}/copy": ["compatible", "parsed-vs-wire-output"],
"console POST /agent/{agent_id}/debug-conversation/refresh": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /agent/{agent_id}/trace": ["compatible", "parsed-vs-wire-output"],
"console POST /apps/{app_id}/advanced-chat/workflows/draft/human-input/nodes/{node_id}/form/preview": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /apps/{app_id}/agent/config/files": ["compatible", "parsed-vs-wire-output"],
"console POST /apps/{app_id}/agent/config/skills/upload": ["compatible", "parsed-vs-wire-output"],
"console POST /apps/{app_id}/completion-messages": ["compatible", "undocumented-output"],
"console POST /apps/{app_id}/copy": ["compatible", "parsed-vs-wire-output"],
"console POST /apps/{app_id}/text-to-audio": ["compatible", "undocumented-output"],
"console POST /apps/{app_id}/workflows/draft/human-input/nodes/{node_id}/form/preview": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer/copy-from-roster": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer/save-to-roster": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /apps/{resource_id}/api-keys": ["compatible", "parsed-vs-wire-output"],
"console POST /apps/imports": ["multipart-selection", "parsed-vs-wire-output"],
"console POST /apps/imports/{import_id}/confirm": ["compatible", "parsed-vs-wire-output"],
"console POST /datasets/{dataset_id}/documents/download-zip": [
"compatible",
"undocumented-output"
],
"console POST /datasets/{dataset_id}/knowledge-fs-upgrades/{job_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /datasets/{resource_id}/api-keys": ["compatible", "parsed-vs-wire-output"],
"console POST /datasets/api-keys": ["compatible", "parsed-vs-wire-output"],
"console POST /installed-apps/{installed_app_id}/chat-messages": [
"compatible",
"undocumented-output"
],
"console POST /installed-apps/{installed_app_id}/completion-messages": [
"compatible",
"undocumented-output"
],
"console POST /installed-apps/{installed_app_id}/workflows/run": [
"compatible",
"undocumented-output"
],
"console POST /knowledge-fs/query-stream": ["compatible", "raw-stream-vs-string"],
"console POST /knowledge-fs/source-provider-preview/jobs": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /knowledge-fs/spaces/{control_space_id}/documents": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /knowledge-fs/spaces/{control_space_id}/golden-questions": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /knowledge-fs/spaces/{control_space_id}/quality/bad-cases": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /logout": ["no-input-schema", "compatible"],
"console POST /rag/pipeline/dataset": ["compatible", "parsed-vs-wire-output"],
"console POST /rag/pipeline/empty-dataset": ["no-input-schema", "compatible"],
"console POST /rag/pipelines/{pipeline_id}/workflows/published/datasource/nodes/{node_id}/preview": [
"compatible",
"undocumented-output"
],
"console POST /rag/pipelines/{pipeline_id}/workflows/published/run": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /rag/pipelines/imports": ["compatible", "parsed-vs-wire-output"],
"console POST /rag/pipelines/imports/{import_id}/confirm": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /refresh-token": ["no-input-schema", "compatible"],
"console POST /snippets/{snippet_id}/workflows/draft/nodes/{node_id}/agent-composer/copy-from-roster": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /snippets/{snippet_id}/workflows/draft/nodes/{node_id}/agent-composer/save-to-roster": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /trial-apps/{app_id}/chat-messages": ["compatible", "undocumented-output"],
"console POST /trial-apps/{app_id}/completion-messages": ["compatible", "undocumented-output"],
"console POST /trial-apps/{app_id}/workflows/run": ["compatible", "undocumented-output"],
"console POST /workflow-generate": ["compatible", "parsed-vs-wire-output"],
"console POST /workflow-generate/stream": ["compatible", "parsed-vs-wire-output"],
"console POST /workspaces/current/network-access-groups": ["compatible", "parsed-vs-wire-output"],
"console POST /workspaces/current/plugin/list/installations/ids": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /workspaces/current/plugin/tasks/delete_all": ["no-input-schema", "compatible"],
"console POST /workspaces/current/plugin/upload/bundle": [
"no-input-schema",
"parsed-vs-wire-output"
],
"console POST /workspaces/current/plugin/upload/github": ["compatible", "parsed-vs-wire-output"],
"console POST /workspaces/current/plugin/upload/pkg": ["compatible", "parsed-vs-wire-output"],
"console POST /workspaces/current/rbac/access-policies": ["compatible", "parsed-vs-wire-output"],
"console POST /workspaces/current/rbac/access-policies/{policy_id}/copy": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /workspaces/current/rbac/roles": ["compatible", "parsed-vs-wire-output"],
"console POST /workspaces/current/rbac/roles/{role_id}/copy": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /workspaces/current/skills": ["compatible", "parsed-vs-wire-output"],
"console POST /workspaces/current/skills/{skill_id}/assist/messages": [
"compatible",
"undocumented-output"
],
"console POST /workspaces/current/skills/{skill_id}/duplicate": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /workspaces/current/skills/{skill_id}/publish": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /workspaces/current/skills/{skill_id}/restore": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /workspaces/current/skills/import": ["compatible", "parsed-vs-wire-output"],
"console POST /workspaces/current/tool-provider/api/schema": [
"compatible",
"parsed-vs-wire-output"
],
"console POST /workspaces/current/tool-provider/mcp": ["compatible", "parsed-vs-wire-output"],
"console PUT /agent/{agent_id}": ["compatible", "parsed-vs-wire-output"],
"console PUT /agent/{agent_id}/build-draft": ["compatible", "parsed-vs-wire-output"],
"console PUT /agent/{agent_id}/composer": ["compatible", "parsed-vs-wire-output"],
"console PUT /apps/{app_id}/workflows/draft/nodes/{node_id}/agent-composer": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /knowledge-fs/spaces/{control_space_id}/tags": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /snippets/{snippet_id}/workflows/draft/nodes/{node_id}/agent-composer": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /workspaces/current/network-access-groups/{group_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /workspaces/current/rbac/access-policies/{policy_id}": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /workspaces/current/rbac/access-policy-bindings/{binding_id}/lock": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /workspaces/current/rbac/access-policy-bindings/{binding_id}/unlock": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /workspaces/current/rbac/agents/{agent_id}/users/{target_account_id}/access-policies": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /workspaces/current/rbac/apps/{app_id}/users/{target_account_id}/access-policies": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /workspaces/current/rbac/datasets/{dataset_id}/users/{target_account_id}/access-policies": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /workspaces/current/rbac/members/{member_id}/rbac-roles": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /workspaces/current/rbac/roles/{role_id}": ["compatible", "parsed-vs-wire-output"],
"console PUT /workspaces/current/rbac/workspace/agents/access-policies/{policy_id}/bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /workspaces/current/rbac/workspace/apps/access-policies/{policy_id}/bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /workspaces/current/rbac/workspace/datasets/access-policies/{policy_id}/bindings": [
"compatible",
"parsed-vs-wire-output"
],
"console PUT /workspaces/current/skills/{skill_id}/files": ["compatible", "parsed-vs-wire-output"]
}
@@ -0,0 +1,125 @@
/* oxlint-disable vitest/no-import-node-test, antfu/no-import-dist -- Verify standalone Console imports with the built mapper and bundler. */
import assert from 'node:assert/strict'
import { Buffer } from 'node:buffer'
import { mkdtemp, rm, writeFile } from 'node:fs/promises'
import { join, resolve } from 'node:path'
import { test } from 'node:test'
import { gzipSync } from 'node:zlib'
import { build } from 'vite'
import { loadConsoleDocument } from '../../contracts/scripts/compose-console-openapi.mjs'
import { openapi } from '../dist/tooling/vite.js'
/* oxlint-enable vitest/no-import-node-test, antfu/no-import-dist */
const repository = resolve(import.meta.dirname, '../../..')
test('a standalone metadata consumer prunes every unused console operation', async (t) => {
const directory = await mkdtemp(join(import.meta.dirname, '.console-bundle-'))
try {
const spec = loadConsoleDocument()
const path = '/knowledge-fs/spaces/{control_space_id}/metadata'
const fullSpec = join(directory, 'console.openapi')
const entry = join(directory, 'consumer.ts')
await writeFile(fullSpec, JSON.stringify(spec))
await writeFile(
entry,
`import { api, query } from './console.openapi';
export const loadMetadata = (input) => api.knowledgeFs.spaces.byControlSpaceId.metadata.get(input);
export const metadataOptions = (input) => query.knowledgeFs.spaces.byControlSpaceId.metadata.get.queryOptions({ input });
`,
)
const reduced = join(directory, 'reduced.openapi')
await writeFile(
reduced,
JSON.stringify({
...spec,
paths: {
[path]: { ...spec.paths[path], post: undefined, patch: undefined, delete: undefined },
},
}),
)
for (const document of [fullSpec, reduced]) {
await writeFile(
`${document}.errors.ts`,
`export * from ${JSON.stringify(join(repository, 'packages/contracts/generated/api/console/errors.gen.ts'))};`,
)
await writeFile(
`${document}.queries.ts`,
`const defaults = { queryOptions: { retry: false, staleTime: 30000 } };
export { defaults as 'GET ${path}' };`,
)
}
async function bundle(useReduced) {
const result = await build({
configFile: false,
root: directory,
logLevel: 'silent',
plugins: [
...(useReduced
? [
{
name: 'one-operation-control',
enforce: 'pre',
resolveId(source) {
if (source === './console.openapi') return reduced
},
},
]
: []),
openapi(),
],
build: {
write: false,
minify: true,
lib: { entry, formats: ['es'] },
rollupOptions: {
output: { chunkFileNames: 'error-[hash].js' },
},
},
})
if (!useReduced) {
const chunks = (Array.isArray(result) ? result : [result])
.flatMap((item) => item.output)
.filter((file) => file.type === 'chunk')
const initial = chunks
.filter((file) => file.isEntry)
.map((file) => file.code)
.join('\n')
const deferred = chunks
.filter((file) => !file.isEntry)
.map((file) => file.code)
.join('\n')
assert(
!initial.includes('knowledge_fs_access_denied'),
'Validators must load only when a request fails',
)
t.diagnostic(
`Metadata entry: ${gzipSync(initial).length} gzip; deferred error validation: ${gzipSync(deferred).length} gzip.`,
)
}
return (Array.isArray(result) ? result : [result])
.flatMap((item) => item.output)
.filter((item) => item.type === 'chunk')
.map((item) => item.code)
.join('\n')
}
const full = await bundle(false)
const single = await bundle(true)
assert.equal(full.replace(/^\/\/.*$/gm, ''), single.replace(/^\/\/.*$/gm, ''))
assert(full.includes('/knowledge-fs/spaces/'))
for (const unused of [
'/files/upload',
'/datasets',
'/chat-messages',
'parseDocument',
'draft_workflow_not_sync',
'environment_deployments',
'zKnowledgeFsSpaceResponse',
])
assert(!full.includes(unused), `Unused code retained: ${unused}`)
t.diagnostic(
`Standalone metadata consumer: ${Buffer.byteLength(full)} bytes JS, ${gzipSync(full).length} gzip, including the SDK transport.`,
)
} finally {
await rm(directory, { recursive: true, force: true })
}
})
@@ -0,0 +1,193 @@
import assert from 'node:assert/strict'
import { spawnSync } from 'node:child_process'
import { mkdir, mkdtemp, readdir, readFile, rm, symlink, writeFile } from 'node:fs/promises'
import { join, relative, resolve } from 'node:path'
import { test } from 'node:test'
import { loadConsoleDocument } from '../../contracts/scripts/compose-console-openapi.mjs'
const repository = resolve(import.meta.dirname, '../../..')
const web = join(repository, 'web')
const next = join(web, 'node_modules/next/dist/bin/next')
async function javascript(directory) {
const entries = await readdir(directory, { withFileTypes: true })
return (
await Promise.all(
entries.map(async (entry) => {
const file = join(directory, entry.name)
if (entry.isDirectory()) return javascript(file)
return entry.name.endsWith('.js') ? readFile(file, 'utf8') : ''
}),
)
).join('\n')
}
for (const bundler of ['turbopack', 'webpack']) {
test(`Next ${bundler}: Console and Marketplace imports keep separate transports and prune unused operations`, async () => {
const consoleSpec = loadConsoleDocument()
const alias = 'enterprise.access.getMetadata'
consoleSpec.paths['/knowledge-fs/spaces/{control_space_id}/metadata'].get['x-client-path'] =
alias.split('.')
const dir = await mkdtemp(join(web, '.openapi-next-'))
// Match production: contracts owns the document but only Web depends on the SDK.
const specDir = await mkdtemp(join(repository, 'packages/contracts/.openapi-next-'))
try {
await mkdir(join(dir, 'app'))
await writeFile(join(dir, 'package.json'), JSON.stringify({ private: true, type: 'module' }))
await writeFile(
join(dir, 'next.config.mjs'),
`
const loader = { loader: '@dify/openapi-content-mapper/loader', options: { runtime: ${JSON.stringify(relative(specDir, join(dir, 'runtime.js')))}, sidecars: ${JSON.stringify(relative(specDir, join(dir, 'spec.openapi')))} } };
const marketplaceLoader = { loader: '@dify/openapi-content-mapper/loader', options: { runtime: ${JSON.stringify(relative(specDir, join(dir, 'marketplace-runtime.js')))}, sidecars: ${JSON.stringify(relative(specDir, join(dir, 'marketplace.openapi')))} } };
const namespaceLoader = { loader: '@dify/openapi-content-mapper/loader' };
export default {
experimental: { cpus: 1, extensionAlias: { '.js': ['.ts', '.js'] } },
turbopack: { root: ${JSON.stringify(repository)}, rules: { '*console-spec.openapi-source': { loaders: [loader], as: '*.js' }, '*marketplace-spec.json': { loaders: [marketplaceLoader], as: '*.js' }, '*openapi-namespace.js': { loaders: [namespaceLoader], as: '*.js' } } },
webpack(config) { config.module.rules.push({ test: /console-spec\\.openapi-source$/, type: 'javascript/auto', use: [loader] }, { test: /marketplace-spec\\.json$/, type: 'javascript/auto', use: [marketplaceLoader] }, { test: /openapi-namespace\\.js$/, type: 'javascript/auto', use: [namespaceLoader] }); return config; },
};
`,
)
await writeFile(
join(specDir, 'console-export.mjs'),
`process.stdout.write(${JSON.stringify(
JSON.stringify({
...consoleSpec,
info: { title: 'SCHEMA_METADATA_MUST_DISAPPEAR', version: '1' },
paths: {
...consoleSpec.paths,
'/UNUSED_ENDPOINT_MUST_DISAPPEAR': {
get: { responses: { 200: { description: 'OK' } } },
},
},
}),
)});`,
)
await writeFile(
join(specDir, 'console-spec.openapi-source'),
JSON.stringify({ command: ['node', 'console-export.mjs'], inputs: ['console-export.mjs'] }),
)
await symlink(join(specDir, 'console-spec.openapi-source'), join(dir, 'spec.openapi'))
await writeFile(
join(specDir, 'marketplace-spec.json'),
JSON.stringify({
openapi: '3.1.0',
info: { title: 'Independent document', version: '1' },
paths: {
'/templates/{templateId}': {
get: {
'x-client-path': ['templateDetail'],
parameters: [
{ name: 'templateId', in: 'path', required: true, schema: { type: 'string' } },
],
responses: { 200: { description: 'OK' } },
},
},
'/template-collections': { get: { responses: { 200: { description: 'Unused' } } } },
},
}),
)
await symlink(join(specDir, 'marketplace-spec.json'), join(dir, 'marketplace.openapi'))
await writeFile(
join(dir, 'marketplace.openapi.queries.ts'),
"const policy = { queryOptions: { staleTime: 3131 } }; export { policy as 'GET /templates/{templateId}' };",
)
await writeFile(
join(dir, 'marketplace-runtime.js'),
`
import { createClient } from '@dify/openapi-content-mapper';
export default { queryKeyPrefix: ['marketplace'], createClient: () => createClient({ baseUrl: 'https://marketplace.test', fetch: async url => Response.json({ value: String(url) }) }) };
`,
)
const policy = `const selected = { queryOptions: { staleTime: 4242 } }; const unused = { queryOptions: { meta: { marker: 'UNUSED_POLICY_MUST_DISAPPEAR' } } }; export { selected as 'GET /knowledge-fs/spaces/{control_space_id}/metadata', unused as 'GET /UNUSED_ENDPOINT_MUST_DISAPPEAR' };`
const errors = `const selected = { CONFLICT: { status: 409 } }; const unused = { UNUSED: { status: 400, message: 'UNUSED_ERROR_MUST_DISAPPEAR' } }; export { selected as 'GET /knowledge-fs/spaces/{control_space_id}/metadata', unused as 'GET /UNUSED_ENDPOINT_MUST_DISAPPEAR' };`
await writeFile(
join(dir, 'spec.openapi.queries.ts'),
`export * from ${JSON.stringify(bundler === 'webpack' ? './policies.js' : './policies.ts')};`,
)
await writeFile(join(dir, 'policies.ts'), policy)
await writeFile(
join(dir, 'spec.openapi.errors.ts'),
`export * from ${JSON.stringify(bundler === 'webpack' ? './errors.js' : './errors.ts')};`,
)
await writeFile(join(dir, 'errors.ts'), errors)
await writeFile(
join(dir, 'runtime.js'),
`
import { createClient } from '@dify/openapi-content-mapper';
export default {
queryKeyPrefix: ['bound'],
createClient: ({ context }) => createClient({ baseUrl: 'https://bound.test', fetch: async url => context.user === 'conflict' ? Response.json({ code: 'CONFLICT' }, { status: 409 }) : Response.json({ value: String(url) + ':' + context.user }) }),
};
`,
)
await writeFile(
join(dir, 'app/layout.jsx'),
'export default function Layout({ children }) { return <html><body>{children}</body></html> }',
)
await writeFile(
join(dir, 'app/button.jsx'),
`
'use client';
import { api, query } from '../spec.openapi';
import { api as marketplace, query as marketplaceQuery } from '../marketplace.openapi';
export default function Button() {
return <><button onClick={() => marketplace.templateDetail({ params: { templateId: 'template-1' } })}>{JSON.stringify(marketplaceQuery.templateDetail.key())}</button><button onClick={() => api.${alias}({ params: { control_space_id: 'space-1' } }, { context: { user: 'client' } })}>{JSON.stringify(query.${alias}.key())}</button></>;
}
`,
)
await writeFile(
join(dir, 'app/page.jsx'),
`
import { api, query } from '../spec.openapi';
import { api as marketplace, query as marketplaceQuery } from '../marketplace.openapi';
import Button from './button';
export default async function Page() {
const market = await marketplace.templateDetail({ params: { templateId: 'template-1' } });
const marketOptions = marketplaceQuery.templateDetail.queryOptions({ input: { params: { templateId: 'template-1' } } });
const response = await api.${alias}({ params: { control_space_id: 'space-1' } }, { context: { user: 'server' } });
const defined = await api.${alias}({ params: { control_space_id: 'space-1' } }, { context: { user: 'conflict' } }).catch(error => error.defined);
const options = query.${alias}.queryOptions({ input: { params: { control_space_id: 'space-1' } } });
return <><p>{market.value};market-stale:{marketOptions.staleTime}</p><p>{response.value}</p><p>defined-error:{String(defined)};stale:{options.staleTime}</p><Button /></>;
}
`,
)
const result = spawnSync(process.execPath, [next, 'build', `--${bundler}`], {
cwd: dir,
env: {
...process.env,
NEXT_TELEMETRY_DISABLED: '1',
NODE_OPTIONS: '--max-old-space-size=1024',
RAYON_NUM_THREADS: '1',
},
encoding: 'utf8',
timeout: 120_000,
killSignal: 'SIGKILL',
maxBuffer: 4 * 1024 * 1024,
})
assert.equal(result.status, 0, `${result.error ?? ''}\n${result.stdout}\n${result.stderr}`)
const html = await readFile(join(dir, '.next/server/app/index.html'), 'utf8')
assert(html.includes('https://bound.test/knowledge-fs/spaces/space-1/metadata:server'))
assert(html.includes('bound'))
assert(html.replaceAll(/<!--.*?-->/g, '').includes('defined-error:true;stale:4242'))
assert(html.includes('4242'))
assert(
html
.replaceAll(/<!--.*?-->/g, '')
.includes('https://marketplace.test/templates/template-1;market-stale:3131'),
)
assert(html.includes('marketplace'))
const client = await javascript(join(dir, '.next/static/chunks'))
assert(client.includes('/knowledge-fs/spaces/'))
assert(!client.includes('/datasets'))
assert(!client.includes('/template-collections'))
assert(!client.includes('UNUSED_ENDPOINT_MUST_DISAPPEAR'))
assert(!client.includes('SCHEMA_METADATA_MUST_DISAPPEAR'))
assert(!client.includes('UNUSED_POLICY_MUST_DISAPPEAR'))
assert(!client.includes('UNUSED_ERROR_MUST_DISAPPEAR'))
} finally {
await rm(dir, { recursive: true, force: true })
await rm(specDir, { recursive: true, force: true })
}
})
}
@@ -0,0 +1,46 @@
/* oxlint-disable vitest/no-import-node-test -- Compare every generated error map with the current Console contracts. */
import assert from 'node:assert/strict'
import { test } from 'node:test'
import { consoleRouterContract } from '../../contracts/console.ts'
import * as maps from '../../contracts/generated/api/console/errors.gen.ts'
/* oxlint-enable vitest/no-import-node-test */
test('standalone error maps preserve every Console status, code and validated payload', async (t) => {
let operations = 0
let cases = 0
async function walk(node) {
const definition = node?.['~orpc']
if (!definition) {
for (const child of Object.values(node)) await walk(child)
return
}
if (!Object.keys(definition.errorMap).length) return
const key = `${definition.route.method} ${definition.route.path}`
const actual = maps[key]
assert(actual, `Missing ${key}`)
assert.deepEqual(Object.keys(actual), Object.keys(definition.errorMap))
operations++
for (const [code, expected] of Object.entries(definition.errorMap)) {
assert.equal(actual[code].status, expected.status)
assert.equal(actual[code].message, expected.message)
assert.equal(!!actual[code].data, !!expected.data)
if (!expected.data) continue
for (const value of [
{ code, message: 'message', status: expected.status, extra: 'must be stripped' },
{ code, message: 'message', status: expected.status, details: { value: [1, null] } },
{ code: 'unknown', message: 1, status: 'invalid' },
]) {
assert.deepEqual(
await actual[code].data['~standard'].validate(value),
await expected.data['~standard'].validate(value),
key,
)
cases++
}
}
}
await walk(consoleRouterContract)
assert.equal(operations, Object.keys(maps).length)
assert(operations > 0)
t.diagnostic(`${operations} operation maps, ${cases} payload comparisons`)
})
@@ -0,0 +1,125 @@
/* oxlint-disable vitest/no-import-node-test -- Compare native mapper types with the repository's generated contracts. */
import assert from 'node:assert/strict'
import { spawnSync } from 'node:child_process'
import { mkdtempSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'
import { join, resolve } from 'node:path'
import { test } from 'node:test'
/* oxlint-enable vitest/no-import-node-test */
const root = resolve(import.meta.dirname, '..')
const contracts = resolve(root, '../contracts')
const specDir = process.env.DIFY_OPENAPI_DIR ?? join(contracts, 'openapi')
test('five generated oRPC contracts match, except intentional stream and multipart differences', () => {
const dir = mkdtempSync(join(root, 'integration/.orpc-'))
try {
for (const name of ['console', 'service', 'openapi'])
symlinkSync(join(specDir, `${name}-openapi.json`), join(dir, `${name}.openapi`))
writeFileSync(
join(dir, 'tsconfig.json'),
JSON.stringify({
compilerOptions: {
strict: true,
noEmit: true,
skipLibCheck: true,
target: 'ES2022',
module: 'NodeNext',
allowImportingTsExtensions: true,
types: ['node'],
lib: ['ES2022', 'DOM'],
},
contentMappers: [{ package: root, extensions: ['.openapi'] }],
include: ['*.ts'],
}),
)
const checks = [
['listDatasets', 'consoleApi.datasets.get', 'datasets.get', [true, true], [true, true]],
['createDataset', 'consoleApi.datasets.post', 'datasets.post', [true, true], [true, true]],
[
'uploadFile',
'consoleApi.files.upload.post',
'files.upload.post',
[true, true],
[true, true],
],
[
'chatMessage',
'serviceApi.chatMessages.post',
'chatMessages.post',
[true, true],
[false, false],
],
[
'chatRun',
'openapiApi.apps.byAppId.chat.run.post',
'run2.post',
[false, false],
[true, true],
],
]
const source = `
import { api as consoleApi } from './console.openapi';
import { api as serviceApi } from './service.openapi';
import { api as openapiApi } from './openapi.openapi';
import type { datasets } from '../../../contracts/generated/api/console/datasets/orpc.gen.ts';
import type { files } from '../../../contracts/generated/api/console/files/orpc.gen.ts';
import type { chatMessages } from '../../../contracts/generated/api/service/orpc.gen.ts';
import type { run2 } from '../../../contracts/generated/api/openapi/orpc.gen.ts';
// Read the actual procedure's Standard Schema input/output types, including Zod defaults.
// This uses the generated contract schemas, not the parallel types.gen.ts declarations.
type Schema = { '~standard': { types?: { input: unknown; output: unknown } } };
type Contract = { '~orpc': { inputSchema?: Schema; outputSchema?: Schema } };
type Input<T extends Contract> = NonNullable<NonNullable<T['~orpc']['inputSchema']>['~standard']['types']>['input'];
type Output<T extends Contract> = NonNullable<NonNullable<T['~orpc']['outputSchema']>['~standard']['types']>['output'];
type Ext<A, B> = [A] extends [B] ? true : false;
type Any<T> = 0 extends (1 & T) ? true : false;
type Unknown<T> = unknown extends T ? true : false;
${checks
.map(
([name, api, contract, input, output]) => `
type ${name}NewIn = Parameters<typeof ${api}>[0];
type ${name}OldIn = Input<typeof ${contract}>;
type ${name}NewOut = Awaited<ReturnType<typeof ${api}>>;
type ${name}OldOut = Output<typeof ${contract}>;
export const ${name}Input: [Ext<${name}NewIn, ${name}OldIn>, Ext<${name}OldIn, ${name}NewIn>] = ${JSON.stringify(input)};
export const ${name}Output: [Ext<${name}NewOut, ${name}OldOut>, Ext<${name}OldOut, ${name}NewOut>] = ${JSON.stringify(output)};
export const ${name}NotAny: [Any<${name}NewIn>, Any<${name}OldIn>, Any<${name}NewOut>, Any<${name}OldOut>] = [false, false, false, false];
export const ${name}NotUnknown: [Unknown<${name}NewIn>, Unknown<${name}OldIn>, Unknown<${name}NewOut>, Unknown<${name}OldOut>] = [false, false, false, false];
`,
)
.join('\n')}
type NewBlocking = Exclude<chatMessageNewOut, ReadableStream<Uint8Array>>;
type OldBlocking = Exclude<chatMessageOldOut, string>;
export const blockingOutput: [Ext<NewBlocking, OldBlocking>, Ext<OldBlocking, NewBlocking>] = [true, true];
// Keep the refreshed discovery field checked explicitly, so stale exports fail this test.
type NewUpgrade = listDatasetsNewOut['data'][number]['knowledge_fs_upgrade'];
type OldUpgrade = listDatasetsOldOut['data'][number]['knowledge_fs_upgrade'];
export const upgrade: [Ext<NewUpgrade, OldUpgrade>, Ext<OldUpgrade, NewUpgrade>] = [true, true];
`
writeFileSync(join(dir, 'check.ts'), source)
const result = spawnSync(
process.execPath,
[
join(root, 'node_modules/typescript/bin/tsc'),
'--runExternalCode',
'--pretty',
'false',
'-p',
dir,
],
{ cwd: root, encoding: 'utf8', timeout: 60000 },
)
assert.ifError(result.error)
assert.equal(
result.status,
0,
result.stdout +
result.stderr +
[...result.stdout.matchAll(/check\.ts\((\d+),/g)]
.map((match) => `\n${source.split('\n')[Number(match[1]) - 1]}`)
.join(''),
)
} finally {
rmSync(dir, { recursive: true, force: true })
}
})
@@ -0,0 +1,295 @@
import assert from 'node:assert/strict'
import { spawn } from 'node:child_process'
import { mkdtemp, readdir, readFile, rm, writeFile } from 'node:fs/promises'
import { tmpdir } from 'node:os'
import { join, resolve } from 'node:path'
import { test } from 'node:test'
const root = resolve(import.meta.dirname, '..')
function run(command, args, cwd) {
return new Promise((resolve, reject) => {
const child = spawn(command, args, {
cwd,
env: {
...process.env,
GOMAXPROCS: '1',
GOMEMLIMIT: '512MiB',
RAYON_NUM_THREADS: '1',
NODE_OPTIONS: '--max-old-space-size=1024',
pnpm_config_verify_deps_before_run: 'false',
},
stdio: ['ignore', 'pipe', 'pipe'],
timeout: 180_000,
killSignal: 'SIGKILL',
})
let output = ''
child.stdout.on('data', (chunk) => {
output = (output + chunk).slice(-32_768)
})
child.stderr.on('data', (chunk) => {
output = (output + chunk).slice(-32_768)
})
child.on('error', reject)
child.on('close', (code) =>
code === 0 ? resolve(output) : reject(new Error(`${command} exited ${code}:\n${output}`)),
)
})
}
async function files(directory, prefix = '') {
const found = []
for (const entry of await readdir(directory, { withFileTypes: true })) {
const name = `${prefix}${entry.name}`
if (entry.isDirectory()) found.push(...(await files(join(directory, entry.name), `${name}/`)))
else found.push(name)
}
return found
}
test('packed SDK installs and works outside the workspace with npm and official Vite', async () => {
const manifest = JSON.parse(await readFile(join(root, 'package.json'), 'utf8'))
const directory = await mkdtemp(join(tmpdir(), 'openapi-package-'))
try {
const tarball = process.env.OPENAPI_PACKAGE_TARBALL
? resolve(process.env.OPENAPI_PACKAGE_TARBALL)
: join(directory, 'sdk.tgz')
await run('pnpm', ['pack', '--out', tarball], root)
await writeFile(
join(directory, 'package.json'),
JSON.stringify({ private: true, type: 'module' }),
)
await run(
'npm',
[
'install',
'--ignore-scripts',
'--no-audit',
'--no-fund',
'--package-lock=false',
tarball,
'typescript@7.1.0-beta',
'vite@8.3.5',
],
directory,
)
const installed = join(directory, 'node_modules', manifest.name)
const packed = JSON.parse(await readFile(join(installed, 'package.json'), 'utf8'))
assert.equal(packed.name, manifest.name)
assert.equal(packed.version, manifest.version)
assert(!packed.private)
assert(!packed.dependencies.vite)
assert.equal(packed.peerDependenciesMeta.vite.optional, true)
for (const lifecycle of ['preinstall', 'install', 'postinstall', 'prepare'])
assert(
!packed.scripts?.[lifecycle],
`Consumer lifecycle must not build the package: ${lifecycle}`,
)
assert.equal(packed.license, 'SEE LICENSE IN LICENSE')
assert.equal(
await readFile(join(root, 'LICENSE'), 'utf8'),
await readFile(join(root, '../../LICENSE'), 'utf8'),
)
assert.equal(
await readFile(join(installed, 'LICENSE'), 'utf8'),
await readFile(join(root, 'LICENSE'), 'utf8'),
)
for (const section of ['dependencies', 'optionalDependencies', 'peerDependencies'])
for (const version of Object.values(packed[section] ?? {}))
assert(
!/^(?:catalog|workspace|link|file):/.test(version),
`Unresolved package dependency: ${version}`,
)
const packedFiles = await files(installed)
assert(packedFiles.includes('README.md'))
assert(packedFiles.includes('CHANGELOG.md'))
for (const file of packedFiles)
assert(
/^(?:dist\/.*\.(?:js|d\.ts)|package\.json|README\.md|LICENSE|CHANGELOG\.md)$/.test(file),
`Unexpected packaged file: ${file}`,
)
for (const target of Object.values(packed.exports)) {
if (typeof target === 'string') continue
assert(packedFiles.includes(target.types.slice(2)), `Missing declarations: ${target.types}`)
assert(packedFiles.includes(target.default.slice(2)), `Missing runtime: ${target.default}`)
}
assert(packedFiles.includes(packed.typescript.contentMapper.exec[1]))
await writeFile(
join(directory, 'export.mjs'),
`console.log(JSON.stringify({
openapi: '3.1.0', paths: { '/status': { get: { responses: { 200: { content: {
'application/json': { schema: { type: 'object', required: ['name'], properties: { name: { type: 'string' } } } }
} } } } } }
}));`,
)
await writeFile(
join(directory, 'backend.openapi-source'),
JSON.stringify({
command: ['node', 'export.mjs'],
inputs: ['export.mjs'],
}),
)
await writeFile(
join(directory, 'backend.openapi-source.config.ts'),
`
export { default } from './pets.yaml.config.ts';
export type { Context } from './pets.yaml.config.ts';
`,
)
await writeFile(
join(directory, 'pets.yaml'),
`
openapi: 3.1.0
paths:
/pets/{petId}:
get:
parameters:
- name: petId
in: path
required: true
schema:
type: integer
responses:
'200':
content:
application/json:
schema:
type: object
required: [name]
properties:
name:
type: string
/UNUSED_ENDPOINT:
get:
responses:
'204':
description: unused
`,
)
await writeFile(
join(directory, 'pets.yaml.config.ts'),
`
import type { RuntimeConfig } from '@dify/openapi-content-mapper';
import { createClient } from '@dify/openapi-content-mapper';
export type Context = { name?: string };
const runtime: RuntimeConfig<Context> = {
queryKeyPrefix: ['pets'],
createClient: ({context}) => createClient({
baseUrl: 'https://example.test',
fetch: async () => context?.name === 'conflict'
? Response.json({code: 'CONFLICT'}, {status: 409})
: Response.json({name: context?.name ?? 'Mochi'}),
}),
};
export default runtime;
`,
)
await writeFile(
join(directory, 'pets.yaml.queries.ts'),
`const defaults = {queryOptions: {staleTime: 1234}}; export {defaults as 'GET /pets/{petId}'};`,
)
await writeFile(
join(directory, 'pets.yaml.errors.ts'),
`const errors = {CONFLICT: {status: 409}}; export {errors as 'GET /pets/{petId}'};`,
)
await writeFile(
join(directory, 'index.ts'),
`
import { api, query } from './pets.yaml';
import { api as backend } from './backend.openapi-source';
import { safe } from '@orpc/client';
const backendName: string = (await backend.status.get()).name;
// @ts-expect-error command-source types survive packaging
const wrongBackendName: number = (await backend.status.get()).name;
const result = await safe(api.pets.byPetId.get({params: {petId: 1}}));
if (result.isDefined) { const code: 'CONFLICT' = result.error.code; }
const pet = await api.pets.byPetId.get({params: {petId: 1}}, {context: {name: 'Mochi'}});
const name: string = pet.name;
query.pets.byPetId.get.queryOptions({input: {params: {petId: 1}}, context: {name: 'Mochi'}});
// @ts-expect-error inferred request types survive packaging
api.pets.byPetId.get({params: {petId: 'wrong'}});
// @ts-expect-error sidecar context survives packaging
api.pets.byPetId.get({params: {petId: 1}}, {context: {name: 123}});
`,
)
for (const module of ['NodeNext', 'ESNext']) {
await writeFile(
join(directory, 'tsconfig.json'),
JSON.stringify({
compilerOptions: {
strict: true,
noEmit: true,
skipLibCheck: true,
target: 'ES2022',
module,
moduleResolution: module === 'NodeNext' ? 'NodeNext' : 'Bundler',
types: [],
allowImportingTsExtensions: true,
},
contentMappers: [
{
package: manifest.name,
extensions: ['.yaml', '.openapi', '.openapi-source'],
options: { sources: ['./backend.openapi-source'] },
},
],
include: ['*.ts'],
}),
)
await run(
process.execPath,
['node_modules/typescript/bin/tsc', '--runExternalCode', '--noEmit'],
directory,
)
}
await writeFile(
join(directory, 'runtime.mjs'),
`
import assert from 'node:assert/strict';
import * as document from './pets.yaml';
import { api as backend } from './backend.openapi-source';
import { safe } from '@orpc/client';
assert.deepEqual(await backend.status.get(undefined, {context: {name: 'backend'}}), {name: 'backend'});
assert.deepEqual(Object.keys(document), ['api', 'query']);
assert.deepEqual(await document.api.pets.byPetId.get({params: {petId: 1}}, {context: {name: 'packed'}}), {name: 'packed'});
assert.deepEqual(document.query.key(), [['pets'], {}]);
assert.equal(document.query.pets.byPetId.get.queryOptions({input: {params: {petId: 1}}}).staleTime, 1234);
const failure = await safe(document.api.pets.byPetId.get({params: {petId: 1}}, {context: {name: 'conflict'}}));
assert.equal(failure.isDefined, true);
assert.equal(failure.error.code, 'CONFLICT');
assert.equal(typeof (await import('@dify/openapi-content-mapper/loader')).default, 'function');
`,
)
await run(process.execPath, ['--import', `${manifest.name}/register`, 'runtime.mjs'], directory)
await writeFile(
join(directory, 'entry.mjs'),
`
import { api } from './pets.yaml';
import { api as backend } from './backend.openapi-source';
export const getPet = (input) => api.pets.byPetId.get(input);
export const getStatus = () => backend.status.get();
`,
)
await writeFile(
join(directory, 'bundle.mjs'),
`
import assert from 'node:assert/strict';
import { build } from 'vite';
import { openapi } from '@dify/openapi-content-mapper/vite';
const result = await build({
configFile: false, logLevel: 'silent', plugins: [openapi()],
build: { write: false, lib: {entry: './entry.mjs', formats: ['es']} },
});
const code = result[0].output.filter(file => file.type === 'chunk').map(file => file.code).join('\\n');
assert(code.includes('/pets/{petId}'));
assert(code.includes('/status'));
assert(!code.includes('export.mjs'));
assert(!code.includes('UNUSED_ENDPOINT'));
assert(!code.includes('parseDocument'));
`,
)
await run(process.execPath, ['bundle.mjs'], directory)
} finally {
await rm(directory, { recursive: true, force: true })
}
})
@@ -0,0 +1,395 @@
/* oxlint-disable vitest/no-import-node-test, antfu/no-import-dist -- Native compiler and built SDK integration against unchanged repository documents. */
import assert from 'node:assert/strict'
import { Buffer } from 'node:buffer'
import { spawnSync } from 'node:child_process'
import { createHash } from 'node:crypto'
import { once } from 'node:events'
import { existsSync, mkdtempSync, readFileSync, rmSync, symlinkSync, writeFileSync } from 'node:fs'
import { createServer } from 'node:http'
import { join, resolve } from 'node:path'
import { test } from 'node:test'
import { pathToFileURL } from 'node:url'
import { gzipSync } from 'node:zlib'
import { build } from 'vite'
import { createClient } from '../dist/index.js'
import { describeOperations } from '../dist/operation.js'
import { createRouter } from '../dist/tooling/router.js'
import { transformSpec } from '../dist/tooling/transform.js'
import { openapi } from '../dist/tooling/vite.js'
import { rpcProcess } from '../test/rpc.mjs'
import '../dist/tooling/register.js'
/* oxlint-enable vitest/no-import-node-test, antfu/no-import-dist */
const root = resolve(import.meta.dirname, '..')
const specDir = process.env.DIFY_OPENAPI_DIR ?? resolve(root, '../contracts/openapi')
const names = [
'console',
'fastopenapi-console',
'inner',
'openapi',
'service',
'web',
'knowledge-fs',
]
const files = names.map((name) =>
name === 'knowledge-fs'
? resolve(root, '../../api/knowledge-fs-contract/knowledge-fs.openapi.json')
: join(specDir, `${name}-openapi.json`),
)
const compiler = join(root, 'node_modules/typescript/bin/tsc')
function routes(node, path = []) {
return [...node.methods]
.map(([method, operation]) => ({ members: [...path, method], operation }))
.concat([...node.children].flatMap(([key, child]) => routes(child, [...path, key])))
}
test('unchanged Dify and KnowledgeFS OpenAPI documents', { timeout: 120000 }, async (t) => {
for (const file of files)
assert(
existsSync(file),
`Missing ${file}. Supply DIFY_OPENAPI_DIR with existing generated OpenAPI files; this test never regenerates or edits them.`,
)
const dir = mkdtempSync(join(root, 'integration/.repository-'))
const specs = files.map((file) => JSON.parse(readFileSync(file, 'utf8')))
const contents = files.map((file) => readFileSync(file, 'utf8'))
const entries = names.map((name) => join(dir, `${name}.openapi`))
const hash = (text) => createHash('sha256').update(text).digest('hex')
try {
for (const [index, file] of files.entries()) symlinkSync(file, entries[index])
writeFileSync(
join(dir, 'tsconfig.json'),
JSON.stringify({
compilerOptions: {
strict: true,
noEmit: true,
skipLibCheck: true,
target: 'ES2022',
module: 'NodeNext',
types: ['node'],
lib: ['ES2022', 'DOM'],
},
contentMappers: [{ package: root, extensions: ['.openapi'] }],
include: ['*.ts'],
}),
)
await t.test('all operations survive mapping; source hashes and counts are recorded', () => {
specs.forEach((spec, index) => {
const transformed = transformSpec(contents[index], entries[index])
assert.equal(transformed.diagnostics, undefined, JSON.stringify(transformed.diagnostics))
const operations = describeOperations(spec)
const declared = Object.values(spec.paths).reduce(
(count, item) =>
count +
Object.keys(item).filter((method) =>
['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'].includes(
method,
),
).length,
0,
)
assert.equal(
operations.size,
declared,
'No unsupported operation may be silently filtered out',
)
assert.equal(routes(createRouter(operations)).length, operations.size)
t.diagnostic(
`${names[index]}: ${Object.keys(spec.paths).length} paths, ${operations.size} operations, ${Buffer.byteLength(contents[index])} bytes, sha256 ${hash(contents[index])}`,
)
})
})
await t.test('native TS 7.1 checks every route plus real request/response assertions', () => {
const allRoutes = specs
.flatMap((spec, index) => [
`import { api as api${index} } from './${names[index]}.openapi';`,
...routes(createRouter(describeOperations(spec))).map(({ members }, routeIndex) => {
const expression = `api${index}${members.map((key) => `[${JSON.stringify(key)}]`).join('')}`
return `export type Input${index}_${routeIndex} = Parameters<typeof ${expression}>; export type Output${index}_${routeIndex} = Awaited<ReturnType<typeof ${expression}>>;`
}),
])
.join('\n')
writeFileSync(join(dir, 'all-routes.ts'), allRoutes)
writeFileSync(
join(dir, 'assertions.ts'),
`
import { api as consoleApi, query as consoleQuery } from './console.openapi';
import { api as service } from './service.openapi';
import { api as web } from './web.openapi';
import { api as inner } from './inner.openapi';
import { api as openapi } from './openapi.openapi';
import { api as fast } from './fastopenapi-console.openapi';
import { api as knowledge } from './knowledge-fs.openapi';
type IsAny<T> = 0 extends (1 & T) ? true : false;
const datasets = await consoleApi.datasets.get({query: {page: 1, ids: ['id']}});
const total: number = datasets.total;
const redirect: Awaited<ReturnType<typeof consoleApi.mcp.oauth.callback.get>> = undefined;
const notAny: IsAny<typeof datasets> = false;
// @ts-expect-error actual pagination type is numeric
const wrongTotal: string = datasets.total;
// @ts-expect-error actual query limit is numeric
consoleApi.datasets.get({query: {limit: '10'}});
consoleApi.datasets.post({body: {name: 'Example'}});
// @ts-expect-error required dataset name comes from a local schema reference
consoleApi.datasets.post({body: {}});
const upload = await consoleApi.files.upload.post({body: {file: new File(['file'], 'file.txt'), source: 'datasets'}});
const fileId: string = upload.id;
// @ts-expect-error binary file accepts Blob/File, not a string
consoleApi.files.upload.post({body: {file: 'file.txt'}});
// @ts-expect-error file is required
consoleApi.files.upload.post({body: {source: 'datasets'}});
const options = consoleQuery.datasets.get.queryOptions({input: {query: {page: 1}}});
type QueryResult = Awaited<ReturnType<typeof options.queryFn>>;
const queryTotal: number = (null! as QueryResult).total;
await service.datasets.byDatasetId.document.createByFile.post({params: {dataset_id: 'id'}, body: {file: new Blob(['file'])}});
await service.datasets.byDatasetId.document.create_by_file.post({params: {dataset_id: 'id'}, body: {file: new Blob(['file'])}});
await openapi.apps.byAppId.chat.run.post({params: {app_id: 'id'}, contentType: 'multipart/form-data', body: {query: 'hello', inputs: {enabled: true}}});
await openapi.apps.byAppId.chat.run.post({params: {app_id: 'id'}, body: {query: 'hello', attachments: ['path.txt']}});
await openapi.apps.byAppId.chat.run.post({params: {app_id: 'id'}, contentType: 'multipart/form-data', body: {query: 'hello', attachments: [new File(['file'], 'file.txt')]}});
// @ts-expect-error binary values need explicit multipart selection when JSON is also available
openapi.apps.byAppId.chat.run.post({params: {app_id: 'id'}, body: {query: 'hello', attachments: [new Blob(['file'])]}});
const parameters = await web.parameters.get();
const question: string | undefined = parameters.suggested_questions?.[0];
const opaque: unknown = await inner.agentConfig.byAgentId.env.patch({params: {agent_id: 'id'}});
// @ts-expect-error an undocumented 200 body must remain unknown, not invent a shape
opaque.success;
await fast.console.api.ping.get();
const health = await knowledge.health.get();
const runtime: 'cloudflare-workers' | 'node-docker' = health.runtime;
await knowledge.uploadSessions.byId.smallFile.post({params: {id: 'id'}, query: {knowledgeSpaceId: 'space'}, body: new Blob(['bytes'])});
// @ts-expect-error raw binary upload does not accept a JSON object
knowledge.uploadSessions.byId.smallFile.post({params: {id: 'id'}, query: {knowledgeSpaceId: 'space'}, body: {file: 'x'}});
const bulk = knowledge.knowledgeSpaces.byId.documents.bulk.post({params: {id: 'id'}, body: {files: [new File(['a'], 'a.txt')]}});
type Chat = Awaited<ReturnType<typeof service.chatMessages.post>>;
const stream: Extract<Chat, ReadableStream<Uint8Array>> = new ReadableStream<Uint8Array>();
`,
)
const started = performance.now()
const result = spawnSync(
process.execPath,
[compiler, '--runExternalCode', '--pretty', 'false', '-p', dir],
{ cwd: root, encoding: 'utf8', timeout: 90000 },
)
assert.ifError(result.error)
assert.equal(result.status, 0, result.stdout + result.stderr)
t.diagnostic(`Native compilation: ${Math.round(performance.now() - started)} ms`)
})
await t.test('native editor completions and hover work on the full console spec', async () => {
const rpc = rpcProcess(process.execPath, [compiler, '--lsp', '--stdio'], root)
try {
await rpc.request('initialize', {
processId: process.pid,
rootUri: pathToFileURL(dir).href,
capabilities: {},
initializationOptions: { runExternalCode: true },
})
rpc.notify('initialized', {})
const uri = pathToFileURL(join(dir, 'editor.ts')).href
const text =
"import { api } from './console.openapi';\nconst result = await api.datasets.get();\nresult.total;\napi.datasets."
rpc.notify('textDocument/didOpen', {
textDocument: { uri, languageId: 'typescript', version: 1, text },
})
const completions = await rpc.request('textDocument/completion', {
textDocument: { uri },
position: { line: 3, character: 13 },
})
const labels = (completions.items ?? completions).map((item) => item.label)
assert(labels.includes('get') && labels.includes('post'))
const hover = await rpc.request('textDocument/hover', {
textDocument: { uri },
position: { line: 2, character: 9 },
})
assert.match(JSON.stringify(hover), /total.*number/)
} finally {
rpc.close()
}
})
await t.test(
'real HTTP serialization: query, multipart, binary, relative servers and streaming',
async () => {
const [
{ api: consoleApi },
,
,
{ api: publicApi },
{ api: serviceApi },
,
{ api: knowledge },
] = await Promise.all(entries.map((file) => import(pathToFileURL(file).href)))
const requests = []
const server = createServer(async (req, res) => {
try {
const chunks = []
for await (const chunk of req) chunks.push(chunk)
const body = Buffer.concat(chunks)
const request = new Request(`http://localhost${req.url}`, {
method: req.method,
headers: req.headers,
...(req.method !== 'GET' ? { body } : {}),
})
const contentType = req.headers['content-type'] ?? ''
const data = contentType.startsWith('multipart/')
? await request.formData()
: body.toString()
requests.push({ path: req.url, headers: req.headers, data })
if (req.url === '/v1/chat-messages') {
res.writeHead(200, { 'Content-Type': 'text/event-stream' })
res.write('data: {"event":"message","answer":"hello"}\n\n')
} else {
res.setHeader('Content-Type', 'application/json')
res.end(
JSON.stringify({ data: [], total: 0, id: 'uploaded', name: 'test.txt', size: 5 }),
)
}
} catch (error) {
res.writeHead(500).end(String(error))
}
})
server.listen(0, '127.0.0.1')
await once(server, 'listening')
const origin = `http://127.0.0.1:${server.address().port}`
const previousLocation = Object.getOwnPropertyDescriptor(globalThis, 'location')
try {
Object.defineProperty(globalThis, 'location', {
configurable: true,
value: new URL(origin),
})
const client = createClient({ headers: { 'Content-Type': 'application/json' } })
await consoleApi.datasets.get({ query: { ids: ['a', 'b'], page: 2 } }, { client })
assert.equal(requests.at(-1).path, '/console/api/datasets?ids=a&ids=b&page=2')
await consoleApi.files.upload.post(
{ body: { file: new File(['hello'], 'test.txt'), source: 'datasets' } },
{ client },
)
assert.match(requests.at(-1).headers['content-type'], /^multipart\/form-data; boundary=/)
assert.equal(requests.at(-1).data.get('file').name, 'test.txt')
assert.equal(await requests.at(-1).data.get('file').text(), 'hello')
assert.equal(requests.at(-1).data.get('source'), 'datasets')
const direct = createClient({ baseUrl: origin })
await knowledge.uploadSessions.byId.smallFile.post(
{
params: { id: 'a/b' },
query: { knowledgeSpaceId: 'space' },
body: new Blob(['binary']),
},
{ client: direct },
)
assert.equal(
requests.at(-1).path,
'/upload-sessions/a%2Fb/small-file?knowledgeSpaceId=space',
)
assert.equal(requests.at(-1).headers['content-type'], 'application/octet-stream')
assert.equal(requests.at(-1).data, 'binary')
await knowledge.knowledgeSpaces.byId.documents.bulk.post(
{
params: { id: 'id' },
body: { files: [new File(['a'], 'a.txt'), new File(['b'], 'b.txt')] },
},
{ client: direct },
)
assert.deepEqual(
requests
.at(-1)
.data.getAll('files')
.map((file) => file.name),
['a.txt', 'b.txt'],
)
for (const member of ['createByFile', 'create_by_file']) {
await serviceApi.datasets.byDatasetId.document[member].post(
{ params: { dataset_id: 'id' }, body: { file: new File(['file'], 'file.txt') } },
{ client },
)
}
assert.equal(requests.at(-2).path, '/v1/datasets/id/document/create-by-file')
assert.equal(requests.at(-1).path, '/v1/datasets/id/document/create_by_file')
await publicApi.apps.byAppId.chat.run.post(
{
params: { app_id: 'id' },
contentType: 'multipart/form-data',
body: { query: 'hello', inputs: { enabled: true } },
},
{ client },
)
assert.equal(requests.at(-1).path, '/openapi/v1/apps/id/chat:run')
assert.equal(await requests.at(-1).data.get('query').text(), '"hello"')
assert.equal(await requests.at(-1).data.get('inputs').text(), '{"enabled":true}')
const stream = await serviceApi.chatMessages.post(
{ body: { query: 'hello', inputs: {}, user: 'test', response_mode: 'streaming' } },
{ client, signal: AbortSignal.timeout(3000) },
)
assert(stream instanceof ReadableStream)
const reader = stream.getReader()
assert.match(new TextDecoder().decode((await reader.read()).value), /"answer":"hello"/)
await reader.cancel()
} finally {
if (previousLocation) Object.defineProperty(globalThis, 'location', previousLocation)
else delete globalThis.location
server.closeAllConnections()
await new Promise((resolve) => server.close(resolve))
}
},
)
for (const [index, members, route] of [
[0, 'datasets.get', '/datasets'],
[6, 'health.get', '/health'],
]) {
for (const namespace of ['api', 'query'])
await t.test(
`${names[index]} ${namespace}: full-document bundle equals one-path bundle`,
async () => {
async function bundle(file) {
writeFileSync(
join(dir, 'entry.ts'),
`import { ${namespace} } from './${file}'; export const operation = ${namespace}.${members}${namespace === 'query' ? '.queryOptions' : ''};`,
)
const result = await build({
configFile: false,
root: dir,
logLevel: 'silent',
plugins: [openapi()],
build: {
write: false,
minify: true,
lib: { entry: join(dir, 'entry.ts'), formats: ['es'] },
},
})
return (Array.isArray(result) ? result : [result])
.flatMap((result) => result.output)
.filter((file) => file.type === 'chunk')
.map((file) => file.code)
.join('\n')
}
const full = await bundle(`${names[index]}.openapi`)
const reduced = {
...specs[index],
paths: { [route]: { ...specs[index].paths[route], post: undefined } },
}
writeFileSync(join(dir, 'reduced.openapi'), JSON.stringify(reduced))
const small = await bundle('reduced.openapi')
const normalize = (code) => code.replace(/^\/\/.*$/gm, '')
assert.equal(normalize(full), normalize(small))
for (const marker of [
'/files/upload',
'/upload-sessions/',
'DatasetCreatePayload',
'parseDocument',
'YAMLParseError',
])
assert(!full.includes(marker), `Unexpected unused content: ${marker}`)
t.diagnostic(
`${names[index]} ${namespace}: ${Buffer.byteLength(full)} bytes, ${gzipSync(full).length} gzip`,
)
},
)
}
} finally {
for (const [index, file] of files.entries())
assert.equal(
hash(readFileSync(file, 'utf8')),
hash(contents[index]),
'Source document must stay untouched',
)
rmSync(dir, { recursive: true, force: true })
}
})
@@ -0,0 +1,130 @@
{
"name": "@dify/openapi-content-mapper",
"version": "0.1.0-beta.0",
"description": "Typed OpenAPI imports with TypeScript 7.1 Content Mappers, tree-shakable API calls and query helpers.",
"keywords": [
"content-mapper",
"nextjs",
"openapi",
"sdk",
"tanstack-query",
"tree-shaking",
"typescript",
"vite"
],
"homepage": "https://github.com/langgenius/dify/tree/main/packages/openapi-content-mapper#readme",
"bugs": {
"url": "https://github.com/langgenius/dify/issues"
},
"license": "SEE LICENSE IN LICENSE",
"repository": {
"type": "git",
"url": "git+https://github.com/langgenius/dify.git",
"directory": "packages/openapi-content-mapper"
},
"files": [
"CHANGELOG.md",
"LICENSE",
"dist"
],
"type": "module",
"sideEffects": [
"./dist/tooling/register.js"
],
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"./vite": {
"types": "./dist/tooling/vite.d.ts",
"default": "./dist/tooling/vite.js"
},
"./loader": {
"types": "./dist/tooling/loader.d.ts",
"default": "./dist/tooling/loader.js"
},
"./namespace": {
"types": "./dist/tooling/openapi-namespace.d.ts",
"default": "./dist/tooling/openapi-namespace.js"
},
"./register": {
"types": "./dist/tooling/register.d.ts",
"default": "./dist/tooling/register.js"
},
"./mapper": {
"types": "./dist/tooling/mapper.d.ts",
"default": "./dist/tooling/mapper.js"
},
"./runtime": {
"types": "./dist/client.d.ts",
"default": "./dist/client.js"
},
"./query-runtime": {
"types": "./dist/query-runtime.d.ts",
"default": "./dist/query-runtime.js"
},
"./package.json": "./package.json",
"./errors": {
"types": "./dist/errors.d.ts",
"default": "./dist/errors.js"
}
},
"publishConfig": {
"access": "public",
"registry": "https://registry.npmjs.org/",
"tag": "beta"
},
"scripts": {
"build": "vp pack",
"prepare": "pnpm run build",
"type-check": "tsc -p tsconfig.json --noEmit && tsc --runExternalCode --noEmit -p examples/petstore/tsconfig.json",
"test": "node --test --test-concurrency=1 test/*.test.mjs",
"demo": "node --import ./dist/tooling/register.js examples/petstore/demo.ts",
"test:next": "node --test integration/next.mjs",
"test:repository": "node --test integration/*.test.mjs",
"compare:orpc": "node integration/compare-orpc.mjs",
"check:orpc": "node integration/compare-orpc.mjs --check",
"prepack": "pnpm run build",
"test:package": "node --test integration/package.mjs",
"check:console": "node integration/compare-orpc.mjs --console --check"
},
"dependencies": {
"@orpc/client": "catalog:",
"@orpc/contract": "catalog:",
"@orpc/standard-server": "catalog:",
"@orpc/tanstack-query": "catalog:",
"es-module-lexer": "catalog:",
"import-meta-resolve": "catalog:",
"yaml": "catalog:"
},
"devDependencies": {
"@tanstack/query-core": "catalog:",
"@types/node": "catalog:",
"typescript": "catalog:ts71",
"vite": "catalog:",
"vite-plus": "catalog:"
},
"peerDependencies": {
"vite": "catalog:public-vite"
},
"peerDependenciesMeta": {
"vite": {
"optional": true
}
},
"typescript": {
"contentMapper": {
"compilerOptions": [],
"dynamicConfig": true,
"exec": [
"node",
"dist/tooling/mapper.js"
]
}
},
"engines": {
"node": ">=24"
}
}
@@ -0,0 +1,259 @@
import type { OperationDescriptor } from './operation.js'
import type { CallOptions } from './types.js'
import { getFilenameFromContentDisposition } from '@orpc/standard-server'
export type ClientOptions = {
baseUrl?: string
headers?: HeadersInit
fetch?: typeof globalThis.fetch
}
export class ApiError extends Error {
readonly response: globalThis.Response
readonly data: unknown
constructor(response: globalThis.Response, data: unknown) {
super(`HTTP ${response.status} ${response.statusText}`)
this.name = 'ApiError'
this.response = response
this.data = data
}
}
export type RuntimeOptions = {
client?: HttpClient
path?: Record<string, unknown>
query?: Record<string, unknown>
header?: Record<string, unknown>
cookie?: Record<string, unknown>
body?: unknown
contentType?: string
headers?: HeadersInit
signal?: AbortSignal
credentials?: RequestCredentials
context?: object
}
/** Bound per document at build time; never wraps or enumerates the router. */
export type RuntimeConfig<Context extends object = object> = {
createClient?: (options: CallOptions<Context>) => HttpClient
queryKeyPrefix?: readonly string[]
onError?: (error: unknown) => void
}
function scalar(value: unknown): string {
if (!['string', 'number', 'boolean'].includes(typeof value))
throw new Error('Parameter values must be strings, numbers, booleans, or flat arrays/objects')
return String(value)
}
function simple(value: unknown, explode: boolean, encode: (s: string) => string): string {
if (Array.isArray(value)) return value.map((item) => encode(scalar(item))).join(',')
if (value && typeof value === 'object') {
return Object.entries(value)
.map(([key, item]) => `${encode(key)}${explode ? '=' : ','}${encode(scalar(item))}`)
.join(',')
}
return encode(scalar(value))
}
function queryValues(
search: URLSearchParams,
name: string,
value: unknown,
style: string,
explode: boolean,
) {
if (style === 'deepObject') {
if (!value || typeof value !== 'object' || Array.isArray(value) || !explode)
throw new Error('deepObject requires a flat object and explode: true')
for (const [key, item] of Object.entries(value)) search.append(`${name}[${key}]`, scalar(item))
} else if (style === 'form') {
if (Array.isArray(value) && explode) value.forEach((item) => search.append(name, scalar(item)))
else if (value && typeof value === 'object' && !Array.isArray(value) && explode)
Object.entries(value).forEach(([key, item]) => search.append(key, scalar(item)))
else
search.append(
name,
simple(value, false, (s) => s),
)
} else {
throw new Error(`Unsupported query serialization style: ${style}`)
}
}
export type HttpClient = {
getConfig: () => ClientOptions
setConfig: (config: Partial<ClientOptions>) => void
request: (operation: OperationDescriptor, options?: RuntimeOptions) => Promise<unknown>
}
export function createClient(initial: ClientOptions = {}): HttpClient {
let config = { ...initial }
async function request(
operation: OperationDescriptor,
options: RuntimeOptions = {},
): Promise<unknown> {
const { method, path: template, parameters = [] } = operation
const fetcher = config.fetch ?? globalThis.fetch
let path = template
const search = new URLSearchParams()
const headers = new Headers(config.headers)
new Headers(options.headers).forEach((value, key) => headers.set(key, value))
for (const parameter of parameters) {
const location = String(parameter.in)
const name = String(parameter.name)
const group = options[location as 'path' | 'query' | 'header' | 'cookie']
const value = group && Object.hasOwn(group, name) ? group[name] : undefined
if (value === undefined) {
if (parameter.required === true || location === 'path')
throw new Error(`Missing required ${location} parameter: ${name}`)
continue
}
const style = String(
parameter.style ?? (location === 'query' || location === 'cookie' ? 'form' : 'simple'),
)
const explode =
parameter.explode === undefined ? style === 'form' : parameter.explode === true
switch (location) {
case 'path':
if (style !== 'simple') throw new Error(`Unsupported path style: ${style}`)
path = path.replaceAll(`{${name}}`, simple(value, explode, encodeURIComponent))
break
case 'query':
queryValues(search, name, value, style, explode)
break
case 'header':
if (style !== 'simple') throw new Error(`Unsupported header style: ${style}`)
headers.set(
name,
simple(value, explode, (s) => s),
)
break
case 'cookie':
// Fetch forbids manually setting Cookie in browsers; usable in Node.
if (style !== 'form' || typeof value === 'object')
throw new Error('Only primitive form-style cookies are supported')
headers.set(
'Cookie',
[
headers.get('Cookie'),
`${encodeURIComponent(name)}=${encodeURIComponent(scalar(value))}`,
]
.filter(Boolean)
.join('; '),
)
break
default:
throw new Error(`Unsupported parameter location: ${location}`)
}
}
if (/\{[^}]+\}/.test(path)) throw new Error(`Unresolved path template: ${path}`)
const base = config.baseUrl ?? operation.baseUrl
if (!base || /\{[^}]+\}/.test(base))
throw new Error('Provide baseUrl, or a server URL without template variables')
const url = new URL(
`${base.replace(/\/$/, '')}/${path.replace(/^\//, '')}`,
globalThis.location?.origin,
)
search.forEach((value, key) => url.searchParams.append(key, value))
if (operation.bodyRequired && options.body === undefined)
throw new Error('Missing required request body')
let body: BodyInit | undefined
if (options.body !== undefined) {
const mediaType = options.contentType ?? operation.contentType
if (!mediaType || !(operation.contentTypes ?? [operation.contentType]).includes(mediaType))
throw new Error('Request content type must be declared by the operation')
if (mediaType === 'multipart/form-data') {
const form = new FormData()
if (!options.body || typeof options.body !== 'object' || Array.isArray(options.body))
throw new Error('Multipart body must be an object')
for (const [key, value] of Object.entries(options.body)) {
if (value === undefined) continue
if (operation.multipartJson?.includes(key)) {
form.append(key, new Blob([JSON.stringify(value)], { type: 'application/json' }))
} else {
for (const item of Array.isArray(value) ? value : [value])
form.append(key, item instanceof Blob ? item : scalar(item))
}
}
// Fetch supplies the boundary, including when a shared client has JSON headers.
headers.delete('Content-Type')
body = form
} else if (mediaType === 'application/octet-stream') {
if (!(options.body instanceof Blob)) throw new Error('Binary body must be a Blob or File')
headers.set('Content-Type', mediaType)
body = options.body
} else {
headers.set('Content-Type', mediaType)
body = JSON.stringify(options.body)
}
}
const response = await fetcher(url, {
method: method.toUpperCase(),
headers,
body,
signal: options.signal,
credentials: options.credentials,
})
let contentType = response.headers.get('content-type')?.split(';')[0]?.trim() ?? ''
if (response.ok) {
const media =
operation.responseContentTypes?.[response.status] ?? operation.responseContentTypes?.['2XX']
// Match the most specific declaration. A binary wildcard remains a Blob
// even when the server chooses JSON, text, or SSE as its concrete media type.
if (media && !media.includes(contentType)) {
const range = `${contentType.split('/')[0]}/*`
if (media.includes(range)) contentType = range
else if (media.includes('*/*')) contentType = '*/*'
}
}
let data: unknown
if (response.status !== 204 && response.status !== 205 && method !== 'head') {
const disposition = response.headers.get('content-disposition')
if (response.ok && disposition !== null) {
const blob = await response.blob()
data = new File([blob], getFilenameFromContentDisposition(disposition) ?? 'blob', {
type: blob.type,
})
} else if (response.ok && contentType === 'text/event-stream') data = response.body
else if (contentType === 'application/json' || contentType.endsWith('+json'))
data = await response.json()
else if (contentType.startsWith('text/')) data = await response.text()
else data = await response.blob()
}
if (!response.ok) throw new ApiError(response, data)
return data
}
return {
request,
getConfig: () => ({ ...config, headers: new Headers(config.headers) }),
setConfig: (update) => {
config = { ...config, ...update }
},
}
}
export const client = /* @__PURE__ */ createClient()
export async function invokeRpcOperation(
operation: OperationDescriptor,
input: Omit<RuntimeOptions, 'path' | 'header' | 'headers'> & {
params?: Record<string, unknown>
headers?: Record<string, unknown>
} = {},
options: CallOptions = {},
runtime?: RuntimeConfig,
validateError?: (error: unknown) => Promise<unknown>,
): Promise<unknown> {
const { params, headers, ...request } = input
const call = { ...request, path: params, ...options, header: headers }
try {
const transport = call.client ?? runtime?.createClient?.(call) ?? client
return await transport.request(operation, call)
} catch (error) {
const failure = validateError ? await validateError(error) : error
runtime?.onError?.(failure)
throw failure
}
}
@@ -0,0 +1,46 @@
import type { OpenApiDocument } from './types.js'
export function record(value: unknown): Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value)
? (value as Record<string, unknown>)
: {}
}
export function resolveRef(value: unknown, root: unknown): Record<string, unknown> {
const seen = new Set<string>()
let result = record(value)
while (typeof result.$ref === 'string') {
const ref = result.$ref
if (seen.has(ref)) throw new Error(`Circular reference outside a schema: ${ref}`)
seen.add(ref)
result = record(pointer(root, ref))
}
return result
}
export function pointerPath(ref: string): string[] {
if (!ref.startsWith('#/'))
throw new Error(`Only local JSON Pointer references are supported: ${ref}`)
return ref
.slice(2)
.split('/')
.map((part) => part.replace(/~1/g, '/').replace(/~0/g, '~'))
}
export function pointer(root: unknown, ref: string): unknown {
let value = root
for (const key of pointerPath(ref)) {
if (value === null || typeof value !== 'object' || !Object.hasOwn(value, key))
throw new Error(`Unresolved reference: ${ref}`)
value = (value as Record<string, unknown>)[key]
}
return value
}
export function assertDocument(value: unknown): asserts value is OpenApiDocument {
const doc = record(value)
if (typeof doc.openapi !== 'string' || !/^3\.[01]\./.test(doc.openapi))
throw new Error('Expected an OpenAPI 3.0.x or 3.1.x document')
if (!doc.paths || typeof doc.paths !== 'object' || Array.isArray(doc.paths))
throw new Error('OpenAPI document must contain a paths object')
}
Loaded 100 of 150 files, more files were not shown because too many files have changed in this diff. Show more