From 1e8329f02cc889b99bb9b507d4f861303299fe55 Mon Sep 17 00:00:00 2001 From: zyssyz123 <916125788@qq.com> Date: Mon, 15 Jun 2026 19:09:15 +0800 Subject: [PATCH] feat: Unify Agent v2 console routes (#37465) Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> --- api/controllers/console/agent/app_helpers.py | 10 + api/controllers/console/agent/composer.py | 43 +- api/controllers/console/agent/roster.py | 187 +- api/controllers/console/app/agent.py | 485 +++-- .../console/app/agent_app_access.py | 15 +- .../console/app/agent_app_feature.py | 17 +- .../console/app/agent_app_sandbox.py | 23 +- .../console/app/agent_drive_inspector.py | 83 +- api/controllers/console/app/app.py | 8 +- api/openapi/markdown/console-openapi.md | 579 ++++-- api/services/agent/roster_service.py | 39 +- .../console/agent/test_agent_controllers.py | 300 ++- .../console/app/test_agent_app_sandbox.py | 11 +- .../console/app/test_agent_drive_inspector.py | 73 + .../console/app/test_agent_skills.py | 142 +- .../console/app/test_app_response_models.py | 26 +- .../console/app/test_create_app_payload.py | 13 +- .../services/agent/test_agent_services.py | 25 + .../generated/api/console/agent/orpc.gen.ts | 582 ++++++ .../generated/api/console/agent/types.gen.ts | 1545 ++++++++++++++ .../generated/api/console/agent/zod.gen.ts | 1817 +++++++++++++++++ .../generated/api/console/agents/orpc.gen.ts | 100 - .../generated/api/console/agents/types.gen.ts | 587 ------ .../generated/api/console/agents/zod.gen.ts | 743 ------- .../generated/api/console/apps/orpc.gen.ts | 807 +++----- .../generated/api/console/apps/types.gen.ts | 1013 ++++----- .../generated/api/console/apps/zod.gen.ts | 1163 +++++------ .../generated/api/console/orpc.gen.ts | 4 +- 28 files changed, 6705 insertions(+), 3735 deletions(-) create mode 100644 api/controllers/console/agent/app_helpers.py create mode 100644 packages/contracts/generated/api/console/agent/orpc.gen.ts create mode 100644 packages/contracts/generated/api/console/agent/types.gen.ts create mode 100644 packages/contracts/generated/api/console/agent/zod.gen.ts delete mode 100644 packages/contracts/generated/api/console/agents/orpc.gen.ts delete mode 100644 packages/contracts/generated/api/console/agents/types.gen.ts delete mode 100644 packages/contracts/generated/api/console/agents/zod.gen.ts diff --git a/api/controllers/console/agent/app_helpers.py b/api/controllers/console/agent/app_helpers.py new file mode 100644 index 0000000000..51adc1e136 --- /dev/null +++ b/api/controllers/console/agent/app_helpers.py @@ -0,0 +1,10 @@ +from uuid import UUID + +from extensions.ext_database import db +from models.model import App +from services.agent.roster_service import AgentRosterService + + +def resolve_agent_app_model(*, tenant_id: str, agent_id: UUID) -> App: + """Resolve the hidden Agent App backing an Agent Console resource.""" + return AgentRosterService(db.session).get_agent_app_model(tenant_id=tenant_id, agent_id=str(agent_id)) diff --git a/api/controllers/console/agent/composer.py b/api/controllers/console/agent/composer.py index 5e778f67f9..6915a54db9 100644 --- a/api/controllers/console/agent/composer.py +++ b/api/controllers/console/agent/composer.py @@ -1,7 +1,10 @@ +from uuid import UUID + from flask_restx import Resource from controllers.common.schema import register_response_schema_models, register_schema_models from controllers.console import console_ns +from controllers.console.agent.app_helpers import resolve_agent_app_model from controllers.console.app.wraps import get_app_model from controllers.console.wraps import ( account_initialization_required, @@ -35,6 +38,10 @@ register_response_schema_models( ) +def _resolve_agent_app_id(*, tenant_id: str, agent_id: UUID) -> str: + return resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id).id + + @console_ns.route("/apps//workflows/draft/nodes//agent-composer") class WorkflowAgentComposerApi(Resource): @console_ns.response( @@ -176,18 +183,18 @@ class WorkflowAgentComposerSaveToRosterApi(Resource): ) -@console_ns.route("/apps//agent-composer") -class AgentAppComposerApi(Resource): +@console_ns.route("/agent//composer") +class AgentComposerApi(Resource): @console_ns.response(200, "Agent app composer state", console_ns.models[AgentAppComposerResponse.__name__]) @setup_required @login_required @account_initialization_required - @get_app_model(mode=[AppMode.AGENT]) @with_current_tenant_id - def get(self, tenant_id: str, app_model: App): + def get(self, tenant_id: str, agent_id: UUID): + app_id = _resolve_agent_app_id(tenant_id=tenant_id, agent_id=agent_id) return dump_response( AgentAppComposerResponse, - AgentComposerService.load_agent_app_composer(tenant_id=tenant_id, app_id=app_model.id), + AgentComposerService.load_agent_app_composer(tenant_id=tenant_id, app_id=app_id), ) @console_ns.expect(console_ns.models[ComposerSavePayload.__name__]) @@ -196,24 +203,24 @@ class AgentAppComposerApi(Resource): @login_required @account_initialization_required @edit_permission_required - @get_app_model(mode=[AppMode.AGENT]) @with_current_user_id @with_current_tenant_id - def put(self, tenant_id: str, account_id: str, app_model: App): + def put(self, tenant_id: str, account_id: str, agent_id: UUID): + app_id = _resolve_agent_app_id(tenant_id=tenant_id, agent_id=agent_id) payload = ComposerSavePayload.model_validate(console_ns.payload or {}) return dump_response( AgentAppComposerResponse, AgentComposerService.save_agent_app_composer( tenant_id=tenant_id, - app_id=app_model.id, + app_id=app_id, account_id=account_id, payload=payload, ), ) -@console_ns.route("/apps//agent-composer/validate") -class AgentAppComposerValidateApi(Resource): +@console_ns.route("/agent//composer/validate") +class AgentComposerValidateApi(Resource): @console_ns.expect(console_ns.models[ComposerSavePayload.__name__]) @console_ns.response( 200, "Agent app composer validation result", console_ns.models[AgentComposerValidateResponse.__name__] @@ -221,36 +228,36 @@ class AgentAppComposerValidateApi(Resource): @setup_required @login_required @account_initialization_required - @get_app_model(mode=[AppMode.AGENT]) @with_current_tenant_id - def post(self, tenant_id: str, app_model: App): + def post(self, tenant_id: str, agent_id: UUID): + _resolve_agent_app_id(tenant_id=tenant_id, agent_id=agent_id) payload = ComposerSavePayload.model_validate(console_ns.payload or {}) ComposerConfigValidator.validate_save_payload(payload) findings = AgentComposerService.collect_validation_findings( tenant_id=tenant_id, payload=payload, - agent_id=AgentComposerService.resolve_bound_agent_id(tenant_id=tenant_id, app_id=app_model.id), + agent_id=str(agent_id), ) return dump_response(AgentComposerValidateResponse, {"result": "success", "errors": [], **findings}) -@console_ns.route("/apps//agent-composer/candidates") -class AgentAppComposerCandidatesApi(Resource): +@console_ns.route("/agent//composer/candidates") +class AgentComposerCandidatesApi(Resource): @console_ns.response( 200, "Agent app composer candidates", console_ns.models[AgentComposerCandidatesResponse.__name__] ) @setup_required @login_required @account_initialization_required - @get_app_model(mode=[AppMode.AGENT]) @with_current_user_id @with_current_tenant_id - def get(self, tenant_id: str, current_user_id: str, app_model: App): + def get(self, tenant_id: str, current_user_id: str, agent_id: UUID): + app_id = _resolve_agent_app_id(tenant_id=tenant_id, agent_id=agent_id) return dump_response( AgentComposerCandidatesResponse, AgentComposerService.get_agent_app_candidates( tenant_id=tenant_id, - app_id=app_model.id, + app_id=app_id, user_id=current_user_id, ), ) diff --git a/api/controllers/console/agent/roster.py b/api/controllers/console/agent/roster.py index 735e5fe88b..d8f5c5c500 100644 --- a/api/controllers/console/agent/roster.py +++ b/api/controllers/console/agent/roster.py @@ -6,10 +6,21 @@ from pydantic import BaseModel, Field from controllers.common.schema import query_params_from_model, register_response_schema_models, register_schema_models from controllers.console import console_ns +from controllers.console.app.app import ( + AppDetailWithSite, + AppListQuery, + AppPagination, + UpdateAppPayload, + _normalize_app_list_query_args, +) from controllers.console.wraps import ( account_initialization_required, + cloud_edition_billing_resource_check, + edit_permission_required, + enterprise_license_required, setup_required, with_current_tenant_id, + with_current_user, ) from extensions.ext_database import db from fields.agent_fields import ( @@ -18,12 +29,17 @@ from fields.agent_fields import ( AgentInviteOptionsResponse, AgentPublishedReferenceResponse, AgentRosterListResponse, - AgentRosterResponse, ) from libs.helper import dump_response from libs.login import login_required +from models import Account +from models.model import IconType +from services.agent.errors import AgentNotFoundError from services.agent.roster_service import AgentRosterService +from services.app_service import AppListParams, AppService, CreateAppParams +from services.enterprise.enterprise_service import EnterpriseService from services.entities.agent_entities import RosterListQuery +from services.feature_service import FeatureService class AgentInviteOptionsQuery(RosterListQuery): @@ -34,20 +50,32 @@ class AgentIdPath(BaseModel): agent_id: str +class AgentAppCreatePayload(BaseModel): + name: str = Field(..., min_length=1, description="Agent name") + description: str | None = Field(default=None, description="Agent description (max 400 chars)", max_length=400) + icon_type: IconType | None = Field(default=None, description="Icon type") + icon: str | None = Field(default=None, description="Icon") + icon_background: str | None = Field(default=None, description="Icon background color") + + register_schema_models( console_ns, + AgentAppCreatePayload, AgentInviteOptionsQuery, AgentIdPath, + AppListQuery, + UpdateAppPayload, RosterListQuery, ) register_response_schema_models( console_ns, + AppDetailWithSite, + AppPagination, AgentConfigSnapshotDetailResponse, AgentConfigSnapshotListResponse, AgentInviteOptionsResponse, AgentPublishedReferenceResponse, AgentRosterListResponse, - AgentRosterResponse, ) @@ -55,25 +83,138 @@ def _agent_roster_service() -> AgentRosterService: return AgentRosterService(db.session) -@console_ns.route("/agents") -class AgentRosterListApi(Resource): - @console_ns.doc(params=query_params_from_model(RosterListQuery)) - @console_ns.response(200, "Agent roster list", console_ns.models[AgentRosterListResponse.__name__]) +def _serialize_agent_app_detail(app_model) -> dict: + app_model = AppService().get_app(app_model) + if FeatureService.get_system_features().webapp_auth.enabled: + app_setting = EnterpriseService.WebAppAuth.get_app_access_mode_by_id(app_id=str(app_model.id)) + app_model.access_mode = app_setting.access_mode # type: ignore[attr-defined] + + payload = AppDetailWithSite.model_validate(app_model, from_attributes=True).model_dump(mode="json") + agent_id = payload.pop("bound_agent_id", None) + if not agent_id: + raise AgentNotFoundError() + payload["id"] = agent_id + return payload + + +def _serialize_agent_app_pagination(app_pagination) -> dict: + payload = AppPagination.model_validate(app_pagination, from_attributes=True).model_dump(mode="json") + for item in payload["data"]: + agent_id = item.pop("bound_agent_id", None) + if agent_id: + item["id"] = agent_id + return payload + + +def _resolve_agent_app_model(*, tenant_id: str, agent_id: UUID): + return _agent_roster_service().get_agent_app_model(tenant_id=tenant_id, agent_id=str(agent_id)) + + +@console_ns.route("/agent") +class AgentAppListApi(Resource): + @console_ns.doc(params=query_params_from_model(AppListQuery)) + @console_ns.response(200, "Agent app list", console_ns.models[AppPagination.__name__]) @setup_required @login_required @account_initialization_required + @with_current_user @with_current_tenant_id - def get(self, tenant_id: str): - query = RosterListQuery.model_validate(request.args.to_dict(flat=True)) - return dump_response( - AgentRosterListResponse, - _agent_roster_service().list_roster_agents( - tenant_id=tenant_id, page=query.page, limit=query.limit, keyword=query.keyword - ), + def get(self, current_tenant_id: str, current_user: Account): + args = AppListQuery.model_validate(_normalize_app_list_query_args(request.args)) + params = AppListParams( + page=args.page, + limit=args.limit, + mode="agent", + name=args.name, + tag_ids=args.tag_ids, + creator_ids=args.creator_ids, + is_created_by_me=args.is_created_by_me, + status="normal", ) + app_pagination = AppService().get_paginate_apps(current_user.id, current_tenant_id, params) + if app_pagination is None: + empty = AppPagination(page=args.page, limit=args.limit, total=0, has_more=False, data=[]) + return empty.model_dump(mode="json") -@console_ns.route("/agents/invite-options") + return _serialize_agent_app_pagination(app_pagination) + + @console_ns.expect(console_ns.models[AgentAppCreatePayload.__name__]) + @console_ns.response(201, "Agent app created successfully", console_ns.models[AppDetailWithSite.__name__]) + @console_ns.response(403, "Insufficient permissions") + @console_ns.response(400, "Invalid request parameters") + @setup_required + @login_required + @account_initialization_required + @cloud_edition_billing_resource_check("apps") + @edit_permission_required + @with_current_user + @with_current_tenant_id + def post(self, current_tenant_id: str, current_user: Account): + args = AgentAppCreatePayload.model_validate(console_ns.payload) + params = CreateAppParams( + name=args.name, + description=args.description, + mode="agent", + icon_type=args.icon_type, + icon=args.icon, + icon_background=args.icon_background, + ) + + app = AppService().create_app(current_tenant_id, params, current_user) + return _serialize_agent_app_detail(app), 201 + + +@console_ns.route("/agent/") +class AgentAppApi(Resource): + @console_ns.response(200, "Agent app detail", console_ns.models[AppDetailWithSite.__name__]) + @setup_required + @login_required + @account_initialization_required + @enterprise_license_required + @with_current_tenant_id + def get(self, tenant_id: str, agent_id: UUID): + app_model = _resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) + return _serialize_agent_app_detail(app_model) + + @console_ns.expect(console_ns.models[UpdateAppPayload.__name__]) + @console_ns.response(200, "Agent app updated successfully", console_ns.models[AppDetailWithSite.__name__]) + @console_ns.response(403, "Insufficient permissions") + @console_ns.response(400, "Invalid request parameters") + @setup_required + @login_required + @account_initialization_required + @edit_permission_required + @with_current_tenant_id + def put(self, tenant_id: str, agent_id: UUID): + app_model = _resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) + args = UpdateAppPayload.model_validate(console_ns.payload) + args_dict: AppService.ArgsDict = { + "name": args.name, + "description": args.description or "", + "icon_type": args.icon_type, + "icon": args.icon or "", + "icon_background": args.icon_background or "", + "use_icon_as_answer_icon": args.use_icon_as_answer_icon or False, + "max_active_requests": args.max_active_requests or 0, + } + updated = AppService().update_app(app_model, args_dict) + return _serialize_agent_app_detail(updated) + + @console_ns.response(204, "Agent app deleted successfully") + @console_ns.response(403, "Insufficient permissions") + @setup_required + @login_required + @account_initialization_required + @edit_permission_required + @with_current_tenant_id + def delete(self, tenant_id: str, agent_id: UUID): + app_model = _resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) + AppService().delete_app(app_model) + return "", 204 + + +@console_ns.route("/agent/invite-options") class AgentInviteOptionsApi(Resource): @console_ns.doc(params=query_params_from_model(AgentInviteOptionsQuery)) @console_ns.response(200, "Agent invite options", console_ns.models[AgentInviteOptionsResponse.__name__]) @@ -95,21 +236,7 @@ class AgentInviteOptionsApi(Resource): ) -@console_ns.route("/agents/") -class AgentRosterDetailApi(Resource): - @console_ns.response(200, "Agent detail", console_ns.models[AgentRosterResponse.__name__]) - @setup_required - @login_required - @account_initialization_required - @with_current_tenant_id - def get(self, tenant_id: str, agent_id: UUID): - return dump_response( - AgentRosterResponse, - _agent_roster_service().get_roster_agent_detail(tenant_id=tenant_id, agent_id=str(agent_id)), - ) - - -@console_ns.route("/agents//versions") +@console_ns.route("/agent//versions") class AgentRosterVersionsApi(Resource): @console_ns.response(200, "Agent versions", console_ns.models[AgentConfigSnapshotListResponse.__name__]) @setup_required @@ -123,7 +250,7 @@ class AgentRosterVersionsApi(Resource): ) -@console_ns.route("/agents//versions/") +@console_ns.route("/agent//versions/") class AgentRosterVersionDetailApi(Resource): @console_ns.response(200, "Agent version detail", console_ns.models[AgentConfigSnapshotDetailResponse.__name__]) @setup_required diff --git a/api/controllers/console/app/agent.py b/api/controllers/console/app/agent.py index 929aa1d1ff..23ccd28ad6 100644 --- a/api/controllers/console/app/agent.py +++ b/api/controllers/console/app/agent.py @@ -1,5 +1,6 @@ import logging from typing import Any +from uuid import UUID from flask import request from flask_restx import Resource @@ -13,8 +14,14 @@ from controllers.common.schema import ( register_schema_models, ) from controllers.console import console_ns +from controllers.console.agent.app_helpers import resolve_agent_app_model from controllers.console.app.wraps import get_app_model -from controllers.console.wraps import account_initialization_required, setup_required, with_current_user +from controllers.console.wraps import ( + account_initialization_required, + setup_required, + with_current_tenant_id, + with_current_user, +) from extensions.ext_database import db from fields.base import ResponseModel from libs.helper import uuid_value @@ -42,7 +49,7 @@ from services.file_service import FileService logger = logging.getLogger(__name__) -_AGENT_DRIVE_APP_MODES = [AppMode.AGENT, AppMode.WORKFLOW, AppMode.ADVANCED_CHAT] +_WORKFLOW_AGENT_DRIVE_APP_MODES = [AppMode.WORKFLOW, AppMode.ADVANCED_CHAT] class AgentLogQuery(BaseModel): @@ -72,6 +79,10 @@ class AgentDriveDeleteFileQuery(AgentDriveMutationQuery): key: str = Field(min_length=1, description="Drive key, e.g. files/sample.pdf") +class AgentDriveDeleteFileByAgentQuery(BaseModel): + key: str = Field(min_length=1, description="Drive key, e.g. files/sample.pdf") + + class AgentLogMetaResponse(ResponseModel): status: str executor: str @@ -138,7 +149,7 @@ class AgentDriveDeleteResponse(ResponseModel): config_version_id: str | None = None -register_schema_models(console_ns, AgentLogQuery, AgentDriveFilePayload) +register_schema_models(console_ns, AgentLogQuery, AgentDriveFilePayload, AgentDriveDeleteFileByAgentQuery) register_response_schema_models( console_ns, AgentDriveDeleteResponse, @@ -152,7 +163,7 @@ register_response_schema_models( def _resolve_agent_id(app_model: App, node_id: str | None) -> str | None: - if node_id: + if node_id and app_model.mode != AppMode.AGENT: return AgentComposerService.resolve_workflow_node_agent_id( tenant_id=app_model.tenant_id, app_id=app_model.id, node_id=node_id ) @@ -163,6 +174,192 @@ def _agent_not_bound() -> tuple[dict[str, str], int]: return {"code": "agent_not_bound", "message": "no agent is bound for this app/node"}, 400 +def _upload_skill_for_app(*, current_user: Account): + if "file" not in request.files: + return {"code": "no_file", "message": "no skill file uploaded"}, 400 + if len(request.files) > 1: + return {"code": "too_many_files", "message": "only one skill file is allowed"}, 400 + + upload = request.files["file"] + content = upload.stream.read() + try: + manifest = SkillPackageService().validate_and_extract(content=content, filename=upload.filename or "") + except SkillPackageError as exc: + return {"code": exc.code, "message": exc.message}, exc.status_code + + upload_file = FileService(db.engine).upload_file( + filename=upload.filename or "skill.zip", + content=content, + mimetype=upload.mimetype or "application/zip", + user=current_user, + ) + skill_ref = manifest.to_skill_ref(file_id=upload_file.id) + return {"skill": skill_ref.model_dump(exclude_none=True), "manifest": manifest.model_dump()}, 201 + + +def _standardize_skill_for_app(*, current_user: Account, app_model: App): + query = query_params_from_request(AgentDriveMutationQuery) + agent_id = _resolve_agent_id(app_model, query.node_id) + if not agent_id: + return _agent_not_bound() + if "file" not in request.files: + return {"code": "no_file", "message": "no skill file uploaded"}, 400 + if len(request.files) > 1: + return {"code": "too_many_files", "message": "only one skill file is allowed"}, 400 + + upload = request.files["file"] + content = upload.stream.read() + try: + result = SkillStandardizeService().standardize( + content=content, + filename=upload.filename or "", + tenant_id=app_model.tenant_id, + user_id=current_user.id, + agent_id=agent_id, + ) + except (SkillPackageError, AgentDriveError) as exc: + return {"code": exc.code, "message": exc.message}, exc.status_code + return result, 201 + + +def _commit_drive_file_for_app(*, current_user: Account, app_model: App, allow_node_id: bool = True): + query = query_params_from_request(AgentDriveMutationQuery) + node_id = query.node_id if allow_node_id else None + agent_id = _resolve_agent_id(app_model, node_id) + if not agent_id: + return _agent_not_bound() + payload = AgentDriveFilePayload.model_validate(console_ns.payload or {}) + + upload_file = db.session.scalar( + select(UploadFile).where( + UploadFile.id == payload.upload_file_id, + UploadFile.tenant_id == app_model.tenant_id, + ) + ) + if upload_file is None: + return {"code": "upload_file_not_found", "message": "upload file not found in this workspace"}, 404 + + try: + key = normalize_drive_key(f"files/{upload_file.name}") + committed = AgentDriveService().commit( + tenant_id=app_model.tenant_id, + user_id=current_user.id, + agent_id=agent_id, + items=[ + DriveCommitItem( + key=key, + file_ref=DriveFileRef(kind="upload_file", id=upload_file.id), + # ADD FILE uploads exist solely to live in the drive, so the + # drive owns (and physically cleans) the value on delete. + value_owned_by_drive=True, + ) + ], + ) + except AgentDriveError as exc: + return {"code": exc.code, "message": exc.message}, exc.status_code + + row = committed[0] + file_ref = AgentFileRefConfig.model_validate( + { + "id": row["key"], + "name": upload_file.name, + "file_id": upload_file.id, + "drive_key": row["key"], + "type": row.get("mime_type"), + "size": row.get("size"), + } + ) + config_version_id = AgentComposerService.add_drive_file_ref( + tenant_id=app_model.tenant_id, + agent_id=agent_id, + account_id=current_user.id, + file_ref=file_ref, + app_id=app_model.id, + node_id=node_id, + ) + return { + "file": { + "name": upload_file.name, + "drive_key": row["key"], + "file_id": upload_file.id, + "size": row.get("size"), + "mime_type": row.get("mime_type"), + }, + "config_version_id": config_version_id, + }, 201 + + +def _delete_drive_file_for_app(*, current_user: Account, app_model: App, allow_node_id: bool = True): + query = query_params_from_request(AgentDriveDeleteFileQuery) + node_id = query.node_id if allow_node_id else None + agent_id = _resolve_agent_id(app_model, node_id) + if not agent_id: + return _agent_not_bound() + try: + key = normalize_drive_key(query.key) + except AgentDriveError as exc: + return {"code": exc.code, "message": exc.message}, exc.status_code + + config_version_id = AgentComposerService.remove_drive_refs( + tenant_id=app_model.tenant_id, + agent_id=agent_id, + account_id=current_user.id, + file_key=key, + app_id=app_model.id, + node_id=node_id, + ) + removed_keys: list[str] = [] + try: + removed_keys = AgentDriveService().delete(tenant_id=app_model.tenant_id, agent_id=agent_id, key=key) + except AgentDriveError as exc: + return {"code": exc.code, "message": exc.message}, exc.status_code + except Exception: + # Soul-first ordering: the ref is already gone; orphan KV rows are + # harmless and an idempotent DELETE retry cleans them. + logger.exception("agent drive delete failed for key %s (soul already updated)", key) + return {"result": "success", "removed_keys": removed_keys, "config_version_id": config_version_id} + + +def _delete_skill_for_app(*, current_user: Account, app_model: App, slug: str, allow_node_id: bool = True): + query = query_params_from_request(AgentDriveMutationQuery) + node_id = query.node_id if allow_node_id else None + agent_id = _resolve_agent_id(app_model, node_id) + if not agent_id: + return _agent_not_bound() + if "/" in slug or not slug.strip(): + return {"code": "drive_key_invalid", "message": "skill slug must be a single path segment"}, 400 + + config_version_id = AgentComposerService.remove_drive_refs( + tenant_id=app_model.tenant_id, + agent_id=agent_id, + account_id=current_user.id, + skill_slug=slug, + app_id=app_model.id, + node_id=node_id, + ) + removed_keys: list[str] = [] + try: + removed_keys = AgentDriveService().delete(tenant_id=app_model.tenant_id, agent_id=agent_id, prefix=f"{slug}/") + except AgentDriveError as exc: + return {"code": exc.code, "message": exc.message}, exc.status_code + except Exception: + logger.exception("agent drive delete failed for skill %s (soul already updated)", slug) + return {"result": "success", "removed_keys": removed_keys, "config_version_id": config_version_id} + + +def _infer_skill_tools_for_app(*, app_model: App, slug: str): + query = query_params_from_request(AgentDriveMutationQuery) + agent_id = _resolve_agent_id(app_model, query.node_id) + if not agent_id: + return _agent_not_bound() + if "/" in slug or not slug.strip(): + return {"code": "drive_key_invalid", "message": "skill slug must be a single path segment"}, 400 + try: + return SkillToolInferenceService().infer(tenant_id=app_model.tenant_id, agent_id=agent_id, slug=slug) + except SkillToolInferenceError as exc: + return {"code": exc.code, "message": exc.message}, exc.status_code + + @console_ns.route("/apps//agent/logs") class AgentLogApi(Resource): @console_ns.doc("get_agent_logs") @@ -182,6 +379,23 @@ class AgentLogApi(Resource): return AgentService.get_agent_logs(app_model, args.conversation_id, args.message_id) +@console_ns.route("/agent//skills/upload") +class AgentSkillUploadByAgentApi(Resource): + @console_ns.doc("upload_agent_skill_by_agent") + @console_ns.doc(description="Upload + validate a Skill package for an Agent App") + @console_ns.doc(params={"agent_id": "Agent ID"}) + @console_ns.response(201, "Skill validated", console_ns.models[AgentSkillUploadResponse.__name__]) + @console_ns.response(400, "Invalid skill package") + @setup_required + @login_required + @account_initialization_required + @with_current_user + @with_current_tenant_id + def post(self, tenant_id: str, current_user: Account, agent_id: UUID): + resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) + return _upload_skill_for_app(current_user=current_user) + + @console_ns.route("/apps//agent/skills/upload") class AgentSkillUploadApi(Resource): @console_ns.doc("upload_agent_skill") @@ -192,7 +406,7 @@ class AgentSkillUploadApi(Resource): @setup_required @login_required @account_initialization_required - @get_app_model(mode=_AGENT_DRIVE_APP_MODES) + @get_app_model(mode=_WORKFLOW_AGENT_DRIVE_APP_MODES) @with_current_user def post(self, current_user: Account, app_model: App): """Validate an uploaded Skill package and persist the archive. @@ -200,26 +414,28 @@ class AgentSkillUploadApi(Resource): Returns a validated skill ref (to bind into the Agent soul config on save) plus its manifest. Standardizing into the agent drive is ENG-594. """ - if "file" not in request.files: - return {"code": "no_file", "message": "no skill file uploaded"}, 400 - if len(request.files) > 1: - return {"code": "too_many_files", "message": "only one skill file is allowed"}, 400 + return _upload_skill_for_app(current_user=current_user) - upload = request.files["file"] - content = upload.stream.read() - try: - manifest = SkillPackageService().validate_and_extract(content=content, filename=upload.filename or "") - except SkillPackageError as exc: - return {"code": exc.code, "message": exc.message}, exc.status_code - upload_file = FileService(db.engine).upload_file( - filename=upload.filename or "skill.zip", - content=content, - mimetype=upload.mimetype or "application/zip", - user=current_user, - ) - skill_ref = manifest.to_skill_ref(file_id=upload_file.id) - return {"skill": skill_ref.model_dump(exclude_none=True), "manifest": manifest.model_dump()}, 201 +@console_ns.route("/agent//skills/standardize") +class AgentSkillStandardizeByAgentApi(Resource): + @console_ns.doc("standardize_agent_skill_by_agent") + @console_ns.doc(description="Validate + standardize a Skill into an Agent App drive") + @console_ns.doc(params={"agent_id": "Agent ID"}) + @console_ns.response( + 201, + "Skill standardized into drive", + console_ns.models[AgentSkillStandardizeResponse.__name__], + ) + @console_ns.response(400, "Invalid skill package or no bound agent") + @setup_required + @login_required + @account_initialization_required + @with_current_user + @with_current_tenant_id + def post(self, tenant_id: str, current_user: Account, agent_id: UUID): + app_model = resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) + return _standardize_skill_for_app(current_user=current_user, app_model=app_model) @console_ns.route("/apps//agent/skills/standardize") @@ -236,32 +452,43 @@ class AgentSkillStandardizeApi(Resource): @setup_required @login_required @account_initialization_required - @get_app_model(mode=_AGENT_DRIVE_APP_MODES) + @get_app_model(mode=_WORKFLOW_AGENT_DRIVE_APP_MODES) @with_current_user def post(self, current_user: Account, app_model: App): """Upload a Skill, validate it, and standardize it into the app agent's drive.""" - query = query_params_from_request(AgentDriveMutationQuery) - agent_id = _resolve_agent_id(app_model, query.node_id) - if not agent_id: - return _agent_not_bound() - if "file" not in request.files: - return {"code": "no_file", "message": "no skill file uploaded"}, 400 - if len(request.files) > 1: - return {"code": "too_many_files", "message": "only one skill file is allowed"}, 400 + return _standardize_skill_for_app(current_user=current_user, app_model=app_model) - upload = request.files["file"] - content = upload.stream.read() - try: - result = SkillStandardizeService().standardize( - content=content, - filename=upload.filename or "", - tenant_id=app_model.tenant_id, - user_id=current_user.id, - agent_id=agent_id, - ) - except (SkillPackageError, AgentDriveError) as exc: - return {"code": exc.code, "message": exc.message}, exc.status_code - return result, 201 + +@console_ns.route("/agent//files") +class AgentDriveFilesByAgentApi(Resource): + @console_ns.doc("commit_agent_drive_file_by_agent") + @console_ns.doc(description="Commit an uploaded file into the Agent App drive under files/") + @console_ns.doc(params={"agent_id": "Agent ID"}) + @console_ns.expect(console_ns.models[AgentDriveFilePayload.__name__]) + @console_ns.response( + 201, "File committed into the agent drive", console_ns.models[AgentDriveFileCommitResponse.__name__] + ) + @setup_required + @login_required + @account_initialization_required + @with_current_user + @with_current_tenant_id + def post(self, tenant_id: str, current_user: Account, agent_id: UUID): + app_model = resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) + return _commit_drive_file_for_app(current_user=current_user, app_model=app_model, allow_node_id=False) + + @console_ns.doc("delete_agent_drive_file_by_agent") + @console_ns.doc(description="Delete one Agent App drive file by key") + @console_ns.doc(params={"agent_id": "Agent ID", **query_params_from_model(AgentDriveDeleteFileByAgentQuery)}) + @console_ns.response(200, "File removed", console_ns.models[AgentDriveDeleteResponse.__name__]) + @setup_required + @login_required + @account_initialization_required + @with_current_user + @with_current_tenant_id + def delete(self, tenant_id: str, current_user: Account, agent_id: UUID): + app_model = resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) + return _delete_drive_file_for_app(current_user=current_user, app_model=app_model, allow_node_id=False) @console_ns.route("/apps//agent/files") @@ -276,73 +503,11 @@ class AgentDriveFilesApi(Resource): @setup_required @login_required @account_initialization_required - @get_app_model(mode=_AGENT_DRIVE_APP_MODES) + @get_app_model(mode=_WORKFLOW_AGENT_DRIVE_APP_MODES) @with_current_user def post(self, current_user: Account, app_model: App): """ADD FILE: commit one uploaded file into the bound agent's drive.""" - query = query_params_from_request(AgentDriveMutationQuery) - agent_id = _resolve_agent_id(app_model, query.node_id) - if not agent_id: - return _agent_not_bound() - payload = AgentDriveFilePayload.model_validate(console_ns.payload or {}) - - upload_file = db.session.scalar( - select(UploadFile).where( - UploadFile.id == payload.upload_file_id, - UploadFile.tenant_id == app_model.tenant_id, - ) - ) - if upload_file is None: - return {"code": "upload_file_not_found", "message": "upload file not found in this workspace"}, 404 - - try: - key = normalize_drive_key(f"files/{upload_file.name}") - committed = AgentDriveService().commit( - tenant_id=app_model.tenant_id, - user_id=current_user.id, - agent_id=agent_id, - items=[ - DriveCommitItem( - key=key, - file_ref=DriveFileRef(kind="upload_file", id=upload_file.id), - # ADD FILE uploads exist solely to live in the drive, so the - # drive owns (and physically cleans) the value on delete. - value_owned_by_drive=True, - ) - ], - ) - except AgentDriveError as exc: - return {"code": exc.code, "message": exc.message}, exc.status_code - - row = committed[0] - file_ref = AgentFileRefConfig.model_validate( - { - "id": row["key"], - "name": upload_file.name, - "file_id": upload_file.id, - "drive_key": row["key"], - "type": row.get("mime_type"), - "size": row.get("size"), - } - ) - config_version_id = AgentComposerService.add_drive_file_ref( - tenant_id=app_model.tenant_id, - agent_id=agent_id, - account_id=current_user.id, - file_ref=file_ref, - app_id=app_model.id, - node_id=query.node_id, - ) - return { - "file": { - "name": upload_file.name, - "drive_key": row["key"], - "file_id": upload_file.id, - "size": row.get("size"), - "mime_type": row.get("mime_type"), - }, - "config_version_id": config_version_id, - }, 201 + return _commit_drive_file_for_app(current_user=current_user, app_model=app_model) @console_ns.doc("delete_agent_drive_file") @console_ns.doc(description="Delete one drive file by key; soul ref first, then the KV row (ENG-625 D5)") @@ -351,36 +516,26 @@ class AgentDriveFilesApi(Resource): @setup_required @login_required @account_initialization_required - @get_app_model(mode=_AGENT_DRIVE_APP_MODES) + @get_app_model(mode=_WORKFLOW_AGENT_DRIVE_APP_MODES) @with_current_user def delete(self, current_user: Account, app_model: App): - query = query_params_from_request(AgentDriveDeleteFileQuery) - agent_id = _resolve_agent_id(app_model, query.node_id) - if not agent_id: - return _agent_not_bound() - try: - key = normalize_drive_key(query.key) - except AgentDriveError as exc: - return {"code": exc.code, "message": exc.message}, exc.status_code + return _delete_drive_file_for_app(current_user=current_user, app_model=app_model) - config_version_id = AgentComposerService.remove_drive_refs( - tenant_id=app_model.tenant_id, - agent_id=agent_id, - account_id=current_user.id, - file_key=key, - app_id=app_model.id, - node_id=query.node_id, - ) - removed_keys: list[str] = [] - try: - removed_keys = AgentDriveService().delete(tenant_id=app_model.tenant_id, agent_id=agent_id, key=key) - except AgentDriveError as exc: - return {"code": exc.code, "message": exc.message}, exc.status_code - except Exception: - # Soul-first ordering: the ref is already gone; orphan KV rows are - # harmless and an idempotent DELETE retry cleans them. - logger.exception("agent drive delete failed for key %s (soul already updated)", key) - return {"result": "success", "removed_keys": removed_keys, "config_version_id": config_version_id} + +@console_ns.route("/agent//skills/") +class AgentSkillByAgentApi(Resource): + @console_ns.doc("delete_agent_skill_by_agent") + @console_ns.doc(description="Delete a standardized skill from an Agent App drive") + @console_ns.doc(params={"agent_id": "Agent ID", "slug": "Skill slug (single path segment)"}) + @console_ns.response(200, "Skill removed", console_ns.models[AgentDriveDeleteResponse.__name__]) + @setup_required + @login_required + @account_initialization_required + @with_current_user + @with_current_tenant_id + def delete(self, tenant_id: str, current_user: Account, agent_id: UUID, slug: str): + app_model = resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) + return _delete_skill_for_app(current_user=current_user, app_model=app_model, slug=slug, allow_node_id=False) @console_ns.route("/apps//agent/skills/") @@ -400,34 +555,29 @@ class AgentSkillApi(Resource): @setup_required @login_required @account_initialization_required - @get_app_model(mode=_AGENT_DRIVE_APP_MODES) + @get_app_model(mode=_WORKFLOW_AGENT_DRIVE_APP_MODES) @with_current_user def delete(self, current_user: Account, app_model: App, slug: str): - query = query_params_from_request(AgentDriveMutationQuery) - agent_id = _resolve_agent_id(app_model, query.node_id) - if not agent_id: - return _agent_not_bound() - if "/" in slug or not slug.strip(): - return {"code": "drive_key_invalid", "message": "skill slug must be a single path segment"}, 400 + return _delete_skill_for_app(current_user=current_user, app_model=app_model, slug=slug) - config_version_id = AgentComposerService.remove_drive_refs( - tenant_id=app_model.tenant_id, - agent_id=agent_id, - account_id=current_user.id, - skill_slug=slug, - app_id=app_model.id, - node_id=query.node_id, - ) - removed_keys: list[str] = [] - try: - removed_keys = AgentDriveService().delete( - tenant_id=app_model.tenant_id, agent_id=agent_id, prefix=f"{slug}/" - ) - except AgentDriveError as exc: - return {"code": exc.code, "message": exc.message}, exc.status_code - except Exception: - logger.exception("agent drive delete failed for skill %s (soul already updated)", slug) - return {"result": "success", "removed_keys": removed_keys, "config_version_id": config_version_id} + +@console_ns.route("/agent//skills//infer-tools") +class AgentSkillInferToolsByAgentApi(Resource): + @console_ns.doc("infer_agent_skill_tools_by_agent") + @console_ns.doc(description="Infer CLI tool + ENV suggestions from a standardized Agent App skill") + @console_ns.doc(params={"agent_id": "Agent ID", "slug": "Skill slug (single path segment)"}) + @console_ns.response( + 200, + "Inference result (draft suggestions, nothing persisted)", + console_ns.models[SkillToolInferenceResult.__name__], + ) + @setup_required + @login_required + @account_initialization_required + @with_current_tenant_id + def post(self, tenant_id: str, agent_id: UUID, slug: str): + app_model = resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) + return _infer_skill_tools_for_app(app_model=app_model, slug=slug) @console_ns.route("/apps//agent/skills//infer-tools") @@ -451,16 +601,7 @@ class AgentSkillInferToolsApi(Resource): @setup_required @login_required @account_initialization_required - @get_app_model(mode=_AGENT_DRIVE_APP_MODES) + @get_app_model(mode=_WORKFLOW_AGENT_DRIVE_APP_MODES) def post(self, app_model: App, slug: str): """Suggest CLI tools/env for a skill. Saving still goes through composer validation.""" - query = query_params_from_request(AgentDriveMutationQuery) - agent_id = _resolve_agent_id(app_model, query.node_id) - if not agent_id: - return _agent_not_bound() - if "/" in slug or not slug.strip(): - return {"code": "drive_key_invalid", "message": "skill slug must be a single path segment"}, 400 - try: - return SkillToolInferenceService().infer(tenant_id=app_model.tenant_id, agent_id=agent_id, slug=slug) - except SkillToolInferenceError as exc: - return {"code": exc.code, "message": exc.message}, exc.status_code + return _infer_skill_tools_for_app(app_model=app_model, slug=slug) diff --git a/api/controllers/console/app/agent_app_access.py b/api/controllers/console/app/agent_app_access.py index 97ff134490..aa236de158 100644 --- a/api/controllers/console/app/agent_app_access.py +++ b/api/controllers/console/app/agent_app_access.py @@ -5,17 +5,18 @@ reference. This exposes the read-only "Workflow access" surface from the PRD: which workflow apps use this Agent, without leaking the workflows' internals. """ +from uuid import UUID + from flask_restx import Resource from pydantic import Field from controllers.common.schema import register_response_schema_models from controllers.console import console_ns -from controllers.console.app.wraps import get_app_model +from controllers.console.agent.app_helpers import resolve_agent_app_model from controllers.console.wraps import account_initialization_required, setup_required, with_current_tenant_id from extensions.ext_database import db from fields.base import ResponseModel from libs.login import login_required -from models.model import App, AppMode from services.agent.roster_service import AgentRosterService @@ -34,23 +35,23 @@ class AgentReferencingWorkflowsResponse(ResponseModel): register_response_schema_models(console_ns, AgentReferencingWorkflowsResponse) -@console_ns.route("/apps//agent-referencing-workflows") +@console_ns.route("/agent//referencing-workflows") class AgentAppReferencingWorkflowsResource(Resource): @console_ns.doc("list_agent_app_referencing_workflows") @console_ns.doc(description="List workflow apps that reference this Agent App's bound Agent (read-only)") - @console_ns.doc(params={"app_id": "Application ID"}) + @console_ns.doc(params={"agent_id": "Agent ID"}) @console_ns.response( 200, "Referencing workflows listed successfully", console_ns.models[AgentReferencingWorkflowsResponse.__name__], ) - @console_ns.response(404, "App not found") + @console_ns.response(404, "Agent not found") @setup_required @login_required @account_initialization_required - @get_app_model(mode=[AppMode.AGENT]) @with_current_tenant_id - def get(self, tenant_id: str, app_model: App): + def get(self, tenant_id: str, agent_id: UUID): + app_model = resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) workflows = AgentRosterService(db.session).list_workflows_referencing_app_agent( tenant_id=tenant_id, app_id=app_model.id ) diff --git a/api/controllers/console/app/agent_app_feature.py b/api/controllers/console/app/agent_app_feature.py index 104fc391d5..79d7589873 100644 --- a/api/controllers/console/app/agent_app_feature.py +++ b/api/controllers/console/app/agent_app_feature.py @@ -9,17 +9,20 @@ persists them onto the app's ``app_model_config`` without touching anything the Soul owns. """ +from uuid import UUID + from flask_restx import Resource from pydantic import BaseModel, Field from controllers.common.fields import SimpleResultResponse from controllers.common.schema import register_response_schema_models, register_schema_models from controllers.console import console_ns -from controllers.console.app.wraps import get_app_model +from controllers.console.agent.app_helpers import resolve_agent_app_model from controllers.console.wraps import ( account_initialization_required, edit_permission_required, setup_required, + with_current_tenant_id, with_current_user, ) from events.app_event import app_model_config_was_updated @@ -32,7 +35,6 @@ from models.agent_config_entities import ( AgentSuggestedQuestionsAfterAnswerFeatureConfig, AgentTextToSpeechFeatureConfig, ) -from models.model import App, AppMode from services.agent_app_feature_service import AgentAppFeatureConfigService @@ -64,22 +66,23 @@ register_schema_models(console_ns, AgentAppFeaturesPayload) register_response_schema_models(console_ns, SimpleResultResponse) -@console_ns.route("/apps//agent-features") +@console_ns.route("/agent//features") class AgentAppFeatureConfigResource(Resource): @console_ns.doc("update_agent_app_features") @console_ns.doc(description="Update an Agent App's presentation features (opener, follow-up, citations, ...)") - @console_ns.doc(params={"app_id": "Application ID"}) + @console_ns.doc(params={"agent_id": "Agent ID"}) @console_ns.expect(console_ns.models[AgentAppFeaturesPayload.__name__]) @console_ns.response(200, "Features updated successfully", console_ns.models[SimpleResultResponse.__name__]) @console_ns.response(400, "Invalid configuration") - @console_ns.response(404, "App not found") + @console_ns.response(404, "Agent not found") @setup_required @login_required @edit_permission_required @account_initialization_required - @get_app_model(mode=[AppMode.AGENT]) @with_current_user - def post(self, current_user: Account, app_model: App): + @with_current_tenant_id + def post(self, tenant_id: str, current_user: Account, agent_id: UUID): + app_model = resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) args = AgentAppFeaturesPayload.model_validate(console_ns.payload or {}) new_app_model_config = AgentAppFeatureConfigService.update_features( diff --git a/api/controllers/console/app/agent_app_sandbox.py b/api/controllers/console/app/agent_app_sandbox.py index b59d66c743..f9bda13c63 100644 --- a/api/controllers/console/app/agent_app_sandbox.py +++ b/api/controllers/console/app/agent_app_sandbox.py @@ -22,6 +22,7 @@ from controllers.common.schema import ( register_schema_models, ) from controllers.console import console_ns +from controllers.console.agent.app_helpers import resolve_agent_app_model from controllers.console.app.wraps import get_app_model from controllers.console.wraps import account_initialization_required, setup_required, with_current_tenant_id from fields.base import ResponseModel @@ -132,18 +133,18 @@ def _handle(exc: Exception) -> tuple[dict[str, object], int]: raise exc -@console_ns.route("/apps//agent-sandbox/files") +@console_ns.route("/agent//sandbox/files") class AgentAppSandboxListResource(Resource): @console_ns.doc("list_agent_app_sandbox_files") @console_ns.doc(description="List a directory in an Agent App conversation sandbox") - @console_ns.doc(params={"app_id": "Application ID", **query_params_from_model(AgentSandboxListQuery)}) + @console_ns.doc(params={"agent_id": "Agent ID", **query_params_from_model(AgentSandboxListQuery)}) @console_ns.response(200, "Listing returned", console_ns.models[SandboxListResponse.__name__]) @setup_required @login_required @account_initialization_required - @get_app_model(mode=[AppMode.AGENT]) @with_current_tenant_id - def get(self, tenant_id: str, app_model: App): + def get(self, tenant_id: str, agent_id: UUID): + app_model = resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) query = query_params_from_request(AgentSandboxListQuery) try: result = AgentAppSandboxService().list_files( @@ -157,18 +158,18 @@ class AgentAppSandboxListResource(Resource): return result.model_dump() -@console_ns.route("/apps//agent-sandbox/files/read") +@console_ns.route("/agent//sandbox/files/read") class AgentAppSandboxReadResource(Resource): @console_ns.doc("read_agent_app_sandbox_file") @console_ns.doc(description="Read a text/binary preview file in an Agent App conversation sandbox") - @console_ns.doc(params={"app_id": "Application ID", **query_params_from_model(AgentSandboxFileQuery)}) + @console_ns.doc(params={"agent_id": "Agent ID", **query_params_from_model(AgentSandboxFileQuery)}) @console_ns.response(200, "Preview returned", console_ns.models[SandboxReadResponse.__name__]) @setup_required @login_required @account_initialization_required - @get_app_model(mode=[AppMode.AGENT]) @with_current_tenant_id - def get(self, tenant_id: str, app_model: App): + def get(self, tenant_id: str, agent_id: UUID): + app_model = resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) query = query_params_from_request(AgentSandboxFileQuery) try: result = AgentAppSandboxService().read_file( @@ -182,7 +183,7 @@ class AgentAppSandboxReadResource(Resource): return result.model_dump() -@console_ns.route("/apps//agent-sandbox/files/upload") +@console_ns.route("/agent//sandbox/files/upload") class AgentAppSandboxUploadResource(Resource): @console_ns.doc("upload_agent_app_sandbox_file") @console_ns.doc(description="Upload one Agent App sandbox file as a Dify ToolFile mapping") @@ -191,9 +192,9 @@ class AgentAppSandboxUploadResource(Resource): @setup_required @login_required @account_initialization_required - @get_app_model(mode=[AppMode.AGENT]) @with_current_tenant_id - def post(self, tenant_id: str, app_model: App): + def post(self, tenant_id: str, agent_id: UUID): + app_model = resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) payload = AgentSandboxUploadPayload.model_validate(request.get_json(silent=True) or {}) try: result = AgentAppSandboxService().upload_file( diff --git a/api/controllers/console/app/agent_drive_inspector.py b/api/controllers/console/app/agent_drive_inspector.py index ff5b87fc28..b8d1d48780 100644 --- a/api/controllers/console/app/agent_drive_inspector.py +++ b/api/controllers/console/app/agent_drive_inspector.py @@ -10,6 +10,8 @@ backend — drive data lives in the API's own DB/storage, served straight from from __future__ import annotations +from uuid import UUID + from flask_restx import Resource from pydantic import BaseModel, Field @@ -19,8 +21,9 @@ from controllers.common.schema import ( register_response_schema_models, ) from controllers.console import console_ns +from controllers.console.agent.app_helpers import resolve_agent_app_model from controllers.console.app.wraps import get_app_model -from controllers.console.wraps import account_initialization_required, setup_required +from controllers.console.wraps import account_initialization_required, setup_required, with_current_tenant_id from fields.base import ResponseModel from libs.login import login_required from models.model import App, AppMode @@ -33,11 +36,19 @@ class AgentDriveListQuery(BaseModel): node_id: str | None = Field(default=None, description="Workflow node ID (workflow composer variant)") +class AgentDriveListByAgentQuery(BaseModel): + prefix: str = Field(default="", description="Key prefix filter: '/' for one skill, 'files/' for files") + + class AgentDriveFileQuery(BaseModel): key: str = Field(min_length=1, description="Drive key, e.g. tender-analyzer/SKILL.md") node_id: str | None = Field(default=None, description="Workflow node ID (workflow composer variant)") +class AgentDriveFileByAgentQuery(BaseModel): + key: str = Field(min_length=1, description="Drive key, e.g. tender-analyzer/SKILL.md") + + class AgentDriveItemResponse(ResponseModel): key: str size: int | None = None @@ -85,7 +96,66 @@ def _handle(exc: AgentDriveError) -> tuple[dict[str, object], int]: return {"code": exc.code, "message": exc.message}, exc.status_code -_APP_MODES = [AppMode.AGENT, AppMode.WORKFLOW, AppMode.ADVANCED_CHAT] +_WORKFLOW_APP_MODES = [AppMode.WORKFLOW, AppMode.ADVANCED_CHAT] + + +@console_ns.route("/agent//drive/files") +class AgentDriveListByAgentApi(Resource): + @console_ns.doc("list_agent_drive_files_by_agent") + @console_ns.doc(description="List agent drive entries for an Agent App") + @console_ns.doc(params={"agent_id": "Agent ID", **query_params_from_model(AgentDriveListByAgentQuery)}) + @console_ns.response(200, "Drive entries", console_ns.models[AgentDriveListResponse.__name__]) + @setup_required + @login_required + @account_initialization_required + @with_current_tenant_id + def get(self, tenant_id: str, agent_id: UUID): + query = query_params_from_request(AgentDriveListByAgentQuery) + resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) + try: + items = AgentDriveService().manifest(tenant_id=tenant_id, agent_id=str(agent_id), prefix=query.prefix) + except AgentDriveError as exc: + return _handle(exc) + return {"items": [{k: v for k, v in item.items() if k != "file_id"} for item in items]} + + +@console_ns.route("/agent//drive/files/preview") +class AgentDrivePreviewByAgentApi(Resource): + @console_ns.doc("preview_agent_drive_file_by_agent") + @console_ns.doc(description="Truncated text preview of one Agent App drive value") + @console_ns.doc(params={"agent_id": "Agent ID", **query_params_from_model(AgentDriveFileByAgentQuery)}) + @console_ns.response(200, "Preview", console_ns.models[AgentDrivePreviewResponse.__name__]) + @setup_required + @login_required + @account_initialization_required + @with_current_tenant_id + def get(self, tenant_id: str, agent_id: UUID): + query = query_params_from_request(AgentDriveFileByAgentQuery) + resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) + try: + return AgentDriveService().preview(tenant_id=tenant_id, agent_id=str(agent_id), key=query.key) + except AgentDriveError as exc: + return _handle(exc) + + +@console_ns.route("/agent//drive/files/download") +class AgentDriveDownloadByAgentApi(Resource): + @console_ns.doc("download_agent_drive_file_by_agent") + @console_ns.doc(description="Time-limited external signed URL for one Agent App drive value") + @console_ns.doc(params={"agent_id": "Agent ID", **query_params_from_model(AgentDriveFileByAgentQuery)}) + @console_ns.response(200, "Signed URL", console_ns.models[AgentDriveDownloadResponse.__name__]) + @setup_required + @login_required + @account_initialization_required + @with_current_tenant_id + def get(self, tenant_id: str, agent_id: UUID): + query = query_params_from_request(AgentDriveFileByAgentQuery) + resolve_agent_app_model(tenant_id=tenant_id, agent_id=agent_id) + try: + url = AgentDriveService().download_url(tenant_id=tenant_id, agent_id=str(agent_id), key=query.key) + except AgentDriveError as exc: + return _handle(exc) + return {"url": url} @console_ns.route("/apps//agent/drive/files") @@ -97,7 +167,7 @@ class AgentDriveListApi(Resource): @setup_required @login_required @account_initialization_required - @get_app_model(mode=_APP_MODES) + @get_app_model(mode=_WORKFLOW_APP_MODES) def get(self, app_model: App): query = query_params_from_request(AgentDriveListQuery) agent_id = _resolve_agent_id(app_model, query.node_id) @@ -121,7 +191,7 @@ class AgentDrivePreviewApi(Resource): @setup_required @login_required @account_initialization_required - @get_app_model(mode=_APP_MODES) + @get_app_model(mode=_WORKFLOW_APP_MODES) def get(self, app_model: App): query = query_params_from_request(AgentDriveFileQuery) agent_id = _resolve_agent_id(app_model, query.node_id) @@ -142,7 +212,7 @@ class AgentDriveDownloadApi(Resource): @setup_required @login_required @account_initialization_required - @get_app_model(mode=_APP_MODES) + @get_app_model(mode=_WORKFLOW_APP_MODES) def get(self, app_model: App): query = query_params_from_request(AgentDriveFileQuery) agent_id = _resolve_agent_id(app_model, query.node_id) @@ -157,6 +227,9 @@ class AgentDriveDownloadApi(Resource): __all__ = [ "AgentDriveDownloadApi", + "AgentDriveDownloadByAgentApi", "AgentDriveListApi", + "AgentDriveListByAgentApi", "AgentDrivePreviewApi", + "AgentDrivePreviewByAgentApi", ] diff --git a/api/controllers/console/app/app.py b/api/controllers/console/app/app.py index 7d0656e862..750530346c 100644 --- a/api/controllers/console/app/app.py +++ b/api/controllers/console/app/app.py @@ -64,7 +64,7 @@ from services.entities.knowledge_entities.knowledge_entities import ( ) from services.feature_service import FeatureService -ALLOW_CREATE_APP_MODES = ["chat", "agent-chat", "agent", "advanced-chat", "workflow", "completion"] +ALLOW_CREATE_APP_MODES = ["chat", "agent-chat", "advanced-chat", "workflow", "completion"] register_enum_models(console_ns, IconType) @@ -163,9 +163,7 @@ def _normalize_app_list_query_args(query_args: MultiDict[str, str]) -> dict[str, class CreateAppPayload(BaseModel): name: str = Field(..., min_length=1, description="App name") description: str | None = Field(default=None, description="App description (max 400 chars)", max_length=400) - mode: Literal["chat", "agent-chat", "agent", "advanced-chat", "workflow", "completion"] = Field( - ..., description="App mode" - ) + mode: Literal["chat", "agent-chat", "advanced-chat", "workflow", "completion"] = Field(..., description="App mode") icon_type: IconType | None = Field(default=None, description="Icon type") icon: str | None = Field(default=None, description="Icon") icon_background: str | None = Field(default=None, description="Icon background color") @@ -400,6 +398,8 @@ class AppPartial(ResponseModel): create_user_name: str | None = None author_name: str | None = None has_draft_trigger: bool | None = None + # For Agent App type: the roster Agent backing this app (None otherwise). + bound_agent_id: str | None = None is_starred: bool = False @computed_field(return_type=str | None) # type: ignore diff --git a/api/openapi/markdown/console-openapi.md b/api/openapi/markdown/console-openapi.md index 682822a6e4..2623d45f6f 100644 --- a/api/openapi/markdown/console-openapi.md +++ b/api/openapi/markdown/console-openapi.md @@ -293,22 +293,42 @@ Check if activation token is valid | ---- | ----------- | ------ | | 200 | Success | **application/json**: [ActivationCheckResponse](#activationcheckresponse)
| -### [GET] /agents +### [GET] /agent #### Parameters | Name | Located in | Description | Required | Schema | | ---- | ---------- | ----------- | -------- | ------ | -| keyword | query | | No | string | -| limit | query | | No | integer,
**Default:** 20 | -| page | query | | No | integer,
**Default:** 1 | +| creator_ids | query | Filter by creator account IDs | No | [ string ] | +| is_created_by_me | query | Filter by creator | No | boolean | +| limit | query | Page size (1-100) | No | integer,
**Default:** 20 | +| mode | query | App mode filter | No | string,
**Available values:** "advanced-chat", "agent", "agent-chat", "all", "channel", "chat", "completion", "workflow",
**Default:** all | +| name | query | Filter by app name | No | string | +| page | query | Page number (1-99999) | No | integer,
**Default:** 1 | +| sort_by | query | Sort apps by last modified, recently created, or earliest created | No | string,
**Available values:** "earliest_created", "last_modified", "recently_created",
**Default:** last_modified | +| tag_ids | query | Filter by tag IDs | No | [ string ] | #### Responses | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Agent roster list | **application/json**: [AgentRosterListResponse](#agentrosterlistresponse)
| +| 200 | Agent app list | **application/json**: [AppPagination](#apppagination)
| -### [GET] /agents/invite-options +### [POST] /agent +#### Request Body + +| Required | Schema | +| -------- | ------ | +| Yes | **application/json**: [AgentAppCreatePayload](#agentappcreatepayload)
| + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 201 | Agent app created successfully | **application/json**: [AppDetailWithSite](#appdetailwithsite)
| +| 400 | Invalid request parameters | | +| 403 | Insufficient permissions | | + +### [GET] /agent/invite-options #### Parameters | Name | Located in | Description | Required | Schema | @@ -324,7 +344,21 @@ Check if activation token is valid | ---- | ----------- | ------ | | 200 | Agent invite options | **application/json**: [AgentInviteOptionsResponse](#agentinviteoptionsresponse)
| -### [GET] /agents/{agent_id} +### [DELETE] /agent/{agent_id} +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | | Yes | string | + +#### Responses + +| Code | Description | +| ---- | ----------- | +| 204 | Agent app deleted successfully | +| 403 | Insufficient permissions | + +### [GET] /agent/{agent_id} #### Parameters | Name | Located in | Description | Required | Schema | @@ -335,9 +369,337 @@ Check if activation token is valid | Code | Description | Schema | | ---- | ----------- | ------ | -| 200 | Agent detail | **application/json**: [AgentRosterResponse](#agentrosterresponse)
| +| 200 | Agent app detail | **application/json**: [AppDetailWithSite](#appdetailwithsite)
| -### [GET] /agents/{agent_id}/versions +### [PUT] /agent/{agent_id} +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | | Yes | string | + +#### Request Body + +| Required | Schema | +| -------- | ------ | +| Yes | **application/json**: [UpdateAppPayload](#updateapppayload)
| + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Agent app updated successfully | **application/json**: [AppDetailWithSite](#appdetailwithsite)
| +| 400 | Invalid request parameters | | +| 403 | Insufficient permissions | | + +### [GET] /agent/{agent_id}/composer +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | | Yes | string | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Agent app composer state | **application/json**: [AgentAppComposerResponse](#agentappcomposerresponse)
| + +### [PUT] /agent/{agent_id}/composer +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | | Yes | string | + +#### Request Body + +| Required | Schema | +| -------- | ------ | +| Yes | **application/json**: [ComposerSavePayload](#composersavepayload)
| + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Agent app composer saved | **application/json**: [AgentAppComposerResponse](#agentappcomposerresponse)
| + +### [GET] /agent/{agent_id}/composer/candidates +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | | Yes | string | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Agent app composer candidates | **application/json**: [AgentComposerCandidatesResponse](#agentcomposercandidatesresponse)
| + +### [POST] /agent/{agent_id}/composer/validate +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | | Yes | string | + +#### Request Body + +| Required | Schema | +| -------- | ------ | +| Yes | **application/json**: [ComposerSavePayload](#composersavepayload)
| + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Agent app composer validation result | **application/json**: [AgentComposerValidateResponse](#agentcomposervalidateresponse)
| + +### [GET] /agent/{agent_id}/drive/files +List agent drive entries for an Agent App + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | +| prefix | query | Key prefix filter: '/' for one skill, 'files/' for files | No | string | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Drive entries | **application/json**: [AgentDriveListResponse](#agentdrivelistresponse)
| + +### [GET] /agent/{agent_id}/drive/files/download +Time-limited external signed URL for one Agent App drive value + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | +| key | query | Drive key, e.g. tender-analyzer/SKILL.md | Yes | string | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Signed URL | **application/json**: [AgentDriveDownloadResponse](#agentdrivedownloadresponse)
| + +### [GET] /agent/{agent_id}/drive/files/preview +Truncated text preview of one Agent App drive value + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | +| key | query | Drive key, e.g. tender-analyzer/SKILL.md | Yes | string | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Preview | **application/json**: [AgentDrivePreviewResponse](#agentdrivepreviewresponse)
| + +### [POST] /agent/{agent_id}/features +Update an Agent App's presentation features (opener, follow-up, citations, ...) + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | + +#### Request Body + +| Required | Schema | +| -------- | ------ | +| Yes | **application/json**: [AgentAppFeaturesPayload](#agentappfeaturespayload)
| + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Features updated successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)
| +| 400 | Invalid configuration | | +| 404 | Agent not found | | + +### [DELETE] /agent/{agent_id}/files +Delete one Agent App drive file by key + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | +| key | query | Drive key, e.g. files/sample.pdf | Yes | string | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | File removed | **application/json**: [AgentDriveDeleteResponse](#agentdrivedeleteresponse)
| + +### [POST] /agent/{agent_id}/files +Commit an uploaded file into the Agent App drive under files/ + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | + +#### Request Body + +| Required | Schema | +| -------- | ------ | +| Yes | **application/json**: [AgentDriveFilePayload](#agentdrivefilepayload)
| + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 201 | File committed into the agent drive | **application/json**: [AgentDriveFileCommitResponse](#agentdrivefilecommitresponse)
| + +### [GET] /agent/{agent_id}/referencing-workflows +List workflow apps that reference this Agent App's bound Agent (read-only) + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Referencing workflows listed successfully | **application/json**: [AgentReferencingWorkflowsResponse](#agentreferencingworkflowsresponse)
| +| 404 | Agent not found | | + +### [GET] /agent/{agent_id}/sandbox/files +List a directory in an Agent App conversation sandbox + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | +| conversation_id | query | Agent App conversation ID | Yes | string | +| path | query | Directory path relative to the sandbox workspace | No | string,
**Default:** . | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Listing returned | **application/json**: [SandboxListResponse](#sandboxlistresponse)
| + +### [GET] /agent/{agent_id}/sandbox/files/read +Read a text/binary preview file in an Agent App conversation sandbox + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | +| conversation_id | query | Agent App conversation ID | Yes | string | +| path | query | File path relative to the sandbox workspace | Yes | string | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Preview returned | **application/json**: [SandboxReadResponse](#sandboxreadresponse)
| + +### [POST] /agent/{agent_id}/sandbox/files/upload +Upload one Agent App sandbox file as a Dify ToolFile mapping + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | | Yes | string | + +#### Request Body + +| Required | Schema | +| -------- | ------ | +| Yes | **application/json**: [AgentSandboxUploadPayload](#agentsandboxuploadpayload)
| + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Uploaded | **application/json**: [SandboxUploadResponse](#sandboxuploadresponse)
| + +### [POST] /agent/{agent_id}/skills/standardize +Validate + standardize a Skill into an Agent App drive + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 201 | Skill standardized into drive | **application/json**: [AgentSkillStandardizeResponse](#agentskillstandardizeresponse)
| +| 400 | Invalid skill package or no bound agent | | + +### [POST] /agent/{agent_id}/skills/upload +Upload + validate a Skill package for an Agent App + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 201 | Skill validated | **application/json**: [AgentSkillUploadResponse](#agentskilluploadresponse)
| +| 400 | Invalid skill package | | + +### [DELETE] /agent/{agent_id}/skills/{slug} +Delete a standardized skill from an Agent App drive + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | +| slug | path | Skill slug (single path segment) | Yes | string | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Skill removed | **application/json**: [AgentDriveDeleteResponse](#agentdrivedeleteresponse)
| + +### [POST] /agent/{agent_id}/skills/{slug}/infer-tools +Infer CLI tool + ENV suggestions from a standardized Agent App skill + +#### Parameters + +| Name | Located in | Description | Required | Schema | +| ---- | ---------- | ----------- | -------- | ------ | +| agent_id | path | Agent ID | Yes | string | +| slug | path | Skill slug (single path segment) | Yes | string | + +#### Responses + +| Code | Description | Schema | +| ---- | ----------- | ------ | +| 200 | Inference result (draft suggestions, nothing persisted) | **application/json**: [SkillToolInferenceResult](#skilltoolinferenceresult)
| + +### [GET] /agent/{agent_id}/versions #### Parameters | Name | Located in | Description | Required | Schema | @@ -350,7 +712,7 @@ Check if activation token is valid | ---- | ----------- | ------ | | 200 | Agent versions | **application/json**: [AgentConfigSnapshotListResponse](#agentconfigsnapshotlistresponse)
| -### [GET] /agents/{agent_id}/versions/{version_id} +### [GET] /agent/{agent_id}/versions/{version_id} #### Parameters | Name | Located in | Description | Required | Schema | @@ -862,164 +1224,6 @@ Run draft workflow for advanced chat application | 400 | Invalid request parameters | | | 403 | Permission denied | | -### [GET] /apps/{app_id}/agent-composer -#### Parameters - -| Name | Located in | Description | Required | Schema | -| ---- | ---------- | ----------- | -------- | ------ | -| app_id | path | | Yes | string | - -#### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Agent app composer state | **application/json**: [AgentAppComposerResponse](#agentappcomposerresponse)
| - -### [PUT] /apps/{app_id}/agent-composer -#### Parameters - -| Name | Located in | Description | Required | Schema | -| ---- | ---------- | ----------- | -------- | ------ | -| app_id | path | | Yes | string | - -#### Request Body - -| Required | Schema | -| -------- | ------ | -| Yes | **application/json**: [ComposerSavePayload](#composersavepayload)
| - -#### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Agent app composer saved | **application/json**: [AgentAppComposerResponse](#agentappcomposerresponse)
| - -### [GET] /apps/{app_id}/agent-composer/candidates -#### Parameters - -| Name | Located in | Description | Required | Schema | -| ---- | ---------- | ----------- | -------- | ------ | -| app_id | path | | Yes | string | - -#### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Agent app composer candidates | **application/json**: [AgentComposerCandidatesResponse](#agentcomposercandidatesresponse)
| - -### [POST] /apps/{app_id}/agent-composer/validate -#### Parameters - -| Name | Located in | Description | Required | Schema | -| ---- | ---------- | ----------- | -------- | ------ | -| app_id | path | | Yes | string | - -#### Request Body - -| Required | Schema | -| -------- | ------ | -| Yes | **application/json**: [ComposerSavePayload](#composersavepayload)
| - -#### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Agent app composer validation result | **application/json**: [AgentComposerValidateResponse](#agentcomposervalidateresponse)
| - -### [POST] /apps/{app_id}/agent-features -Update an Agent App's presentation features (opener, follow-up, citations, ...) - -#### Parameters - -| Name | Located in | Description | Required | Schema | -| ---- | ---------- | ----------- | -------- | ------ | -| app_id | path | Application ID | Yes | string | - -#### Request Body - -| Required | Schema | -| -------- | ------ | -| Yes | **application/json**: [AgentAppFeaturesPayload](#agentappfeaturespayload)
| - -#### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Features updated successfully | **application/json**: [SimpleResultResponse](#simpleresultresponse)
| -| 400 | Invalid configuration | | -| 404 | App not found | | - -### [GET] /apps/{app_id}/agent-referencing-workflows -List workflow apps that reference this Agent App's bound Agent (read-only) - -#### Parameters - -| Name | Located in | Description | Required | Schema | -| ---- | ---------- | ----------- | -------- | ------ | -| app_id | path | Application ID | Yes | string | - -#### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Referencing workflows listed successfully | **application/json**: [AgentReferencingWorkflowsResponse](#agentreferencingworkflowsresponse)
| -| 404 | App not found | | - -### [GET] /apps/{app_id}/agent-sandbox/files -List a directory in an Agent App conversation sandbox - -#### Parameters - -| Name | Located in | Description | Required | Schema | -| ---- | ---------- | ----------- | -------- | ------ | -| app_id | path | Application ID | Yes | string | -| conversation_id | query | Agent App conversation ID | Yes | string | -| path | query | Directory path relative to the sandbox workspace | No | string,
**Default:** . | - -#### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Listing returned | **application/json**: [SandboxListResponse](#sandboxlistresponse)
| - -### [GET] /apps/{app_id}/agent-sandbox/files/read -Read a text/binary preview file in an Agent App conversation sandbox - -#### Parameters - -| Name | Located in | Description | Required | Schema | -| ---- | ---------- | ----------- | -------- | ------ | -| app_id | path | Application ID | Yes | string | -| conversation_id | query | Agent App conversation ID | Yes | string | -| path | query | File path relative to the sandbox workspace | Yes | string | - -#### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Preview returned | **application/json**: [SandboxReadResponse](#sandboxreadresponse)
| - -### [POST] /apps/{app_id}/agent-sandbox/files/upload -Upload one Agent App sandbox file as a Dify ToolFile mapping - -#### Parameters - -| Name | Located in | Description | Required | Schema | -| ---- | ---------- | ----------- | -------- | ------ | -| app_id | path | | Yes | string | - -#### Request Body - -| Required | Schema | -| -------- | ------ | -| Yes | **application/json**: [AgentSandboxUploadPayload](#agentsandboxuploadpayload)
| - -#### Responses - -| Code | Description | Schema | -| ---- | ----------- | ------ | -| 200 | Uploaded | **application/json**: [SandboxUploadResponse](#sandboxuploadresponse)
| - ### [GET] /apps/{app_id}/agent/drive/files List agent drive entries (read-only inspector; one endpoint for both tabs) @@ -10982,6 +11186,16 @@ Default namespace | validation | [ComposerValidationFindingsResponse](#composervalidationfindingsresponse) | | No | | variant | string | | Yes | +#### AgentAppCreatePayload + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| description | string | Agent description (max 400 chars) | No | +| icon | string | Icon | No | +| icon_background | string | Icon background color | No | +| icon_type | [IconType](#icontype) | Icon type | No | +| name | string | Agent name | Yes | + #### AgentAppFeaturesPayload Presentation features configurable on an Agent App. @@ -11239,6 +11453,12 @@ Audit operation recorded for Agent Soul version/revision changes. | version | integer | | Yes | | version_note | string | | No | +#### AgentDriveDeleteFileByAgentQuery + +| Name | Type | Description | Required | +| ---- | ---- | ----------- | -------- | +| key | string | Drive key, e.g. files/sample.pdf | Yes | + #### AgentDriveDeleteResponse | Name | Type | Description | Required | @@ -12182,7 +12402,6 @@ Enum class for api provider schema type. | ---- | ---- | ----------- | -------- | | access_mode | string | | No | | api_base_url | string | | No | -| app_model_config | [ModelConfig](#modelconfig) | | No | | bound_agent_id | string | | No | | created_at | integer | | No | | created_by | string | | No | @@ -12193,9 +12412,11 @@ Enum class for api provider schema type. | icon | string | | No | | icon_background | string | | No | | icon_type | string | | No | +| icon_url | string | | Yes | | id | string | | Yes | | max_active_requests | integer | | No | -| mode_compatible_with_agent | string | | Yes | +| mode | string | | Yes | +| model_config | [ModelConfig](#modelconfig) | | No | | name | string | | Yes | | site | [Site](#site) | | No | | tags | [ [Tag](#tag) ] | | No | @@ -12290,10 +12511,10 @@ AppMCPServer Status Enum | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | -| has_next | boolean | | Yes | -| items | [ [AppPartial](#apppartial) ] | | Yes | +| data | [ [AppPartial](#apppartial) ] | | Yes | +| has_more | boolean | | Yes | +| limit | integer | | Yes | | page | integer | | Yes | -| per_page | integer | | Yes | | total | integer | | Yes | #### AppPartial @@ -12301,20 +12522,22 @@ AppMCPServer Status Enum | Name | Type | Description | Required | | ---- | ---- | ----------- | -------- | | access_mode | string | | No | -| app_model_config | [ModelConfigPartial](#modelconfigpartial) | | No | | author_name | string | | No | +| bound_agent_id | string | | No | | create_user_name | string | | No | | created_at | integer | | No | | created_by | string | | No | -| desc_or_prompt | string | | No | +| description | string | | No | | has_draft_trigger | boolean | | No | | icon | string | | No | | icon_background | string | | No | | icon_type | string | | No | +| icon_url | string | | Yes | | id | string | | Yes | | is_starred | boolean | | No | | max_active_requests | integer | | No | -| mode_compatible_with_agent | string | | Yes | +| mode | string | | Yes | +| model_config | [ModelConfigPartial](#modelconfigpartial) | | No | | name | string | | Yes | | tags | [ [Tag](#tag) ] | | No | | updated_at | integer | | No | @@ -13109,7 +13332,7 @@ Enum class for configurate method of provider model. | icon | string | Icon | No | | icon_background | string | Icon background color | No | | icon_type | [IconType](#icontype) | Icon type | No | -| mode | string,
**Available values:** "advanced-chat", "agent", "agent-chat", "chat", "completion", "workflow" | App mode
*Enum:* `"advanced-chat"`, `"agent"`, `"agent-chat"`, `"chat"`, `"completion"`, `"workflow"` | Yes | +| mode | string,
**Available values:** "advanced-chat", "agent-chat", "chat", "completion", "workflow" | App mode
*Enum:* `"advanced-chat"`, `"agent-chat"`, `"chat"`, `"completion"`, `"workflow"` | Yes | | name | string | App name | Yes | #### CreateSnippetPayload @@ -15562,7 +15785,7 @@ Metadata operation data | ---- | ---- | ----------- | -------- | | created_at | integer | | No | | created_by | string | | No | -| model_dict | [JSONValue](#jsonvalue) | | No | +| model | [JSONValue](#jsonvalue) | | No | | pre_prompt | string | | No | | updated_at | integer | | No | | updated_by | string | | No | diff --git a/api/services/agent/roster_service.py b/api/services/agent/roster_service.py index 56f5b9f60e..f1001637fc 100644 --- a/api/services/agent/roster_service.py +++ b/api/services/agent/roster_service.py @@ -19,7 +19,7 @@ from models.agent import ( ) from models.agent_config_entities import AgentSoulConfig from models.enums import AppStatus -from models.model import App +from models.model import App, AppMode from models.workflow import Workflow from services.agent.agent_soul_state import agent_soul_has_model from services.agent.composer_validator import ComposerConfigValidator @@ -349,6 +349,43 @@ class AgentRosterService: ) ) + def get_agent_app_model(self, *, tenant_id: str, agent_id: str) -> App: + """Resolve the Agent App hidden behind an app-backed Agent id. + + The public /agent route uses Agent ids, while the runtime and legacy app + APIs still operate on App ids internally. Only app-backed roster Agents + are accepted here; workflow-only Agents and historical standalone roster + Agents are not Agent App resources. + """ + agent = self._session.scalar( + select(Agent) + .where( + Agent.tenant_id == tenant_id, + Agent.id == agent_id, + Agent.scope == AgentScope.ROSTER, + Agent.source == AgentSource.AGENT_APP, + Agent.app_id.is_not(None), + Agent.status == AgentStatus.ACTIVE, + ) + .limit(1) + ) + if agent is None or agent.app_id is None: + raise AgentNotFoundError() + + app = self._session.scalar( + select(App) + .where( + App.tenant_id == tenant_id, + App.id == agent.app_id, + App.mode == AppMode.AGENT, + App.status == AppStatus.NORMAL, + ) + .limit(1) + ) + if app is None: + raise AgentNotFoundError() + return app + def list_workflows_referencing_app_agent(self, *, tenant_id: str, app_id: str) -> list[AgentReferencingWorkflow]: """List the workflow apps that reference this Agent App's bound Agent. diff --git a/api/tests/unit_tests/controllers/console/agent/test_agent_controllers.py b/api/tests/unit_tests/controllers/console/agent/test_agent_controllers.py index 0007bddfa5..3d6b23d95b 100644 --- a/api/tests/unit_tests/controllers/console/agent/test_agent_controllers.py +++ b/api/tests/unit_tests/controllers/console/agent/test_agent_controllers.py @@ -1,16 +1,17 @@ from inspect import unwrap from types import SimpleNamespace -from typing import cast +from typing import Any, cast import pytest from flask import Flask +from controllers.console import console_ns from controllers.console.agent import composer as composer_controller from controllers.console.agent import roster as roster_controller from controllers.console.agent.composer import ( - AgentAppComposerApi, - AgentAppComposerCandidatesApi, - AgentAppComposerValidateApi, + AgentComposerApi, + AgentComposerCandidatesApi, + AgentComposerValidateApi, WorkflowAgentComposerApi, WorkflowAgentComposerCandidatesApi, WorkflowAgentComposerImpactApi, @@ -18,42 +19,15 @@ from controllers.console.agent.composer import ( WorkflowAgentComposerValidateApi, ) from controllers.console.agent.roster import ( + AgentAppApi, + AgentAppListApi, AgentInviteOptionsApi, - AgentRosterDetailApi, - AgentRosterListApi, AgentRosterVersionDetailApi, AgentRosterVersionsApi, ) -from models.model import AppMode from services.entities.agent_entities import ComposerSaveStrategy, ComposerVariant -def _agent_response(agent_id: str = "agent-1") -> dict: - return { - "id": agent_id, - "name": "Analyst", - "description": "", - "icon_type": None, - "icon": None, - "icon_background": None, - "agent_kind": "dify_agent", - "scope": "roster", - "source": "agent_app", - "app_id": None, - "workflow_id": None, - "workflow_node_id": None, - "active_config_snapshot_id": "version-1", - "active_config_snapshot": _version_response(), - "status": "active", - "created_by": "account-1", - "updated_by": "account-1", - "archived_by": None, - "archived_at": None, - "created_at": None, - "updated_at": None, - } - - def _version_response(version_id: str = "version-1") -> dict: return { "id": version_id, @@ -103,6 +77,37 @@ def _agent_app_composer_response() -> dict: } +def _app_detail_obj(**overrides): + data = { + "id": "app-1", + "name": "Iris", + "description": "Agent app", + "mode_compatible_with_agent": "agent", + "icon_type": "emoji", + "icon": "robot", + "icon_background": "#fff", + "enable_site": False, + "enable_api": False, + "app_model_config": None, + "workflow": None, + "tracing": None, + "use_icon_as_answer_icon": False, + "created_by": "account-1", + "created_at": None, + "updated_by": "account-1", + "updated_at": None, + "access_mode": None, + "tags": [], + "api_base_url": None, + "max_active_requests": 0, + "deleted_tools": [], + "site": None, + "bound_agent_id": "00000000-0000-0000-0000-000000000001", + } + data.update(overrides) + return SimpleNamespace(**data) + + def _candidates_response(variant: str) -> dict: return { "variant": variant, @@ -112,20 +117,38 @@ def _candidates_response(variant: str) -> dict: } -def _get_app_model_modes(view) -> list[AppMode]: - current = view - while current is not None: - closure = getattr(current, "__closure__", None) - if closure is not None: - for cell in closure: - try: - value = cell.cell_contents - except ValueError: - continue - if isinstance(value, list) and all(isinstance(item, AppMode) for item in value): - return value - current = getattr(current, "__wrapped__", None) - return [] +def test_agent_v2_console_routes_are_agent_id_first() -> None: + paths = {route for item in console_ns.resources for route in item.urls} + + for route in ( + "/agent", + "/agent/", + "/agent//composer", + "/agent//composer/validate", + "/agent//composer/candidates", + "/agent//features", + "/agent//referencing-workflows", + "/agent//drive/files", + "/agent//sandbox/files", + "/agent//skills/upload", + "/agent//files", + "/agent/invite-options", + ): + assert route in paths + + for route in ( + "/agents", + "/agents/invite-options", + "/agents/", + "/agents//versions", + "/apps//agent-composer", + "/apps//agent-composer/validate", + "/apps//agent-composer/candidates", + "/apps//agent-features", + "/apps//agent-referencing-workflows", + "/apps//agent-sandbox/files", + ): + assert route not in paths @pytest.fixture @@ -133,26 +156,114 @@ def account_id() -> str: return "account-1" -def test_roster_list_get_parses_query_and_calls_service(app: Flask, monkeypatch: pytest.MonkeyPatch) -> None: +def test_agent_app_list_and_create_use_agent_route( + app: Flask, monkeypatch: pytest.MonkeyPatch, account_id: str +) -> None: captured: dict[str, object] = {} - def list_roster_agents(_self: object, **kwargs: object) -> dict[str, object]: - captured.update(kwargs) - return {"data": [], "page": kwargs["page"], "limit": kwargs["limit"], "total": 0, "has_more": False} + class FakeAppService: + def get_app(self, app_obj: object) -> object: + return app_obj - monkeypatch.setattr(roster_controller.AgentRosterService, "list_roster_agents", list_roster_agents) + def get_paginate_apps(self, user_id: str, tenant_id: str, params) -> object: + captured["list"] = {"user_id": user_id, "tenant_id": tenant_id, "params": params} + return SimpleNamespace( + page=1, + per_page=10, + total=1, + has_next=False, + items=[_app_detail_obj(id="app-list", bound_agent_id="agent-list")], + ) - with app.test_request_context("/console/api/agents?page=2&limit=5&keyword=analyst"): - result = unwrap(AgentRosterListApi.get)(AgentRosterListApi(), "tenant-1") + def create_app(self, tenant_id: str, params, current_user: object) -> object: + captured["create"] = {"tenant_id": tenant_id, "params": params, "current_user": current_user} + return _app_detail_obj(id="app-created", bound_agent_id="agent-created") - assert result["page"] == 2 - assert captured == {"tenant_id": "tenant-1", "page": 2, "limit": 5, "keyword": "analyst"} + monkeypatch.setattr(roster_controller, "AppService", FakeAppService) + monkeypatch.setattr( + roster_controller.FeatureService, + "get_system_features", + lambda: SimpleNamespace(webapp_auth=SimpleNamespace(enabled=False)), + ) + + with app.test_request_context("/console/api/agent?page=1&limit=10&mode=workflow"): + listed = unwrap(AgentAppListApi.get)(AgentAppListApi(), "tenant-1", SimpleNamespace(id=account_id)) + + assert listed["page"] == 1 + assert listed["limit"] == 10 + assert listed["total"] == 1 + assert listed["data"][0]["id"] == "agent-list" + assert "bound_agent_id" not in listed["data"][0] + list_call = cast(dict[str, object], captured["list"]) + list_params = cast(Any, list_call["params"]) + assert list_params.mode == "agent" + assert list_params.status == "normal" + + with app.test_request_context( + "/console/api/agent", + json={"name": "Iris", "description": "Agent app", "icon_type": "emoji", "icon": "robot"}, + ): + created, status = unwrap(AgentAppListApi.post)(AgentAppListApi(), "tenant-1", SimpleNamespace(id=account_id)) + + assert status == 201 + assert created["id"] == "agent-created" + assert "bound_agent_id" not in created + create_call = cast(dict[str, object], captured["create"]) + create_params = cast(Any, create_call["params"]) + assert create_params.mode == "agent" -def test_roster_direct_mutation_endpoints_are_not_exposed() -> None: - assert not hasattr(AgentRosterListApi, "post") - assert not hasattr(AgentRosterDetailApi, "patch") - assert not hasattr(AgentRosterDetailApi, "delete") +def test_agent_app_detail_update_delete_resolve_app_from_agent_id( + app: Flask, monkeypatch: pytest.MonkeyPatch, account_id: str +) -> None: + agent_id = "00000000-0000-0000-0000-000000000001" + app_model = _app_detail_obj(id="app-1", bound_agent_id=agent_id) + captured: dict[str, object] = {} + + monkeypatch.setattr( + roster_controller.AgentRosterService, + "get_agent_app_model", + lambda _self, **kwargs: app_model, + ) + monkeypatch.setattr( + roster_controller.FeatureService, + "get_system_features", + lambda: SimpleNamespace(webapp_auth=SimpleNamespace(enabled=False)), + ) + + class FakeAppService: + def get_app(self, app_obj: object) -> object: + captured["get_app"] = app_obj + return app_obj + + def update_app(self, app_obj: object, args: dict[str, object]) -> object: + captured["update"] = {"app": app_obj, "args": args} + return _app_detail_obj(id="app-1", name=args["name"], bound_agent_id=agent_id) + + def delete_app(self, app_obj: object) -> None: + captured["delete"] = app_obj + + monkeypatch.setattr(roster_controller, "AppService", FakeAppService) + + detail = unwrap(AgentAppApi.get)(AgentAppApi(), "tenant-1", agent_id) + assert detail["id"] == agent_id + assert "bound_agent_id" not in detail + + with app.test_request_context( + "/console/api/agent/00000000-0000-0000-0000-000000000001", + json={"name": "Renamed", "description": "", "icon_type": "emoji", "icon": "R"}, + ): + updated = unwrap(AgentAppApi.put)(AgentAppApi(), "tenant-1", agent_id) + + assert updated["name"] == "Renamed" + assert updated["id"] == agent_id + assert "bound_agent_id" not in updated + update_call = cast(dict[str, object], captured["update"]) + assert update_call["app"] is app_model + + deleted, status = unwrap(AgentAppApi.delete)(AgentAppApi(), "tenant-1", agent_id) + assert (deleted, status) == ("", 204) + assert captured["delete"] is app_model def test_invite_options_get_parses_app_id(app: Flask, monkeypatch: pytest.MonkeyPatch) -> None: @@ -164,21 +275,16 @@ def test_invite_options_get_parses_app_id(app: Flask, monkeypatch: pytest.Monkey monkeypatch.setattr(roster_controller.AgentRosterService, "list_invite_options", list_invite_options) - with app.test_request_context("/console/api/agents/invite-options?page=1&limit=10&app_id=app-1"): + with app.test_request_context("/console/api/agent/invite-options?page=1&limit=10&app_id=app-1"): result = unwrap(AgentInviteOptionsApi.get)(AgentInviteOptionsApi(), "tenant-1") assert result == {"data": [], "page": 1, "limit": 10, "total": 0, "has_more": False} assert captured == {"tenant_id": "tenant-1", "page": 1, "limit": 10, "keyword": None, "app_id": "app-1"} -def test_roster_detail_and_versions_call_services(app: Flask, monkeypatch: pytest.MonkeyPatch) -> None: +def test_agent_versions_call_services(app: Flask, monkeypatch: pytest.MonkeyPatch) -> None: agent_id = "00000000-0000-0000-0000-000000000001" version_id = "00000000-0000-0000-0000-000000000002" - monkeypatch.setattr( - roster_controller.AgentRosterService, - "get_roster_agent_detail", - lambda _self, **kwargs: _agent_response(cast(str, kwargs["agent_id"])), - ) monkeypatch.setattr( roster_controller.AgentRosterService, "list_agent_versions", @@ -207,7 +313,6 @@ def test_roster_detail_and_versions_call_services(app: Flask, monkeypatch: pytes }, ) - assert unwrap(AgentRosterDetailApi.get)(AgentRosterDetailApi(), "tenant-1", agent_id)["id"] == agent_id assert ( unwrap(AgentRosterVersionsApi.get)(AgentRosterVersionsApi(), "tenant-1", agent_id)["data"][0]["id"] == "version-1" @@ -294,59 +399,76 @@ def test_workflow_impact_returns_empty_without_version(app: Flask) -> None: assert result == {"current_snapshot_id": None, "workflow_node_count": 0, "bindings": []} -def test_agent_app_composer_get_put_validate_and_candidates( +def test_agent_composer_routes_resolve_app_from_agent_id( app: Flask, monkeypatch: pytest.MonkeyPatch, account_id: str ) -> None: - app_model = SimpleNamespace(id="app-1") + agent_id = "00000000-0000-0000-0000-000000000001" + captured: dict[str, object] = {} payload = { "variant": ComposerVariant.AGENT_APP.value, "save_strategy": ComposerSaveStrategy.SAVE_TO_CURRENT_VERSION.value, "agent_soul": {"prompt": {"system_prompt": "x"}}, } + + monkeypatch.setattr(composer_controller, "resolve_agent_app_model", lambda **kwargs: SimpleNamespace(id="app-1")) + + def load_agent_app_composer(**kwargs: object) -> dict: + captured["load"] = kwargs + return _agent_app_composer_response() + + def save_agent_app_composer(**kwargs: object) -> dict: + captured["save"] = kwargs + return _agent_app_composer_response() + + def collect_validation_findings(**kwargs: object) -> dict: + captured["validate"] = kwargs + return {"warnings": [], "knowledge_retrieval_placeholder": []} + + def get_agent_app_candidates(**kwargs: object) -> dict: + captured["candidates"] = kwargs + return _candidates_response("agent_app") + monkeypatch.setattr( composer_controller.AgentComposerService, "load_agent_app_composer", - lambda **kwargs: _agent_app_composer_response(), + load_agent_app_composer, ) monkeypatch.setattr( composer_controller.AgentComposerService, "save_agent_app_composer", - lambda **kwargs: _agent_app_composer_response(), + save_agent_app_composer, ) monkeypatch.setattr(composer_controller.ComposerConfigValidator, "validate_save_payload", lambda payload: None) monkeypatch.setattr( - composer_controller.AgentComposerService, "resolve_workflow_node_agent_id", lambda **kwargs: None + composer_controller.AgentComposerService, + "collect_validation_findings", + collect_validation_findings, ) - monkeypatch.setattr(composer_controller.AgentComposerService, "resolve_bound_agent_id", lambda **kwargs: None) monkeypatch.setattr( composer_controller.AgentComposerService, "get_agent_app_candidates", - lambda **kwargs: _candidates_response("agent_app"), + get_agent_app_candidates, ) - assert unwrap(AgentAppComposerApi.get)(AgentAppComposerApi(), "tenant-1", app_model)["variant"] == "agent_app" + assert unwrap(AgentComposerApi.get)(AgentComposerApi(), "tenant-1", agent_id)["variant"] == "agent_app" + assert cast(dict[str, object], captured["load"])["app_id"] == "app-1" + with app.test_request_context(json=payload): assert ( - unwrap(AgentAppComposerApi.put)(AgentAppComposerApi(), "tenant-1", account_id, app_model)["variant"] - == "agent_app" + unwrap(AgentComposerApi.put)(AgentComposerApi(), "tenant-1", account_id, agent_id)["variant"] == "agent_app" ) - assert unwrap(AgentAppComposerValidateApi.post)(AgentAppComposerValidateApi(), "tenant-1", app_model) == { + assert cast(dict[str, object], captured["save"])["app_id"] == "app-1" + assert unwrap(AgentComposerValidateApi.post)(AgentComposerValidateApi(), "tenant-1", agent_id) == { "result": "success", "errors": [], "warnings": [], "knowledge_retrieval_placeholder": [], } - agent_app_candidates = unwrap(AgentAppComposerCandidatesApi.get)( - AgentAppComposerCandidatesApi(), "tenant-1", account_id, app_model - ) - assert agent_app_candidates["variant"] == "agent_app" + assert cast(dict[str, object], captured["validate"])["agent_id"] == agent_id - -def test_agent_app_composer_routes_are_agent_mode_only() -> None: - assert _get_app_model_modes(AgentAppComposerApi.get) == [AppMode.AGENT] - assert _get_app_model_modes(AgentAppComposerApi.put) == [AppMode.AGENT] - assert _get_app_model_modes(AgentAppComposerValidateApi.post) == [AppMode.AGENT] - assert _get_app_model_modes(AgentAppComposerCandidatesApi.get) == [AppMode.AGENT] + candidates = unwrap(AgentComposerCandidatesApi.get)(AgentComposerCandidatesApi(), "tenant-1", account_id, agent_id) + assert candidates["variant"] == "agent_app" + assert cast(dict[str, object], captured["candidates"])["app_id"] == "app-1" def test_dify_tool_candidate_response_keeps_granularity_fields(): diff --git a/api/tests/unit_tests/controllers/console/app/test_agent_app_sandbox.py b/api/tests/unit_tests/controllers/console/app/test_agent_app_sandbox.py index b1e473ec6d..3cda0a3433 100644 --- a/api/tests/unit_tests/controllers/console/app/test_agent_app_sandbox.py +++ b/api/tests/unit_tests/controllers/console/app/test_agent_app_sandbox.py @@ -119,6 +119,7 @@ def test_handle_maps_sandbox_and_agent_backend_errors() -> None: def test_agent_app_sandbox_resources_proxy_service(monkeypatch: pytest.MonkeyPatch) -> None: service = _AgentAppService() monkeypatch.setattr(module, "AgentAppSandboxService", lambda: service) + monkeypatch.setattr(module, "resolve_agent_app_model", lambda *, tenant_id, agent_id: _app_model()) monkeypatch.setattr( module, "query_params_from_request", @@ -129,11 +130,10 @@ def test_agent_app_sandbox_resources_proxy_service(monkeypatch: pytest.MonkeyPat "request", SimpleNamespace(get_json=lambda silent=True: {"conversation_id": "conv-1", "path": "report.txt"}), ) - app_model = _app_model() - listing = unwrap(module.AgentAppSandboxListResource.get)(object(), "tenant-1", app_model) - preview = unwrap(module.AgentAppSandboxReadResource.get)(object(), "tenant-1", app_model) - upload = unwrap(module.AgentAppSandboxUploadResource.post)(object(), "tenant-1", app_model) + listing = unwrap(module.AgentAppSandboxListResource.get)(object(), "tenant-1", "agent-1") + preview = unwrap(module.AgentAppSandboxReadResource.get)(object(), "tenant-1", "agent-1") + upload = unwrap(module.AgentAppSandboxUploadResource.post)(object(), "tenant-1", "agent-1") assert listing["path"] == "sub/report.txt" assert preview["text"] == "hello" @@ -151,11 +151,12 @@ def test_agent_app_sandbox_resource_returns_normalized_errors(monkeypatch: pytes raise AgentSandboxInspectorError("no_active_session", "no active session", status_code=404) monkeypatch.setattr(module, "AgentAppSandboxService", FailingService) + monkeypatch.setattr(module, "resolve_agent_app_model", lambda *, tenant_id, agent_id: _app_model()) monkeypatch.setattr( module, "query_params_from_request", lambda model: SimpleNamespace(conversation_id="conv-1", path=".") ) - assert unwrap(module.AgentAppSandboxListResource.get)(object(), "tenant-1", _app_model()) == ( + assert unwrap(module.AgentAppSandboxListResource.get)(object(), "tenant-1", "agent-1") == ( {"code": "no_active_session", "message": "no active session"}, 404, ) diff --git a/api/tests/unit_tests/controllers/console/app/test_agent_drive_inspector.py b/api/tests/unit_tests/controllers/console/app/test_agent_drive_inspector.py index 516c87989b..9d1b6c4c0e 100644 --- a/api/tests/unit_tests/controllers/console/app/test_agent_drive_inspector.py +++ b/api/tests/unit_tests/controllers/console/app/test_agent_drive_inspector.py @@ -15,8 +15,11 @@ from flask import Flask from controllers.console.app.agent_drive_inspector import ( AgentDriveDownloadApi, + AgentDriveDownloadByAgentApi, AgentDriveListApi, + AgentDriveListByAgentApi, AgentDrivePreviewApi, + AgentDrivePreviewByAgentApi, ) from services.agent_drive_service import AgentDriveError @@ -53,6 +56,32 @@ def test_list_filters_value_pointers_out_of_console_payload(): assert drive.return_value.manifest.call_args.kwargs["prefix"] == "pdf-toolkit/" +def test_list_by_agent_filters_value_pointers_out_of_console_payload(): + raw = _raw(AgentDriveListByAgentApi.get) + with app.test_request_context("/?prefix=pdf-toolkit/"): + with ( + patch(f"{_MOD}.resolve_agent_app_model", return_value=_APP) as resolve_app, + patch(f"{_MOD}.AgentDriveService") as drive, + ): + drive.return_value.manifest.return_value = [ + { + "key": "pdf-toolkit/SKILL.md", + "size": 5, + "hash": "h", + "mime_type": "text/markdown", + "file_kind": "tool_file", + "file_id": "tf-1", + "created_at": 1718000000, + } + ] + body = raw(AgentDriveListByAgentApi(), "tenant-1", "agent-1") + + assert body["items"][0]["key"] == "pdf-toolkit/SKILL.md" + assert "file_id" not in body["items"][0] + resolve_app.assert_called_once_with(tenant_id="tenant-1", agent_id="agent-1") + assert drive.return_value.manifest.call_args.kwargs["agent_id"] == "agent-1" + + def test_list_resolves_workflow_node_binding_agent(): raw = _raw(AgentDriveListApi.get) with app.test_request_context("/?node_id=agent-node-1"): @@ -101,6 +130,37 @@ def test_preview_passes_through_and_maps_errors(): assert body["code"] == "drive_key_not_found" +def test_preview_by_agent_passes_through_and_maps_errors(): + raw = _raw(AgentDrivePreviewByAgentApi.get) + with app.test_request_context("/?key=pdf-toolkit/SKILL.md"): + with ( + patch(f"{_MOD}.resolve_agent_app_model", return_value=_APP) as resolve_app, + patch(f"{_MOD}.AgentDriveService") as drive, + ): + drive.return_value.preview.return_value = { + "key": "pdf-toolkit/SKILL.md", + "size": 5, + "truncated": False, + "binary": False, + "text": "# hi", + } + body = raw(AgentDrivePreviewByAgentApi(), "tenant-1", "agent-1") + assert body["text"] == "# hi" + resolve_app.assert_called_once_with(tenant_id="tenant-1", agent_id="agent-1") + + with app.test_request_context("/?key=ghost/SKILL.md"): + with ( + patch(f"{_MOD}.resolve_agent_app_model", return_value=_APP), + patch(f"{_MOD}.AgentDriveService") as drive, + ): + drive.return_value.preview.side_effect = AgentDriveError( + "drive_key_not_found", "no drive entry", status_code=404 + ) + body, status = raw(AgentDrivePreviewByAgentApi(), "tenant-1", "agent-1") + assert status == 404 + assert body["code"] == "drive_key_not_found" + + def test_download_returns_signed_url_json(): raw = _raw(AgentDriveDownloadApi.get) with app.test_request_context("/?key=pdf-toolkit/.DIFY-SKILL-FULL.zip"): @@ -108,3 +168,16 @@ def test_download_returns_signed_url_json(): drive.return_value.download_url.return_value = "https://signed.example/zip" body = raw(AgentDriveDownloadApi(), _APP) assert body == {"url": "https://signed.example/zip"} + + +def test_download_by_agent_returns_signed_url_json(): + raw = _raw(AgentDriveDownloadByAgentApi.get) + with app.test_request_context("/?key=pdf-toolkit/.DIFY-SKILL-FULL.zip"): + with ( + patch(f"{_MOD}.resolve_agent_app_model", return_value=_APP) as resolve_app, + patch(f"{_MOD}.AgentDriveService") as drive, + ): + drive.return_value.download_url.return_value = "https://signed.example/zip" + body = raw(AgentDriveDownloadByAgentApi(), "tenant-1", "agent-1") + assert body == {"url": "https://signed.example/zip"} + resolve_app.assert_called_once_with(tenant_id="tenant-1", agent_id="agent-1") diff --git a/api/tests/unit_tests/controllers/console/app/test_agent_skills.py b/api/tests/unit_tests/controllers/console/app/test_agent_skills.py index 21cc0f7790..bcb4aeab46 100644 --- a/api/tests/unit_tests/controllers/console/app/test_agent_skills.py +++ b/api/tests/unit_tests/controllers/console/app/test_agent_skills.py @@ -14,7 +14,16 @@ from unittest.mock import MagicMock, patch from flask import Flask -from controllers.console.app.agent import AgentSkillStandardizeApi, AgentSkillUploadApi +from controllers.console.app.agent import ( + AgentDriveFilesByAgentApi, + AgentSkillByAgentApi, + AgentSkillInferToolsByAgentApi, + AgentSkillStandardizeApi, + AgentSkillStandardizeByAgentApi, + AgentSkillUploadApi, + AgentSkillUploadByAgentApi, +) +from models.model import AppMode from services.agent.skill_package_service import SkillPackageError from services.agent_drive_service import AgentDriveError @@ -32,7 +41,8 @@ def _file_ctx(*, files: dict[str, bytes] | None = None): _USER = SimpleNamespace(id="user-1") -_APP = SimpleNamespace(id="app-1", tenant_id="tenant-1", bound_agent_id="agent-1") +_APP = SimpleNamespace(id="app-1", tenant_id="tenant-1", mode=AppMode.AGENT, bound_agent_id="agent-1") +_WORKFLOW_APP = SimpleNamespace(id="app-1", tenant_id="tenant-1", mode=AppMode.WORKFLOW, bound_agent_id=None) def test_upload_validates_and_returns_skill_ref(): @@ -56,6 +66,28 @@ def test_upload_validates_and_returns_skill_ref(): manifest.to_skill_ref.assert_called_once_with(file_id="uf-1") +def test_upload_by_agent_resolves_app_and_returns_skill_ref(): + raw = _raw(AgentSkillUploadByAgentApi.post) + manifest = MagicMock() + manifest.to_skill_ref.return_value.model_dump.return_value = {"name": "S", "file_id": "uf-1"} + manifest.model_dump.return_value = {"name": "S"} + + with _file_ctx(files={"file": b"zip-bytes"}): + with ( + patch(f"{_MOD}.resolve_agent_app_model", return_value=_APP) as resolve_app, + patch(f"{_MOD}.SkillPackageService") as pkg, + patch(f"{_MOD}.FileService") as fs, + patch(f"{_MOD}.db"), + ): + pkg.return_value.validate_and_extract.return_value = manifest + fs.return_value.upload_file.return_value = SimpleNamespace(id="uf-1") + body, status = raw(AgentSkillUploadByAgentApi(), "tenant-1", _USER, "agent-1") + + assert status == 201 + assert body["skill"] == {"name": "S", "file_id": "uf-1"} + resolve_app.assert_called_once_with(tenant_id="tenant-1", agent_id="agent-1") + + def test_upload_no_file_is_400(): raw = _raw(AgentSkillUploadApi.post) with _file_ctx(files={}): @@ -87,9 +119,25 @@ def test_standardize_returns_result(): assert svc.return_value.standardize.call_args.kwargs["agent_id"] == "agent-1" +def test_standardize_by_agent_resolves_app(): + raw = _raw(AgentSkillStandardizeByAgentApi.post) + with _file_ctx(files={"file": b"zip"}): + with ( + patch(f"{_MOD}.resolve_agent_app_model", return_value=_APP) as resolve_app, + patch(f"{_MOD}.SkillStandardizeService") as svc, + ): + svc.return_value.standardize.return_value = {"skill": {"path": "s"}, "manifest": {}} + body, status = raw(AgentSkillStandardizeByAgentApi(), "tenant-1", _USER, "agent-1") + + assert status == 201 + assert body["skill"] == {"path": "s"} + resolve_app.assert_called_once_with(tenant_id="tenant-1", agent_id="agent-1") + assert svc.return_value.standardize.call_args.kwargs["agent_id"] == "agent-1" + + def test_standardize_no_bound_agent_is_400(): raw = _raw(AgentSkillStandardizeApi.post) - app_without_agent = SimpleNamespace(id="app-1", tenant_id="tenant-1", bound_agent_id=None) + app_without_agent = SimpleNamespace(id="app-1", tenant_id="tenant-1", mode=AppMode.AGENT, bound_agent_id=None) with _file_ctx(files={"file": b"zip"}): body, status = raw(AgentSkillStandardizeApi(), _USER, app_without_agent) assert status == 400 @@ -98,7 +146,6 @@ def test_standardize_no_bound_agent_is_400(): def test_standardize_resolves_workflow_node_agent(): raw = _raw(AgentSkillStandardizeApi.post) - workflow_app = SimpleNamespace(id="app-1", tenant_id="tenant-1", bound_agent_id=None) with app.test_request_context( "/?node_id=agent-node-1", method="POST", data={"file": (io.BytesIO(b"zip"), "skill.zip")} ): @@ -108,7 +155,7 @@ def test_standardize_resolves_workflow_node_agent(): ): composer.resolve_workflow_node_agent_id.return_value = "wf-agent-1" svc.return_value.standardize.return_value = {"skill": {"path": "s"}, "manifest": {}} - body, status = raw(AgentSkillStandardizeApi(), _USER, workflow_app) + body, status = raw(AgentSkillStandardizeApi(), _USER, _WORKFLOW_APP) assert status == 201 assert body["skill"] == {"path": "s"} @@ -165,6 +212,31 @@ def test_files_commit_validates_upload_and_returns_drive_ref(): assert composer.add_drive_file_ref.call_args.kwargs["app_id"] == "app-1" +def test_files_by_agent_commit_uses_agent_route_and_ignores_node_id(): + raw = _raw(AgentDriveFilesByAgentApi.post) + upload = SimpleNamespace(id="uf-1", name="sample.pdf") + with _json_ctx({"upload_file_id": "0fa6f9bc-3416-4476-8857-a13129704dd9"}, query_string="node_id=ignored"): + with ( + patch(f"{_MOD}.resolve_agent_app_model", return_value=_APP) as resolve_app, + patch(f"{_MOD}.console_ns") as ns, + patch(f"{_MOD}.db") as db_mock, + patch(f"{_MOD}.AgentDriveService") as drive, + patch(f"{_MOD}.AgentComposerService") as composer, + ): + ns.payload = {"upload_file_id": "0fa6f9bc-3416-4476-8857-a13129704dd9"} + db_mock.session.scalar.return_value = upload + drive.return_value.commit.return_value = [ + {"key": "files/sample.pdf", "size": 5, "mime_type": "application/pdf"} + ] + composer.add_drive_file_ref.return_value = "ver-2" + body, status = raw(AgentDriveFilesByAgentApi(), "tenant-1", _USER, "agent-1") + + assert status == 201 + assert body["config_version_id"] == "ver-2" + resolve_app.assert_called_once_with(tenant_id="tenant-1", agent_id="agent-1") + assert composer.add_drive_file_ref.call_args.kwargs["node_id"] is None + + def test_files_commit_404_when_upload_not_in_tenant(): from controllers.console.app.agent import AgentDriveFilesApi @@ -186,7 +258,6 @@ def test_files_commit_resolves_workflow_node_agent(): raw = _raw(AgentDriveFilesApi.post) upload = SimpleNamespace(id="uf-1", name="sample.pdf") - workflow_app = SimpleNamespace(id="app-1", tenant_id="tenant-1", bound_agent_id=None) with _json_ctx({"upload_file_id": "0fa6f9bc-3416-4476-8857-a13129704dd9"}, query_string="node_id=agent-node-1"): with ( patch(f"{_MOD}.console_ns") as ns, @@ -201,7 +272,7 @@ def test_files_commit_resolves_workflow_node_agent(): {"key": "files/sample.pdf", "size": 5, "mime_type": "application/pdf"} ] composer.add_drive_file_ref.return_value = "ver-2" - body, status = raw(AgentDriveFilesApi(), _USER, workflow_app) + body, status = raw(AgentDriveFilesApi(), _USER, _WORKFLOW_APP) assert status == 201 assert body["config_version_id"] == "ver-2" @@ -229,11 +300,27 @@ def test_files_delete_updates_soul_then_drive(): assert composer.remove_drive_refs.call_args.kwargs["app_id"] == "app-1" +def test_files_by_agent_delete_uses_agent_route_and_ignores_node_id(): + raw = _raw(AgentDriveFilesByAgentApi.delete) + with _json_ctx(method="DELETE", query_string="key=files/sample.pdf&node_id=ignored"): + with ( + patch(f"{_MOD}.resolve_agent_app_model", return_value=_APP) as resolve_app, + patch(f"{_MOD}.AgentComposerService") as composer, + patch(f"{_MOD}.AgentDriveService") as drive, + ): + composer.remove_drive_refs.return_value = "ver-2" + drive.return_value.delete.return_value = ["files/sample.pdf"] + body = raw(AgentDriveFilesByAgentApi(), "tenant-1", _USER, "agent-1") + + assert body["config_version_id"] == "ver-2" + resolve_app.assert_called_once_with(tenant_id="tenant-1", agent_id="agent-1") + assert composer.remove_drive_refs.call_args.kwargs["node_id"] is None + + def test_files_delete_resolves_workflow_node_agent(): from controllers.console.app.agent import AgentDriveFilesApi raw = _raw(AgentDriveFilesApi.delete) - workflow_app = SimpleNamespace(id="app-1", tenant_id="tenant-1", bound_agent_id=None) with _json_ctx(method="DELETE", query_string="key=files/sample.pdf&node_id=agent-node-1"): with ( patch(f"{_MOD}.AgentComposerService") as composer, @@ -242,7 +329,7 @@ def test_files_delete_resolves_workflow_node_agent(): composer.resolve_workflow_node_agent_id.return_value = "wf-agent-1" composer.remove_drive_refs.return_value = "ver-2" drive.return_value.delete.return_value = ["files/sample.pdf"] - body = raw(AgentDriveFilesApi(), _USER, workflow_app) + body = raw(AgentDriveFilesApi(), _USER, _WORKFLOW_APP) assert body["config_version_id"] == "ver-2" assert drive.return_value.delete.call_args.kwargs["agent_id"] == "wf-agent-1" @@ -284,6 +371,23 @@ def test_skill_delete_uses_slug_prefix_and_is_idempotent(): assert composer.remove_drive_refs.call_args.kwargs["app_id"] == "app-1" +def test_skill_delete_by_agent_uses_agent_route(): + raw = _raw(AgentSkillByAgentApi.delete) + with _json_ctx(method="DELETE", query_string="node_id=ignored"): + with ( + patch(f"{_MOD}.resolve_agent_app_model", return_value=_APP) as resolve_app, + patch(f"{_MOD}.AgentComposerService") as composer, + patch(f"{_MOD}.AgentDriveService") as drive, + ): + composer.remove_drive_refs.return_value = "ver-2" + drive.return_value.delete.return_value = ["tender-analyzer/SKILL.md"] + body = raw(AgentSkillByAgentApi(), "tenant-1", _USER, "agent-1", "tender-analyzer") + + assert body["config_version_id"] == "ver-2" + resolve_app.assert_called_once_with(tenant_id="tenant-1", agent_id="agent-1") + assert composer.remove_drive_refs.call_args.kwargs["node_id"] is None + + def test_skill_delete_rejects_path_like_slug(): from controllers.console.app.agent import AgentSkillApi @@ -314,11 +418,25 @@ def test_infer_tools_returns_draft_suggestions(): assert svc.return_value.infer.call_args.kwargs["slug"] == "audio-transcribe" +def test_infer_tools_by_agent_uses_agent_route(): + raw = _raw(AgentSkillInferToolsByAgentApi.post) + with _json_ctx(query_string="node_id=ignored"): + with ( + patch(f"{_MOD}.resolve_agent_app_model", return_value=_APP) as resolve_app, + patch(f"{_MOD}.SkillToolInferenceService") as svc, + ): + svc.return_value.infer.return_value = {"inferable": True, "cli_tools": [], "reason": None} + body = raw(AgentSkillInferToolsByAgentApi(), "tenant-1", "agent-1", "audio-transcribe") + + assert body["inferable"] is True + resolve_app.assert_called_once_with(tenant_id="tenant-1", agent_id="agent-1") + assert svc.return_value.infer.call_args.kwargs["agent_id"] == "agent-1" + + def test_infer_tools_resolves_workflow_node_agent(): from controllers.console.app.agent import AgentSkillInferToolsApi raw = _raw(AgentSkillInferToolsApi.post) - workflow_app = SimpleNamespace(id="app-1", tenant_id="tenant-1", bound_agent_id=None) with _json_ctx(query_string="node_id=agent-node-1"): with ( patch(f"{_MOD}.AgentComposerService") as composer, @@ -326,7 +444,7 @@ def test_infer_tools_resolves_workflow_node_agent(): ): composer.resolve_workflow_node_agent_id.return_value = "wf-agent-1" svc.return_value.infer.return_value = {"inferable": False, "cli_tools": [], "reason": "none"} - body = raw(AgentSkillInferToolsApi(), workflow_app, "audio-transcribe") + body = raw(AgentSkillInferToolsApi(), _WORKFLOW_APP, "audio-transcribe") assert body["inferable"] is False assert svc.return_value.infer.call_args.kwargs["agent_id"] == "wf-agent-1" @@ -355,7 +473,7 @@ def test_infer_tools_rejects_path_like_slug_and_unbound_app(): body, status = raw(AgentSkillInferToolsApi(), _APP, "a/b") assert (status, body["code"]) == (400, "drive_key_invalid") - app_without_agent = SimpleNamespace(id="app-1", tenant_id="tenant-1", bound_agent_id=None) + app_without_agent = SimpleNamespace(id="app-1", tenant_id="tenant-1", mode=AppMode.AGENT, bound_agent_id=None) with _json_ctx(): body, status = raw(AgentSkillInferToolsApi(), app_without_agent, "x") assert (status, body["code"]) == (400, "agent_not_bound") diff --git a/api/tests/unit_tests/controllers/console/app/test_app_response_models.py b/api/tests/unit_tests/controllers/console/app/test_app_response_models.py index 47126d2b92..ef8f90e5c9 100644 --- a/api/tests/unit_tests/controllers/console/app/test_app_response_models.py +++ b/api/tests/unit_tests/controllers/console/app/test_app_response_models.py @@ -314,37 +314,19 @@ def test_app_list_query_rejects_flat_tag_ids(app_module): app_module.AppListQuery.model_validate(normalized) -def test_create_agent_app_response_includes_bound_agent_id(app_module, monkeypatch: pytest.MonkeyPatch): +def test_create_app_endpoint_rejects_agent_mode(app_module, monkeypatch: pytest.MonkeyPatch): payload = {"name": "Iris", "mode": "agent", "description": "Agent app"} - app_obj = SimpleNamespace( - id="app-1", - name="Iris", - description="Agent app", - mode_compatible_with_agent="agent", - icon_type="emoji", - icon="robot", - icon_background="#fff", - enable_site=False, - enable_api=False, - created_at=_ts(), - updated_at=_ts(), - bound_agent_id="agent-1", - ) app_service = MagicMock() - app_service.create_app.return_value = app_obj monkeypatch.setattr(app_module, "AppService", lambda: app_service) app_module.console_ns.payload = payload try: - response, status = _unwrap(app_module.AppListApi().post)("tenant-1", SimpleNamespace(id="account-1")) + with pytest.raises(ValidationError): + _unwrap(app_module.AppListApi().post)("tenant-1", SimpleNamespace(id="account-1")) finally: app_module.console_ns.payload = None - assert status == 201 - assert response["id"] == "app-1" - assert response["bound_agent_id"] == "agent-1" - created_params = app_service.create_app.call_args.args[1] - assert created_params.mode == "agent" + app_service.create_app.assert_not_called() def test_app_partial_serialization_uses_aliases(app_models): diff --git a/api/tests/unit_tests/controllers/console/app/test_create_app_payload.py b/api/tests/unit_tests/controllers/console/app/test_create_app_payload.py index ebabe50c93..dfb2a4c139 100644 --- a/api/tests/unit_tests/controllers/console/app/test_create_app_payload.py +++ b/api/tests/unit_tests/controllers/console/app/test_create_app_payload.py @@ -1,9 +1,4 @@ -"""Regression tests for CreateAppPayload mode validation. - -The HTTP create-app payload must accept the new "agent" app mode; without it a -user cannot create an Agent App through POST /console/api/apps even though the -service layer (CreateAppParams) supports it. -""" +"""Regression tests for CreateAppPayload mode validation.""" import pytest from pydantic import ValidationError @@ -14,12 +9,16 @@ from controllers.console.app.app import CreateAppPayload class TestCreateAppPayloadMode: @pytest.mark.parametrize( "mode", - ["chat", "agent-chat", "agent", "advanced-chat", "workflow", "completion"], + ["chat", "agent-chat", "advanced-chat", "workflow", "completion"], ) def test_accepts_supported_modes(self, mode: str): payload = CreateAppPayload.model_validate({"name": "X", "mode": mode}) assert payload.mode == mode + def test_rejects_agent_mode(self): + with pytest.raises(ValidationError): + CreateAppPayload.model_validate({"name": "X", "mode": "agent"}) + def test_rejects_unknown_mode(self): with pytest.raises(ValidationError): CreateAppPayload.model_validate({"name": "X", "mode": "not-a-mode"}) diff --git a/api/tests/unit_tests/services/agent/test_agent_services.py b/api/tests/unit_tests/services/agent/test_agent_services.py index 5e85ea4970..24fd66a2ae 100644 --- a/api/tests/unit_tests/services/agent/test_agent_services.py +++ b/api/tests/unit_tests/services/agent/test_agent_services.py @@ -1037,6 +1037,31 @@ class TestAgentAppBackingAgent: assert service.get_app_backing_agent(tenant_id="tenant-1", app_id="app-x") is None + def test_get_agent_app_model_resolves_app_backing_agent(self): + agent = Agent( + id="agent-1", + tenant_id="tenant-1", + name="Iris", + description="", + agent_kind=AgentKind.DIFY_AGENT, + scope=AgentScope.ROSTER, + source=AgentSource.AGENT_APP, + status=AgentStatus.ACTIVE, + app_id="app-1", + ) + app = SimpleNamespace(id="app-1", mode="agent", status="normal") + session = FakeSession(scalar=[agent, app]) + service = AgentRosterService(session) + + assert service.get_agent_app_model(tenant_id="tenant-1", agent_id="agent-1") is app + + def test_get_agent_app_model_rejects_unbound_agent(self): + session = FakeSession() + service = AgentRosterService(session) + + with pytest.raises(roster_service.AgentNotFoundError): + service.get_agent_app_model(tenant_id="tenant-1", agent_id="agent-x") + class TestListWorkflowsReferencingAppAgent: def test_groups_bindings_by_workflow_app_and_sorts_by_name(self): diff --git a/packages/contracts/generated/api/console/agent/orpc.gen.ts b/packages/contracts/generated/api/console/agent/orpc.gen.ts new file mode 100644 index 0000000000..1d56ab6f5f --- /dev/null +++ b/packages/contracts/generated/api/console/agent/orpc.gen.ts @@ -0,0 +1,582 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import { oc } from '@orpc/contract' +import * as z from 'zod' + +import { + zDeleteAgentByAgentIdFilesPath, + zDeleteAgentByAgentIdFilesQuery, + zDeleteAgentByAgentIdFilesResponse, + zDeleteAgentByAgentIdPath, + zDeleteAgentByAgentIdResponse, + zDeleteAgentByAgentIdSkillsBySlugPath, + zDeleteAgentByAgentIdSkillsBySlugResponse, + zGetAgentByAgentIdComposerCandidatesPath, + zGetAgentByAgentIdComposerCandidatesResponse, + zGetAgentByAgentIdComposerPath, + zGetAgentByAgentIdComposerResponse, + zGetAgentByAgentIdDriveFilesDownloadPath, + zGetAgentByAgentIdDriveFilesDownloadQuery, + zGetAgentByAgentIdDriveFilesDownloadResponse, + zGetAgentByAgentIdDriveFilesPath, + zGetAgentByAgentIdDriveFilesPreviewPath, + zGetAgentByAgentIdDriveFilesPreviewQuery, + zGetAgentByAgentIdDriveFilesPreviewResponse, + zGetAgentByAgentIdDriveFilesQuery, + zGetAgentByAgentIdDriveFilesResponse, + zGetAgentByAgentIdPath, + zGetAgentByAgentIdReferencingWorkflowsPath, + zGetAgentByAgentIdReferencingWorkflowsResponse, + zGetAgentByAgentIdResponse, + zGetAgentByAgentIdSandboxFilesPath, + zGetAgentByAgentIdSandboxFilesQuery, + zGetAgentByAgentIdSandboxFilesReadPath, + zGetAgentByAgentIdSandboxFilesReadQuery, + zGetAgentByAgentIdSandboxFilesReadResponse, + zGetAgentByAgentIdSandboxFilesResponse, + zGetAgentByAgentIdVersionsByVersionIdPath, + zGetAgentByAgentIdVersionsByVersionIdResponse, + zGetAgentByAgentIdVersionsPath, + zGetAgentByAgentIdVersionsResponse, + zGetAgentInviteOptionsQuery, + zGetAgentInviteOptionsResponse, + zGetAgentQuery, + zGetAgentResponse, + zPostAgentBody, + zPostAgentByAgentIdComposerValidateBody, + zPostAgentByAgentIdComposerValidatePath, + zPostAgentByAgentIdComposerValidateResponse, + zPostAgentByAgentIdFeaturesBody, + zPostAgentByAgentIdFeaturesPath, + zPostAgentByAgentIdFeaturesResponse, + zPostAgentByAgentIdFilesBody, + zPostAgentByAgentIdFilesPath, + zPostAgentByAgentIdFilesResponse, + zPostAgentByAgentIdSandboxFilesUploadBody, + zPostAgentByAgentIdSandboxFilesUploadPath, + zPostAgentByAgentIdSandboxFilesUploadResponse, + zPostAgentByAgentIdSkillsBySlugInferToolsPath, + zPostAgentByAgentIdSkillsBySlugInferToolsResponse, + zPostAgentByAgentIdSkillsStandardizePath, + zPostAgentByAgentIdSkillsStandardizeResponse, + zPostAgentByAgentIdSkillsUploadPath, + zPostAgentByAgentIdSkillsUploadResponse, + zPostAgentResponse, + zPutAgentByAgentIdBody, + zPutAgentByAgentIdComposerBody, + zPutAgentByAgentIdComposerPath, + zPutAgentByAgentIdComposerResponse, + zPutAgentByAgentIdPath, + zPutAgentByAgentIdResponse, +} from './zod.gen' + +export const get = oc + .route({ + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgentInviteOptions', + path: '/agent/invite-options', + tags: ['console'], + }) + .input(z.object({ query: zGetAgentInviteOptionsQuery.optional() })) + .output(zGetAgentInviteOptionsResponse) + +export const inviteOptions = { + get, +} + +export const get2 = oc + .route({ + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgentByAgentIdComposerCandidates', + path: '/agent/{agent_id}/composer/candidates', + tags: ['console'], + }) + .input(z.object({ params: zGetAgentByAgentIdComposerCandidatesPath })) + .output(zGetAgentByAgentIdComposerCandidatesResponse) + +export const candidates = { + get: get2, +} + +export const post = oc + .route({ + inputStructure: 'detailed', + method: 'POST', + operationId: 'postAgentByAgentIdComposerValidate', + path: '/agent/{agent_id}/composer/validate', + tags: ['console'], + }) + .input( + z.object({ + body: zPostAgentByAgentIdComposerValidateBody, + params: zPostAgentByAgentIdComposerValidatePath, + }), + ) + .output(zPostAgentByAgentIdComposerValidateResponse) + +export const validate = { + post, +} + +export const get3 = oc + .route({ + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgentByAgentIdComposer', + path: '/agent/{agent_id}/composer', + tags: ['console'], + }) + .input(z.object({ params: zGetAgentByAgentIdComposerPath })) + .output(zGetAgentByAgentIdComposerResponse) + +export const put = oc + .route({ + inputStructure: 'detailed', + method: 'PUT', + operationId: 'putAgentByAgentIdComposer', + path: '/agent/{agent_id}/composer', + tags: ['console'], + }) + .input(z.object({ body: zPutAgentByAgentIdComposerBody, params: zPutAgentByAgentIdComposerPath })) + .output(zPutAgentByAgentIdComposerResponse) + +export const composer = { + get: get3, + put, + candidates, + validate, +} + +/** + * Time-limited external signed URL for one Agent App drive value + */ +export const get4 = oc + .route({ + description: 'Time-limited external signed URL for one Agent App drive value', + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgentByAgentIdDriveFilesDownload', + path: '/agent/{agent_id}/drive/files/download', + tags: ['console'], + }) + .input( + z.object({ + params: zGetAgentByAgentIdDriveFilesDownloadPath, + query: zGetAgentByAgentIdDriveFilesDownloadQuery, + }), + ) + .output(zGetAgentByAgentIdDriveFilesDownloadResponse) + +export const download = { + get: get4, +} + +/** + * Truncated text preview of one Agent App drive value + */ +export const get5 = oc + .route({ + description: 'Truncated text preview of one Agent App drive value', + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgentByAgentIdDriveFilesPreview', + path: '/agent/{agent_id}/drive/files/preview', + tags: ['console'], + }) + .input( + z.object({ + params: zGetAgentByAgentIdDriveFilesPreviewPath, + query: zGetAgentByAgentIdDriveFilesPreviewQuery, + }), + ) + .output(zGetAgentByAgentIdDriveFilesPreviewResponse) + +export const preview = { + get: get5, +} + +/** + * List agent drive entries for an Agent App + */ +export const get6 = oc + .route({ + description: 'List agent drive entries for an Agent App', + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgentByAgentIdDriveFiles', + path: '/agent/{agent_id}/drive/files', + tags: ['console'], + }) + .input( + z.object({ + params: zGetAgentByAgentIdDriveFilesPath, + query: zGetAgentByAgentIdDriveFilesQuery.optional(), + }), + ) + .output(zGetAgentByAgentIdDriveFilesResponse) + +export const files = { + get: get6, + download, + preview, +} + +export const drive = { + files, +} + +/** + * Update an Agent App's presentation features (opener, follow-up, citations, ...) + */ +export const post2 = oc + .route({ + description: 'Update an Agent App\'s presentation features (opener, follow-up, citations, ...)', + inputStructure: 'detailed', + method: 'POST', + operationId: 'postAgentByAgentIdFeatures', + path: '/agent/{agent_id}/features', + tags: ['console'], + }) + .input( + z.object({ body: zPostAgentByAgentIdFeaturesBody, params: zPostAgentByAgentIdFeaturesPath }), + ) + .output(zPostAgentByAgentIdFeaturesResponse) + +export const features = { + post: post2, +} + +/** + * Delete one Agent App drive file by key + */ +export const delete_ = oc + .route({ + description: 'Delete one Agent App drive file by key', + inputStructure: 'detailed', + method: 'DELETE', + operationId: 'deleteAgentByAgentIdFiles', + path: '/agent/{agent_id}/files', + tags: ['console'], + }) + .input( + z.object({ params: zDeleteAgentByAgentIdFilesPath, query: zDeleteAgentByAgentIdFilesQuery }), + ) + .output(zDeleteAgentByAgentIdFilesResponse) + +/** + * Commit an uploaded file into the Agent App drive under files/ + */ +export const post3 = oc + .route({ + description: 'Commit an uploaded file into the Agent App drive under files/', + inputStructure: 'detailed', + method: 'POST', + operationId: 'postAgentByAgentIdFiles', + path: '/agent/{agent_id}/files', + successStatus: 201, + tags: ['console'], + }) + .input(z.object({ body: zPostAgentByAgentIdFilesBody, params: zPostAgentByAgentIdFilesPath })) + .output(zPostAgentByAgentIdFilesResponse) + +export const files2 = { + delete: delete_, + post: post3, +} + +/** + * List workflow apps that reference this Agent App's bound Agent (read-only) + */ +export const get7 = oc + .route({ + description: 'List workflow apps that reference this Agent App\'s bound Agent (read-only)', + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgentByAgentIdReferencingWorkflows', + path: '/agent/{agent_id}/referencing-workflows', + tags: ['console'], + }) + .input(z.object({ params: zGetAgentByAgentIdReferencingWorkflowsPath })) + .output(zGetAgentByAgentIdReferencingWorkflowsResponse) + +export const referencingWorkflows = { + get: get7, +} + +/** + * Read a text/binary preview file in an Agent App conversation sandbox + */ +export const get8 = oc + .route({ + description: 'Read a text/binary preview file in an Agent App conversation sandbox', + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgentByAgentIdSandboxFilesRead', + path: '/agent/{agent_id}/sandbox/files/read', + tags: ['console'], + }) + .input( + z.object({ + params: zGetAgentByAgentIdSandboxFilesReadPath, + query: zGetAgentByAgentIdSandboxFilesReadQuery, + }), + ) + .output(zGetAgentByAgentIdSandboxFilesReadResponse) + +export const read = { + get: get8, +} + +/** + * Upload one Agent App sandbox file as a Dify ToolFile mapping + */ +export const post4 = oc + .route({ + description: 'Upload one Agent App sandbox file as a Dify ToolFile mapping', + inputStructure: 'detailed', + method: 'POST', + operationId: 'postAgentByAgentIdSandboxFilesUpload', + path: '/agent/{agent_id}/sandbox/files/upload', + tags: ['console'], + }) + .input( + z.object({ + body: zPostAgentByAgentIdSandboxFilesUploadBody, + params: zPostAgentByAgentIdSandboxFilesUploadPath, + }), + ) + .output(zPostAgentByAgentIdSandboxFilesUploadResponse) + +export const upload = { + post: post4, +} + +/** + * List a directory in an Agent App conversation sandbox + */ +export const get9 = oc + .route({ + description: 'List a directory in an Agent App conversation sandbox', + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgentByAgentIdSandboxFiles', + path: '/agent/{agent_id}/sandbox/files', + tags: ['console'], + }) + .input( + z.object({ + params: zGetAgentByAgentIdSandboxFilesPath, + query: zGetAgentByAgentIdSandboxFilesQuery, + }), + ) + .output(zGetAgentByAgentIdSandboxFilesResponse) + +export const files3 = { + get: get9, + read, + upload, +} + +export const sandbox = { + files: files3, +} + +/** + * Validate + standardize a Skill into an Agent App drive + */ +export const post5 = oc + .route({ + description: 'Validate + standardize a Skill into an Agent App drive', + inputStructure: 'detailed', + method: 'POST', + operationId: 'postAgentByAgentIdSkillsStandardize', + path: '/agent/{agent_id}/skills/standardize', + successStatus: 201, + tags: ['console'], + }) + .input(z.object({ params: zPostAgentByAgentIdSkillsStandardizePath })) + .output(zPostAgentByAgentIdSkillsStandardizeResponse) + +export const standardize = { + post: post5, +} + +/** + * Upload + validate a Skill package for an Agent App + */ +export const post6 = oc + .route({ + description: 'Upload + validate a Skill package for an Agent App', + inputStructure: 'detailed', + method: 'POST', + operationId: 'postAgentByAgentIdSkillsUpload', + path: '/agent/{agent_id}/skills/upload', + successStatus: 201, + tags: ['console'], + }) + .input(z.object({ params: zPostAgentByAgentIdSkillsUploadPath })) + .output(zPostAgentByAgentIdSkillsUploadResponse) + +export const upload2 = { + post: post6, +} + +/** + * Infer CLI tool + ENV suggestions from a standardized Agent App skill + */ +export const post7 = oc + .route({ + description: 'Infer CLI tool + ENV suggestions from a standardized Agent App skill', + inputStructure: 'detailed', + method: 'POST', + operationId: 'postAgentByAgentIdSkillsBySlugInferTools', + path: '/agent/{agent_id}/skills/{slug}/infer-tools', + tags: ['console'], + }) + .input(z.object({ params: zPostAgentByAgentIdSkillsBySlugInferToolsPath })) + .output(zPostAgentByAgentIdSkillsBySlugInferToolsResponse) + +export const inferTools = { + post: post7, +} + +/** + * Delete a standardized skill from an Agent App drive + */ +export const delete2 = oc + .route({ + description: 'Delete a standardized skill from an Agent App drive', + inputStructure: 'detailed', + method: 'DELETE', + operationId: 'deleteAgentByAgentIdSkillsBySlug', + path: '/agent/{agent_id}/skills/{slug}', + tags: ['console'], + }) + .input(z.object({ params: zDeleteAgentByAgentIdSkillsBySlugPath })) + .output(zDeleteAgentByAgentIdSkillsBySlugResponse) + +export const bySlug = { + delete: delete2, + inferTools, +} + +export const skills = { + standardize, + upload: upload2, + bySlug, +} + +export const get10 = oc + .route({ + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgentByAgentIdVersionsByVersionId', + path: '/agent/{agent_id}/versions/{version_id}', + tags: ['console'], + }) + .input(z.object({ params: zGetAgentByAgentIdVersionsByVersionIdPath })) + .output(zGetAgentByAgentIdVersionsByVersionIdResponse) + +export const byVersionId = { + get: get10, +} + +export const get11 = oc + .route({ + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgentByAgentIdVersions', + path: '/agent/{agent_id}/versions', + tags: ['console'], + }) + .input(z.object({ params: zGetAgentByAgentIdVersionsPath })) + .output(zGetAgentByAgentIdVersionsResponse) + +export const versions = { + get: get11, + byVersionId, +} + +export const delete3 = oc + .route({ + inputStructure: 'detailed', + method: 'DELETE', + operationId: 'deleteAgentByAgentId', + path: '/agent/{agent_id}', + successStatus: 204, + tags: ['console'], + }) + .input(z.object({ params: zDeleteAgentByAgentIdPath })) + .output(zDeleteAgentByAgentIdResponse) + +export const get12 = oc + .route({ + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgentByAgentId', + path: '/agent/{agent_id}', + tags: ['console'], + }) + .input(z.object({ params: zGetAgentByAgentIdPath })) + .output(zGetAgentByAgentIdResponse) + +export const put2 = oc + .route({ + inputStructure: 'detailed', + method: 'PUT', + operationId: 'putAgentByAgentId', + path: '/agent/{agent_id}', + tags: ['console'], + }) + .input(z.object({ body: zPutAgentByAgentIdBody, params: zPutAgentByAgentIdPath })) + .output(zPutAgentByAgentIdResponse) + +export const byAgentId = { + delete: delete3, + get: get12, + put: put2, + composer, + drive, + features, + files: files2, + referencingWorkflows, + sandbox, + skills, + versions, +} + +export const get13 = oc + .route({ + inputStructure: 'detailed', + method: 'GET', + operationId: 'getAgent', + path: '/agent', + tags: ['console'], + }) + .input(z.object({ query: zGetAgentQuery.optional() })) + .output(zGetAgentResponse) + +export const post8 = oc + .route({ + inputStructure: 'detailed', + method: 'POST', + operationId: 'postAgent', + path: '/agent', + successStatus: 201, + tags: ['console'], + }) + .input(z.object({ body: zPostAgentBody })) + .output(zPostAgentResponse) + +export const agent = { + get: get13, + post: post8, + inviteOptions, + byAgentId, +} + +export const contract = { + agent, +} diff --git a/packages/contracts/generated/api/console/agent/types.gen.ts b/packages/contracts/generated/api/console/agent/types.gen.ts new file mode 100644 index 0000000000..967e6bf3f1 --- /dev/null +++ b/packages/contracts/generated/api/console/agent/types.gen.ts @@ -0,0 +1,1545 @@ +// This file is auto-generated by @hey-api/openapi-ts + +export type ClientOptions = { + baseUrl: `${string}://${string}/console/api` | (string & {}) +} + +export type AppPagination = { + data: Array + has_more: boolean + limit: number + page: number + total: number +} + +export type AgentAppCreatePayload = { + description?: string | null + icon?: string | null + icon_background?: string | null + icon_type?: IconType | null + name: string +} + +export type AppDetailWithSite = { + access_mode?: string | null + api_base_url?: string | null + bound_agent_id?: string | null + created_at?: number | null + created_by?: string | null + deleted_tools?: Array + description?: string | null + enable_api: boolean + enable_site: boolean + icon?: string | null + icon_background?: string | null + icon_type?: string | null + readonly icon_url: string | null + id: string + max_active_requests?: number | null + mode: string + model_config?: ModelConfig | null + name: string + site?: Site | null + tags?: Array + tracing?: JsonValue | null + updated_at?: number | null + updated_by?: string | null + use_icon_as_answer_icon?: boolean | null + workflow?: WorkflowPartial | null +} + +export type AgentInviteOptionsResponse = { + data: Array + has_more: boolean + limit: number + page: number + total: number +} + +export type UpdateAppPayload = { + description?: string | null + icon?: string | null + icon_background?: string | null + icon_type?: IconType | null + max_active_requests?: number | null + name: string + use_icon_as_answer_icon?: boolean | null +} + +export type AgentAppComposerResponse = { + active_config_snapshot: AgentConfigSnapshotSummaryResponse + agent: AgentComposerAgentResponse + agent_soul: AgentSoulConfig + save_options: Array + validation?: ComposerValidationFindingsResponse | null + variant: 'agent_app' +} + +export type ComposerSavePayload = { + agent_soul?: AgentSoulConfig | null + binding?: ComposerBindingPayload | null + client_revision_id?: string | null + idempotency_key?: string | null + new_agent_name?: string | null + node_job?: WorkflowNodeJobConfig | null + save_strategy: ComposerSaveStrategy + soul_lock?: ComposerSoulLockPayload + variant: ComposerVariant + version_note?: string | null +} + +export type AgentComposerCandidatesResponse = { + allowed_node_job_candidates?: AgentComposerNodeJobCandidatesResponse + allowed_soul_candidates?: AgentComposerSoulCandidatesResponse + capabilities?: ComposerCandidateCapabilities + truncated?: boolean + variant: ComposerVariant +} + +export type AgentComposerValidateResponse = { + errors?: Array + knowledge_retrieval_placeholder?: Array + result: 'success' + warnings?: Array +} + +export type AgentDriveListResponse = { + items?: Array +} + +export type AgentDriveDownloadResponse = { + url: string +} + +export type AgentDrivePreviewResponse = { + binary: boolean + key: string + size?: number | null + text?: string | null + truncated: boolean +} + +export type AgentAppFeaturesPayload = { + opening_statement?: string | null + retriever_resource?: AgentFeatureToggleConfig | null + sensitive_word_avoidance?: AgentSensitiveWordAvoidanceFeatureConfig | null + speech_to_text?: AgentFeatureToggleConfig | null + suggested_questions?: Array | null + suggested_questions_after_answer?: AgentSuggestedQuestionsAfterAnswerFeatureConfig | null + text_to_speech?: AgentTextToSpeechFeatureConfig | null +} + +export type SimpleResultResponse = { + result: string +} + +export type AgentDriveDeleteResponse = { + config_version_id?: string | null + removed_keys?: Array + result: string +} + +export type AgentDriveFilePayload = { + upload_file_id: string +} + +export type AgentDriveFileCommitResponse = { + config_version_id?: string | null + file: AgentDriveFileResponse +} + +export type AgentReferencingWorkflowsResponse = { + data?: Array +} + +export type SandboxListResponse = { + entries?: Array + path: string + truncated?: boolean +} + +export type SandboxReadResponse = { + binary: boolean + path: string + size?: number | null + text?: string | null + truncated: boolean +} + +export type AgentSandboxUploadPayload = { + conversation_id: string + path: string +} + +export type SandboxUploadResponse = { + file: SandboxToolFileResponse + path: string +} + +export type AgentSkillStandardizeResponse = { + manifest: SkillManifest + skill: AgentSkillRefConfig +} + +export type AgentSkillUploadResponse = { + manifest: SkillManifest + skill: AgentSkillRefConfig +} + +export type SkillToolInferenceResult = { + cli_tools?: Array + inferable: boolean + reason?: string | null +} + +export type AgentConfigSnapshotListResponse = { + data: Array +} + +export type AgentConfigSnapshotDetailResponse = { + agent_id?: string | null + config_snapshot: AgentSoulConfig + created_at?: number | null + created_by?: string | null + id: string + revisions?: Array + summary?: string | null + version: number + version_note?: string | null +} + +export type AppPartial = { + access_mode?: string | null + author_name?: string | null + bound_agent_id?: string | null + create_user_name?: string | null + created_at?: number | null + created_by?: string | null + description?: string | null + has_draft_trigger?: boolean | null + icon?: string | null + icon_background?: string | null + icon_type?: string | null + readonly icon_url: string | null + id: string + is_starred?: boolean + max_active_requests?: number | null + mode: string + model_config?: ModelConfigPartial | null + name: string + tags?: Array + updated_at?: number | null + updated_by?: string | null + use_icon_as_answer_icon?: boolean | null + workflow?: WorkflowPartial | null +} + +export type IconType = 'emoji' | 'image' | 'link' + +export type DeletedTool = { + provider_id: string + tool_name: string + type: string +} + +export type ModelConfig = { + completion_params?: { + [key: string]: unknown + } + mode: LlmMode + name: string + provider: string +} + +export type Site = { + chat_color_theme?: string | null + chat_color_theme_inverted: boolean + copyright?: string | null + custom_disclaimer?: string | null + default_language: string + description?: string | null + icon?: string | null + icon_background?: string | null + icon_type?: string | null + readonly icon_url: string | null + privacy_policy?: string | null + show_workflow_steps: boolean + title: string + use_icon_as_answer_icon: boolean +} + +export type Tag = { + id: string + name: string + type: string +} + +export type JsonValue + = | string + | number + | number + | boolean + | { + [key: string]: unknown + } + | Array + | null + +export type WorkflowPartial = { + created_at?: number | null + created_by?: string | null + id: string + updated_at?: number | null + updated_by?: string | null +} + +export type AgentInviteOptionResponse = { + active_config_snapshot?: AgentConfigSnapshotSummaryResponse | null + active_config_snapshot_id?: string | null + agent_kind: AgentKind + app_id?: string | null + archived_at?: number | null + archived_by?: string | null + created_at?: number | null + created_by?: string | null + description: string + existing_node_ids?: Array + icon?: string | null + icon_background?: string | null + icon_type?: AgentIconType | null + id: string + in_current_workflow_count?: number + is_in_current_workflow?: boolean + name: string + published_node_reference_count?: number + published_reference_count?: number + published_references?: Array + role?: string + scope: AgentScope + source: AgentSource + status: AgentStatus + updated_at?: number | null + updated_by?: string | null + workflow_id?: string | null + workflow_node_id?: string | null +} + +export type AgentConfigSnapshotSummaryResponse = { + agent_id?: string | null + created_at?: number | null + created_by?: string | null + id: string + summary?: string | null + version: number + version_note?: string | null +} + +export type AgentComposerAgentResponse = { + active_config_snapshot_id?: string | null + description: string + id: string + name: string + scope: AgentScope + status: AgentStatus +} + +export type AgentSoulConfig = { + app_features?: AgentSoulAppFeaturesConfig + app_variables?: Array + env?: AgentSoulEnvConfig + human?: AgentSoulHumanConfig + knowledge?: AgentSoulKnowledgeConfig + memory?: AgentSoulMemoryConfig + misc_legacy?: AgentSoulAppFeaturesConfig + model?: AgentSoulModelConfig | null + prompt?: AgentSoulPromptConfig + sandbox?: AgentSoulSandboxConfig + schema_version?: number + skills_files?: AgentSoulSkillsFilesConfig + tools?: AgentSoulToolsConfig +} + +export type ComposerSaveStrategy + = | 'node_job_only' + | 'save_as_new_agent' + | 'save_as_new_version' + | 'save_to_current_version' + | 'save_to_roster' + +export type ComposerValidationFindingsResponse = { + knowledge_retrieval_placeholder?: Array + warnings?: Array +} + +export type ComposerBindingPayload = { + agent_id?: string | null + binding_type: 'inline_agent' | 'roster_agent' + current_snapshot_id?: string | null +} + +export type WorkflowNodeJobConfig = { + declared_outputs?: Array + human_contacts?: Array + metadata?: WorkflowNodeJobMetadata + mode?: WorkflowNodeJobMode + previous_node_output_refs?: Array + schema_version?: number + workflow_prompt?: string +} + +export type ComposerSoulLockPayload = { + locked?: boolean + unlocked_from_version_id?: string | null +} + +export type ComposerVariant = 'agent_app' | 'workflow' + +export type AgentComposerNodeJobCandidatesResponse = { + declare_output_types?: Array + human_contacts?: Array + previous_node_outputs?: Array +} + +export type AgentComposerSoulCandidatesResponse = { + cli_tools?: Array + dify_tools?: Array + human_contacts?: Array + knowledge_datasets?: Array + skills_files?: Array< + | ({ + kind: 'skill' + } & AgentComposerSkillCandidateResponse) + | ({ + kind: 'file' + } & AgentComposerFileCandidateResponse) + > +} + +export type ComposerCandidateCapabilities = { + human_roster_available?: boolean +} + +export type ComposerKnowledgePlaceholderResponse = { + id: string + placeholder_name: string +} + +export type ComposerValidationWarningResponse = { + code: string + id?: string | null + kind?: string | null + message?: string | null + surface?: string | null +} + +export type AgentDriveItemResponse = { + created_at?: number | null + file_kind: string + hash?: string | null + key: string + mime_type?: string | null + size?: number | null +} + +export type AgentFeatureToggleConfig = { + enabled?: boolean + [key: string]: unknown +} + +export type AgentSensitiveWordAvoidanceFeatureConfig = { + config?: AgentModerationProviderConfig | null + enabled?: boolean + type?: string | null + [key: string]: unknown +} + +export type AgentSuggestedQuestionsAfterAnswerFeatureConfig = { + enabled?: boolean + model?: AgentSoulModelConfig | null + prompt?: string | null + [key: string]: unknown +} + +export type AgentTextToSpeechFeatureConfig = { + autoPlay?: string | null + enabled?: boolean + language?: string | null + voice?: string | null + [key: string]: unknown +} + +export type AgentDriveFileResponse = { + drive_key: string + file_id: string + mime_type?: string | null + name: string + size?: number | null +} + +export type AgentReferencingWorkflowResponse = { + app_id: string + app_mode: string + app_name: string + node_ids?: Array + workflow_id: string +} + +export type SandboxFileEntryResponse = { + mtime?: number | null + name: string + size?: number | null + type: 'dir' | 'file' | 'other' | 'symlink' +} + +export type SandboxToolFileResponse = { + reference: string + transfer_method?: 'tool_file' +} + +export type SkillManifest = { + description: string + entry_path: string + files: Array + hash: string + name: string + size: number +} + +export type AgentSkillRefConfig = { + description?: string | null + file_id?: string | null + full_archive_file_id?: string | null + full_archive_key?: string | null + id?: string | null + manifest_files?: Array | null + name?: string | null + path?: string | null + skill_md_file_id?: string | null + skill_md_key?: string | null + [key: string]: unknown +} + +export type CliToolSuggestion = { + command?: string + description?: string + env_suggestions?: Array + inferred_from?: string + install_commands?: Array + name: string +} + +export type AgentConfigRevisionResponse = { + created_at?: number | null + created_by?: string | null + current_snapshot_id: string + id: string + operation: AgentConfigRevisionOperation + previous_snapshot_id?: string | null + revision: number + summary?: string | null + version_note?: string | null +} + +export type ModelConfigPartial = { + created_at?: number | null + created_by?: string | null + model?: JsonValue | null + pre_prompt?: string | null + updated_at?: number | null + updated_by?: string | null +} + +export type LlmMode = 'chat' | 'completion' + +export type AgentKind = 'dify_agent' + +export type AgentIconType = 'emoji' | 'image' | 'link' + +export type AgentPublishedReferenceResponse = { + app_id: string + app_mode: string + app_name: string + node_ids?: Array + workflow_id: string + workflow_version: string +} + +export type AgentScope = 'roster' | 'workflow_only' + +export type AgentSource = 'agent_app' | 'imported' | 'roster' | 'system' | 'workflow' + +export type AgentStatus = 'active' | 'archived' + +export type AgentSoulAppFeaturesConfig = { + opening_statement?: string | null + retriever_resource?: AgentFeatureToggleConfig | null + sensitive_word_avoidance?: AgentSensitiveWordAvoidanceFeatureConfig | null + speech_to_text?: AgentFeatureToggleConfig | null + suggested_questions?: Array | null + suggested_questions_after_answer?: AgentSuggestedQuestionsAfterAnswerFeatureConfig | null + text_to_speech?: AgentTextToSpeechFeatureConfig | null + [key: string]: unknown +} + +export type AppVariableConfig = { + default?: unknown + name: string + required?: boolean + type: string +} + +export type AgentSoulEnvConfig = { + secret_refs?: Array + variables?: Array +} + +export type AgentSoulHumanConfig = { + contacts?: Array + tools?: Array +} + +export type AgentSoulKnowledgeConfig = { + datasets?: Array + query_config?: AgentKnowledgeQueryConfig + query_mode?: AgentKnowledgeQueryMode | null +} + +export type AgentSoulMemoryConfig = { + artifacts?: Array + budget?: string | null + scope?: string | null +} + +export type AgentSoulModelConfig = { + credential_ref?: AgentSoulModelCredentialRef | null + model: string + model_provider: string + model_settings?: AgentSoulModelSettings + plugin_id: string +} + +export type AgentSoulPromptConfig = { + system_prompt?: string +} + +export type AgentSoulSandboxConfig = { + config?: AgentSandboxProviderConfig + provider?: string | null +} + +export type AgentSoulSkillsFilesConfig = { + files?: Array + skills?: Array +} + +export type AgentSoulToolsConfig = { + cli_tools?: Array + dify_tools?: Array +} + +export type DeclaredOutputConfig = { + array_item?: DeclaredArrayItem | null + check?: DeclaredOutputCheckConfig | null + description?: string | null + failure_strategy?: DeclaredOutputFailureStrategy + file?: DeclaredOutputFileConfig | null + id?: string | null + name: string + required?: boolean + type: DeclaredOutputType +} + +export type AgentHumanContactConfig = { + channel?: string | null + contact_id?: string | null + contact_method?: string | null + email?: string | null + human_id?: string | null + id?: string | null + method?: string | null + name?: string | null + tenant_id?: string | null + [key: string]: unknown +} + +export type WorkflowNodeJobMetadata = { + agent_soul?: { + [key: string]: unknown + } | null + file_refs?: Array | null +} + +export type WorkflowNodeJobMode = 'let_agent_figure_it_out' | 'tell_agent_what_to_do' + +export type WorkflowPreviousNodeOutputRef = { + key?: string | null + name?: string | null + node_id?: string | null + output?: string | null + selector?: Array | null + value_selector?: Array | null + variable?: string | null + variable_selector?: Array | null + [key: string]: unknown +} + +export type DeclaredOutputType = 'array' | 'boolean' | 'file' | 'number' | 'object' | 'string' + +export type AgentCliToolConfig = { + approved?: boolean + authorization_status?: AgentCliToolAuthorizationStatus | null + command?: string | null + dangerous?: boolean + dangerous_accepted?: boolean + dangerous_acknowledged?: boolean + dangerous_command?: boolean + description?: string | null + enabled?: boolean + env?: AgentCliToolEnvConfig + id?: string | null + inferred_from?: string | null + install?: string | null + install_command?: string | null + install_commands?: Array + invoke_metadata?: { + [key: string]: unknown + } + label?: string | null + name?: string | null + permission?: AgentPermissionConfig | null + pre_authorized?: boolean | null + requires_confirmation?: boolean + risk_accepted?: boolean + risk_level?: AgentCliToolRiskLevel | null + setup_command?: string | null + tool_name?: string | null + [key: string]: unknown +} + +export type AgentComposerDifyToolCandidateResponse = { + description?: string | null + granularity?: string | null + id?: string | null + name?: string | null + plugin_id?: string | null + provider?: string | null + provider_id?: string | null + tools_count?: number | null +} + +export type AgentKnowledgeDatasetConfig = { + description?: string | null + id?: string | null + name?: string | null + [key: string]: unknown +} + +export type AgentComposerSkillCandidateResponse = { + description?: string | null + file_id?: string | null + full_archive_file_id?: string | null + full_archive_key?: string | null + id?: string | null + kind?: 'skill' + manifest_files?: Array | null + name?: string | null + path?: string | null + skill_md_file_id?: string | null + skill_md_key?: string | null + [key: string]: unknown +} + +export type AgentComposerFileCandidateResponse = { + drive_key?: string | null + file_id?: string | null + id?: string | null + kind?: 'file' + name?: string | null + reference?: string | null + remote_url?: string | null + tenant_id?: string | null + transfer_method?: string | null + type?: string | null + upload_file_id?: string | null + url?: string | null + [key: string]: unknown +} + +export type AgentModerationProviderConfig = { + api_based_extension_id?: string | null + inputs_config?: AgentModerationIoConfig | null + keywords?: string | null + outputs_config?: AgentModerationIoConfig | null + [key: string]: unknown +} + +export type EnvSuggestion = { + key: string + reason?: string + secret_likely?: boolean +} + +export type AgentConfigRevisionOperation + = | 'create_version' + | 'save_current_version' + | 'save_new_agent' + | 'save_new_version' + | 'save_to_roster' + +export type AgentSecretRefConfig = { + credential_id?: string | null + env_name?: string | null + id?: string | null + key?: string | null + name?: string | null + permission?: AgentPermissionConfig | null + permission_status?: string | null + provider?: string | null + provider_credential_id?: string | null + ref?: string | null + type?: string | null + variable?: string | null + [key: string]: unknown +} + +export type AgentEnvVariableConfig = { + default?: + | string + | number + | number + | boolean + | Array + | Array + | Array + | Array + | null + env_name?: string | null + key?: string | null + name?: string | null + required?: boolean + type?: string | null + value?: + | string + | number + | number + | boolean + | Array + | Array + | Array + | Array + | null + variable?: string | null + [key: string]: unknown +} + +export type AgentHumanToolConfig = { + description?: string | null + enabled?: boolean + name?: string | null + [key: string]: unknown +} + +export type AgentKnowledgeQueryConfig = { + query?: string | null + score_threshold?: number | null + score_threshold_enabled?: boolean | null + top_k?: number | null + [key: string]: unknown +} + +export type AgentKnowledgeQueryMode = 'generated_query' | 'user_query' + +export type AgentMemoryArtifactConfig = { + id?: string | null + name?: string | null + type?: string | null + url?: string | null + [key: string]: unknown +} + +export type AgentSoulModelCredentialRef = { + id?: string | null + provider?: string | null + type: string +} + +export type AgentSoulModelSettings = { + frequency_penalty?: number | null + max_tokens?: number | null + presence_penalty?: number | null + response_format?: AgentModelResponseFormatConfig | null + stop?: Array | null + temperature?: number | null + top_p?: number | null +} + +export type AgentSandboxProviderConfig = { + cpu?: number | null + env?: Array + image?: string | null + working_dir?: string | null + [key: string]: unknown +} + +export type AgentFileRefConfig = { + drive_key?: string | null + file_id?: string | null + id?: string | null + name?: string | null + reference?: string | null + remote_url?: string | null + tenant_id?: string | null + transfer_method?: string | null + type?: string | null + upload_file_id?: string | null + url?: string | null + [key: string]: unknown +} + +export type AgentSoulDifyToolConfig = { + credential_ref?: AgentSoulDifyToolCredentialRef | null + credential_type?: 'api-key' | 'oauth2' | 'unauthorized' + description?: string | null + enabled?: boolean + name?: string | null + plugin_id?: string | null + provider?: string | null + provider_id?: string | null + provider_type?: string + runtime_parameters?: { + [key: string]: + | string + | number + | number + | boolean + | Array + | Array + | Array + | Array + | null + } + tool_name?: string | null +} + +export type DeclaredArrayItem = { + description?: string | null + type: DeclaredOutputType +} + +export type DeclaredOutputCheckConfig = { + benchmark_file_ref?: AgentFileRefConfig | null + enabled?: boolean + model_ref?: AgentSoulModelConfig | null + prompt?: string | null +} + +export type DeclaredOutputFailureStrategy = { + default_value?: unknown + on_failure?: OutputErrorStrategy + retry?: DeclaredOutputRetryConfig +} + +export type DeclaredOutputFileConfig = { + extensions?: Array + mime_types?: Array +} + +export type AgentCliToolAuthorizationStatus + = | 'allowed' + | 'authorized' + | 'denied' + | 'forbidden' + | 'not_required' + | 'pending' + | 'pre_authorized' + | 'unauthorized' + +export type AgentCliToolEnvConfig = { + secret_refs?: Array + variables?: Array +} + +export type AgentPermissionConfig = { + allowed?: boolean | null + state?: string | null + status?: string | null +} + +export type AgentCliToolRiskLevel = 'dangerous' | 'safe' | 'unknown' + +export type AgentModerationIoConfig = { + enabled?: boolean + preset_response?: string | null + [key: string]: unknown +} + +export type AgentModelResponseFormatConfig = { + type?: string | null + [key: string]: unknown +} + +export type AgentSoulDifyToolCredentialRef = { + id?: string | null + provider?: string | null + type?: 'provider' | 'tool' +} + +export type OutputErrorStrategy = 'default_value' | 'fail_branch' | 'stop' + +export type DeclaredOutputRetryConfig = { + enabled?: boolean + max_retries?: number + retry_interval_ms?: number +} + +export type AppPaginationWritable = { + data: Array + has_more: boolean + limit: number + page: number + total: number +} + +export type AppDetailWithSiteWritable = { + access_mode?: string | null + api_base_url?: string | null + bound_agent_id?: string | null + created_at?: number | null + created_by?: string | null + deleted_tools?: Array + description?: string | null + enable_api: boolean + enable_site: boolean + icon?: string | null + icon_background?: string | null + icon_type?: string | null + id: string + max_active_requests?: number | null + mode: string + model_config?: ModelConfig | null + name: string + site?: SiteWritable | null + tags?: Array + tracing?: JsonValue | null + updated_at?: number | null + updated_by?: string | null + use_icon_as_answer_icon?: boolean | null + workflow?: WorkflowPartial | null +} + +export type AppPartialWritable = { + access_mode?: string | null + author_name?: string | null + bound_agent_id?: string | null + create_user_name?: string | null + created_at?: number | null + created_by?: string | null + description?: string | null + has_draft_trigger?: boolean | null + icon?: string | null + icon_background?: string | null + icon_type?: string | null + id: string + is_starred?: boolean + max_active_requests?: number | null + mode: string + model_config?: ModelConfigPartial | null + name: string + tags?: Array + updated_at?: number | null + updated_by?: string | null + use_icon_as_answer_icon?: boolean | null + workflow?: WorkflowPartial | null +} + +export type SiteWritable = { + chat_color_theme?: string | null + chat_color_theme_inverted: boolean + copyright?: string | null + custom_disclaimer?: string | null + default_language: string + description?: string | null + icon?: string | null + icon_background?: string | null + icon_type?: string | null + privacy_policy?: string | null + show_workflow_steps: boolean + title: string + use_icon_as_answer_icon: boolean +} + +export type GetAgentData = { + body?: never + path?: never + query?: { + creator_ids?: Array + is_created_by_me?: boolean + limit?: number + mode?: + | 'advanced-chat' + | 'agent' + | 'agent-chat' + | 'all' + | 'channel' + | 'chat' + | 'completion' + | 'workflow' + name?: string + page?: number + sort_by?: 'earliest_created' | 'last_modified' | 'recently_created' + tag_ids?: Array + } + url: '/agent' +} + +export type GetAgentResponses = { + 200: AppPagination +} + +export type GetAgentResponse = GetAgentResponses[keyof GetAgentResponses] + +export type PostAgentData = { + body: AgentAppCreatePayload + path?: never + query?: never + url: '/agent' +} + +export type PostAgentErrors = { + 400: unknown + 403: unknown +} + +export type PostAgentResponses = { + 201: AppDetailWithSite +} + +export type PostAgentResponse = PostAgentResponses[keyof PostAgentResponses] + +export type GetAgentInviteOptionsData = { + body?: never + path?: never + query?: { + app_id?: string + keyword?: string + limit?: number + page?: number + } + url: '/agent/invite-options' +} + +export type GetAgentInviteOptionsResponses = { + 200: AgentInviteOptionsResponse +} + +export type GetAgentInviteOptionsResponse + = GetAgentInviteOptionsResponses[keyof GetAgentInviteOptionsResponses] + +export type DeleteAgentByAgentIdData = { + body?: never + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}' +} + +export type DeleteAgentByAgentIdErrors = { + 403: unknown +} + +export type DeleteAgentByAgentIdResponses = { + 204: void +} + +export type DeleteAgentByAgentIdResponse + = DeleteAgentByAgentIdResponses[keyof DeleteAgentByAgentIdResponses] + +export type GetAgentByAgentIdData = { + body?: never + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}' +} + +export type GetAgentByAgentIdResponses = { + 200: AppDetailWithSite +} + +export type GetAgentByAgentIdResponse = GetAgentByAgentIdResponses[keyof GetAgentByAgentIdResponses] + +export type PutAgentByAgentIdData = { + body: UpdateAppPayload + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}' +} + +export type PutAgentByAgentIdErrors = { + 400: unknown + 403: unknown +} + +export type PutAgentByAgentIdResponses = { + 200: AppDetailWithSite +} + +export type PutAgentByAgentIdResponse = PutAgentByAgentIdResponses[keyof PutAgentByAgentIdResponses] + +export type GetAgentByAgentIdComposerData = { + body?: never + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}/composer' +} + +export type GetAgentByAgentIdComposerResponses = { + 200: AgentAppComposerResponse +} + +export type GetAgentByAgentIdComposerResponse + = GetAgentByAgentIdComposerResponses[keyof GetAgentByAgentIdComposerResponses] + +export type PutAgentByAgentIdComposerData = { + body: ComposerSavePayload + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}/composer' +} + +export type PutAgentByAgentIdComposerResponses = { + 200: AgentAppComposerResponse +} + +export type PutAgentByAgentIdComposerResponse + = PutAgentByAgentIdComposerResponses[keyof PutAgentByAgentIdComposerResponses] + +export type GetAgentByAgentIdComposerCandidatesData = { + body?: never + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}/composer/candidates' +} + +export type GetAgentByAgentIdComposerCandidatesResponses = { + 200: AgentComposerCandidatesResponse +} + +export type GetAgentByAgentIdComposerCandidatesResponse + = GetAgentByAgentIdComposerCandidatesResponses[keyof GetAgentByAgentIdComposerCandidatesResponses] + +export type PostAgentByAgentIdComposerValidateData = { + body: ComposerSavePayload + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}/composer/validate' +} + +export type PostAgentByAgentIdComposerValidateResponses = { + 200: AgentComposerValidateResponse +} + +export type PostAgentByAgentIdComposerValidateResponse + = PostAgentByAgentIdComposerValidateResponses[keyof PostAgentByAgentIdComposerValidateResponses] + +export type GetAgentByAgentIdDriveFilesData = { + body?: never + path: { + agent_id: string + } + query?: { + prefix?: string + } + url: '/agent/{agent_id}/drive/files' +} + +export type GetAgentByAgentIdDriveFilesResponses = { + 200: AgentDriveListResponse +} + +export type GetAgentByAgentIdDriveFilesResponse + = GetAgentByAgentIdDriveFilesResponses[keyof GetAgentByAgentIdDriveFilesResponses] + +export type GetAgentByAgentIdDriveFilesDownloadData = { + body?: never + path: { + agent_id: string + } + query: { + key: string + } + url: '/agent/{agent_id}/drive/files/download' +} + +export type GetAgentByAgentIdDriveFilesDownloadResponses = { + 200: AgentDriveDownloadResponse +} + +export type GetAgentByAgentIdDriveFilesDownloadResponse + = GetAgentByAgentIdDriveFilesDownloadResponses[keyof GetAgentByAgentIdDriveFilesDownloadResponses] + +export type GetAgentByAgentIdDriveFilesPreviewData = { + body?: never + path: { + agent_id: string + } + query: { + key: string + } + url: '/agent/{agent_id}/drive/files/preview' +} + +export type GetAgentByAgentIdDriveFilesPreviewResponses = { + 200: AgentDrivePreviewResponse +} + +export type GetAgentByAgentIdDriveFilesPreviewResponse + = GetAgentByAgentIdDriveFilesPreviewResponses[keyof GetAgentByAgentIdDriveFilesPreviewResponses] + +export type PostAgentByAgentIdFeaturesData = { + body: AgentAppFeaturesPayload + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}/features' +} + +export type PostAgentByAgentIdFeaturesErrors = { + 400: unknown + 404: unknown +} + +export type PostAgentByAgentIdFeaturesResponses = { + 200: SimpleResultResponse +} + +export type PostAgentByAgentIdFeaturesResponse + = PostAgentByAgentIdFeaturesResponses[keyof PostAgentByAgentIdFeaturesResponses] + +export type DeleteAgentByAgentIdFilesData = { + body?: never + path: { + agent_id: string + } + query: { + key: string + } + url: '/agent/{agent_id}/files' +} + +export type DeleteAgentByAgentIdFilesResponses = { + 200: AgentDriveDeleteResponse +} + +export type DeleteAgentByAgentIdFilesResponse + = DeleteAgentByAgentIdFilesResponses[keyof DeleteAgentByAgentIdFilesResponses] + +export type PostAgentByAgentIdFilesData = { + body: AgentDriveFilePayload + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}/files' +} + +export type PostAgentByAgentIdFilesResponses = { + 201: AgentDriveFileCommitResponse +} + +export type PostAgentByAgentIdFilesResponse + = PostAgentByAgentIdFilesResponses[keyof PostAgentByAgentIdFilesResponses] + +export type GetAgentByAgentIdReferencingWorkflowsData = { + body?: never + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}/referencing-workflows' +} + +export type GetAgentByAgentIdReferencingWorkflowsErrors = { + 404: unknown +} + +export type GetAgentByAgentIdReferencingWorkflowsResponses = { + 200: AgentReferencingWorkflowsResponse +} + +export type GetAgentByAgentIdReferencingWorkflowsResponse + = GetAgentByAgentIdReferencingWorkflowsResponses[keyof GetAgentByAgentIdReferencingWorkflowsResponses] + +export type GetAgentByAgentIdSandboxFilesData = { + body?: never + path: { + agent_id: string + } + query: { + conversation_id: string + path?: string + } + url: '/agent/{agent_id}/sandbox/files' +} + +export type GetAgentByAgentIdSandboxFilesResponses = { + 200: SandboxListResponse +} + +export type GetAgentByAgentIdSandboxFilesResponse + = GetAgentByAgentIdSandboxFilesResponses[keyof GetAgentByAgentIdSandboxFilesResponses] + +export type GetAgentByAgentIdSandboxFilesReadData = { + body?: never + path: { + agent_id: string + } + query: { + conversation_id: string + path: string + } + url: '/agent/{agent_id}/sandbox/files/read' +} + +export type GetAgentByAgentIdSandboxFilesReadResponses = { + 200: SandboxReadResponse +} + +export type GetAgentByAgentIdSandboxFilesReadResponse + = GetAgentByAgentIdSandboxFilesReadResponses[keyof GetAgentByAgentIdSandboxFilesReadResponses] + +export type PostAgentByAgentIdSandboxFilesUploadData = { + body: AgentSandboxUploadPayload + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}/sandbox/files/upload' +} + +export type PostAgentByAgentIdSandboxFilesUploadResponses = { + 200: SandboxUploadResponse +} + +export type PostAgentByAgentIdSandboxFilesUploadResponse + = PostAgentByAgentIdSandboxFilesUploadResponses[keyof PostAgentByAgentIdSandboxFilesUploadResponses] + +export type PostAgentByAgentIdSkillsStandardizeData = { + body?: never + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}/skills/standardize' +} + +export type PostAgentByAgentIdSkillsStandardizeErrors = { + 400: unknown +} + +export type PostAgentByAgentIdSkillsStandardizeResponses = { + 201: AgentSkillStandardizeResponse +} + +export type PostAgentByAgentIdSkillsStandardizeResponse + = PostAgentByAgentIdSkillsStandardizeResponses[keyof PostAgentByAgentIdSkillsStandardizeResponses] + +export type PostAgentByAgentIdSkillsUploadData = { + body?: never + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}/skills/upload' +} + +export type PostAgentByAgentIdSkillsUploadErrors = { + 400: unknown +} + +export type PostAgentByAgentIdSkillsUploadResponses = { + 201: AgentSkillUploadResponse +} + +export type PostAgentByAgentIdSkillsUploadResponse + = PostAgentByAgentIdSkillsUploadResponses[keyof PostAgentByAgentIdSkillsUploadResponses] + +export type DeleteAgentByAgentIdSkillsBySlugData = { + body?: never + path: { + agent_id: string + slug: string + } + query?: never + url: '/agent/{agent_id}/skills/{slug}' +} + +export type DeleteAgentByAgentIdSkillsBySlugResponses = { + 200: AgentDriveDeleteResponse +} + +export type DeleteAgentByAgentIdSkillsBySlugResponse + = DeleteAgentByAgentIdSkillsBySlugResponses[keyof DeleteAgentByAgentIdSkillsBySlugResponses] + +export type PostAgentByAgentIdSkillsBySlugInferToolsData = { + body?: never + path: { + agent_id: string + slug: string + } + query?: never + url: '/agent/{agent_id}/skills/{slug}/infer-tools' +} + +export type PostAgentByAgentIdSkillsBySlugInferToolsResponses = { + 200: SkillToolInferenceResult +} + +export type PostAgentByAgentIdSkillsBySlugInferToolsResponse + = PostAgentByAgentIdSkillsBySlugInferToolsResponses[keyof PostAgentByAgentIdSkillsBySlugInferToolsResponses] + +export type GetAgentByAgentIdVersionsData = { + body?: never + path: { + agent_id: string + } + query?: never + url: '/agent/{agent_id}/versions' +} + +export type GetAgentByAgentIdVersionsResponses = { + 200: AgentConfigSnapshotListResponse +} + +export type GetAgentByAgentIdVersionsResponse + = GetAgentByAgentIdVersionsResponses[keyof GetAgentByAgentIdVersionsResponses] + +export type GetAgentByAgentIdVersionsByVersionIdData = { + body?: never + path: { + agent_id: string + version_id: string + } + query?: never + url: '/agent/{agent_id}/versions/{version_id}' +} + +export type GetAgentByAgentIdVersionsByVersionIdResponses = { + 200: AgentConfigSnapshotDetailResponse +} + +export type GetAgentByAgentIdVersionsByVersionIdResponse + = GetAgentByAgentIdVersionsByVersionIdResponses[keyof GetAgentByAgentIdVersionsByVersionIdResponses] diff --git a/packages/contracts/generated/api/console/agent/zod.gen.ts b/packages/contracts/generated/api/console/agent/zod.gen.ts new file mode 100644 index 0000000000..50f050ff22 --- /dev/null +++ b/packages/contracts/generated/api/console/agent/zod.gen.ts @@ -0,0 +1,1817 @@ +// This file is auto-generated by @hey-api/openapi-ts + +import * as z from 'zod' + +/** + * AgentDriveDownloadResponse + */ +export const zAgentDriveDownloadResponse = z.object({ + url: z.string(), +}) + +/** + * AgentDrivePreviewResponse + */ +export const zAgentDrivePreviewResponse = z.object({ + binary: z.boolean(), + key: z.string(), + size: z.int().nullish(), + text: z.string().nullish(), + truncated: z.boolean(), +}) + +/** + * SimpleResultResponse + */ +export const zSimpleResultResponse = z.object({ + result: z.string(), +}) + +/** + * AgentDriveDeleteResponse + */ +export const zAgentDriveDeleteResponse = z.object({ + config_version_id: z.string().nullish(), + removed_keys: z.array(z.string()).optional(), + result: z.string(), +}) + +/** + * AgentDriveFilePayload + */ +export const zAgentDriveFilePayload = z.object({ + upload_file_id: z.string(), +}) + +/** + * SandboxReadResponse + */ +export const zSandboxReadResponse = z.object({ + binary: z.boolean(), + path: z.string(), + size: z.int().nullish(), + text: z.string().nullish(), + truncated: z.boolean(), +}) + +/** + * AgentSandboxUploadPayload + */ +export const zAgentSandboxUploadPayload = z.object({ + conversation_id: z.string().min(1), + path: z.string().min(1), +}) + +/** + * IconType + */ +export const zIconType = z.enum(['emoji', 'image', 'link']) + +/** + * AgentAppCreatePayload + */ +export const zAgentAppCreatePayload = z.object({ + description: z.string().max(400).nullish(), + icon: z.string().nullish(), + icon_background: z.string().nullish(), + icon_type: zIconType.nullish(), + name: z.string().min(1), +}) + +/** + * UpdateAppPayload + */ +export const zUpdateAppPayload = z.object({ + description: z.string().max(400).nullish(), + icon: z.string().nullish(), + icon_background: z.string().nullish(), + icon_type: zIconType.nullish(), + max_active_requests: z.int().nullish(), + name: z.string().min(1), + use_icon_as_answer_icon: z.boolean().nullish(), +}) + +/** + * DeletedTool + */ +export const zDeletedTool = z.object({ + provider_id: z.string(), + tool_name: z.string(), + type: z.string(), +}) + +/** + * Site + */ +export const zSite = z.object({ + chat_color_theme: z.string().nullish(), + chat_color_theme_inverted: z.boolean(), + copyright: z.string().nullish(), + custom_disclaimer: z.string().nullish(), + default_language: z.string(), + description: z.string().nullish(), + icon: z.string().nullish(), + icon_background: z.string().nullish(), + icon_type: z.string().nullish(), + icon_url: z.string().nullable(), + privacy_policy: z.string().nullish(), + show_workflow_steps: z.boolean(), + title: z.string(), + use_icon_as_answer_icon: z.boolean(), +}) + +/** + * Tag + */ +export const zTag = z.object({ + id: z.string(), + name: z.string(), + type: z.string(), +}) + +export const zJsonValue = z + .union([ + z.string(), + z.int(), + z.number(), + z.boolean(), + z.record(z.string(), z.unknown()), + z.array(z.unknown()), + ]) + .nullable() + +/** + * WorkflowPartial + */ +export const zWorkflowPartial = z.object({ + created_at: z.int().nullish(), + created_by: z.string().nullish(), + id: z.string(), + updated_at: z.int().nullish(), + updated_by: z.string().nullish(), +}) + +/** + * AgentConfigSnapshotSummaryResponse + */ +export const zAgentConfigSnapshotSummaryResponse = z.object({ + agent_id: z.string().nullish(), + created_at: z.int().nullish(), + created_by: z.string().nullish(), + id: z.string(), + summary: z.string().nullish(), + version: z.int(), + version_note: z.string().nullish(), +}) + +/** + * AgentConfigSnapshotListResponse + */ +export const zAgentConfigSnapshotListResponse = z.object({ + data: z.array(zAgentConfigSnapshotSummaryResponse), +}) + +/** + * ComposerSaveStrategy + */ +export const zComposerSaveStrategy = z.enum([ + 'node_job_only', + 'save_as_new_agent', + 'save_as_new_version', + 'save_to_current_version', + 'save_to_roster', +]) + +/** + * ComposerBindingPayload + */ +export const zComposerBindingPayload = z.object({ + agent_id: z.string().nullish(), + binding_type: z.enum(['inline_agent', 'roster_agent']), + current_snapshot_id: z.string().nullish(), +}) + +/** + * ComposerSoulLockPayload + */ +export const zComposerSoulLockPayload = z.object({ + locked: z.boolean().optional().default(true), + unlocked_from_version_id: z.string().nullish(), +}) + +/** + * ComposerVariant + */ +export const zComposerVariant = z.enum(['agent_app', 'workflow']) + +/** + * ComposerCandidateCapabilities + */ +export const zComposerCandidateCapabilities = z.object({ + human_roster_available: z.boolean().optional().default(false), +}) + +/** + * ComposerKnowledgePlaceholderResponse + */ +export const zComposerKnowledgePlaceholderResponse = z.object({ + id: z.string(), + placeholder_name: z.string(), +}) + +/** + * ComposerValidationWarningResponse + */ +export const zComposerValidationWarningResponse = z.object({ + code: z.string(), + id: z.string().nullish(), + kind: z.string().nullish(), + message: z.string().nullish(), + surface: z.string().nullish(), +}) + +/** + * AgentComposerValidateResponse + */ +export const zAgentComposerValidateResponse = z.object({ + errors: z.array(z.string()).optional(), + knowledge_retrieval_placeholder: z.array(zComposerKnowledgePlaceholderResponse).optional(), + result: z.literal('success'), + warnings: z.array(zComposerValidationWarningResponse).optional(), +}) + +/** + * ComposerValidationFindingsResponse + */ +export const zComposerValidationFindingsResponse = z.object({ + knowledge_retrieval_placeholder: z.array(zComposerKnowledgePlaceholderResponse).optional(), + warnings: z.array(zComposerValidationWarningResponse).optional(), +}) + +/** + * AgentDriveItemResponse + */ +export const zAgentDriveItemResponse = z.object({ + created_at: z.int().nullish(), + file_kind: z.string(), + hash: z.string().nullish(), + key: z.string(), + mime_type: z.string().nullish(), + size: z.int().nullish(), +}) + +/** + * AgentDriveListResponse + */ +export const zAgentDriveListResponse = z.object({ + items: z.array(zAgentDriveItemResponse).optional(), +}) + +/** + * AgentFeatureToggleConfig + */ +export const zAgentFeatureToggleConfig = z.object({ + enabled: z.boolean().optional().default(false), +}) + +/** + * AgentTextToSpeechFeatureConfig + */ +export const zAgentTextToSpeechFeatureConfig = z.object({ + autoPlay: z.string().nullish(), + enabled: z.boolean().optional().default(false), + language: z.string().nullish(), + voice: z.string().nullish(), +}) + +/** + * AgentDriveFileResponse + */ +export const zAgentDriveFileResponse = z.object({ + drive_key: z.string(), + file_id: z.string(), + mime_type: z.string().nullish(), + name: z.string(), + size: z.int().nullish(), +}) + +/** + * AgentDriveFileCommitResponse + */ +export const zAgentDriveFileCommitResponse = z.object({ + config_version_id: z.string().nullish(), + file: zAgentDriveFileResponse, +}) + +/** + * AgentReferencingWorkflowResponse + */ +export const zAgentReferencingWorkflowResponse = z.object({ + app_id: z.string(), + app_mode: z.string(), + app_name: z.string(), + node_ids: z.array(z.string()).optional(), + workflow_id: z.string(), +}) + +/** + * AgentReferencingWorkflowsResponse + */ +export const zAgentReferencingWorkflowsResponse = z.object({ + data: z.array(zAgentReferencingWorkflowResponse).optional(), +}) + +/** + * SandboxFileEntryResponse + */ +export const zSandboxFileEntryResponse = z.object({ + mtime: z.int().nullish(), + name: z.string(), + size: z.int().nullish(), + type: z.enum(['dir', 'file', 'other', 'symlink']), +}) + +/** + * SandboxListResponse + */ +export const zSandboxListResponse = z.object({ + entries: z.array(zSandboxFileEntryResponse).optional(), + path: z.string(), + truncated: z.boolean().optional().default(false), +}) + +/** + * SandboxToolFileResponse + */ +export const zSandboxToolFileResponse = z.object({ + reference: z.string(), + transfer_method: z.literal('tool_file').optional().default('tool_file'), +}) + +/** + * SandboxUploadResponse + */ +export const zSandboxUploadResponse = z.object({ + file: zSandboxToolFileResponse, + path: z.string(), +}) + +/** + * SkillManifest + * + * Validated metadata extracted from a Skill package. + */ +export const zSkillManifest = z.object({ + description: z.string(), + entry_path: z.string(), + files: z.array(z.string()), + hash: z.string(), + name: z.string(), + size: z.int(), +}) + +/** + * AgentSkillRefConfig + */ +export const zAgentSkillRefConfig = z.object({ + description: z.string().nullish(), + file_id: z.string().max(255).nullish(), + full_archive_file_id: z.string().max(255).nullish(), + full_archive_key: z.string().max(512).nullish(), + id: z.string().max(255).nullish(), + manifest_files: z.array(z.string()).nullish(), + name: z.string().max(255).nullish(), + path: z.string().nullish(), + skill_md_file_id: z.string().max(255).nullish(), + skill_md_key: z.string().max(512).nullish(), +}) + +/** + * AgentSkillStandardizeResponse + */ +export const zAgentSkillStandardizeResponse = z.object({ + manifest: zSkillManifest, + skill: zAgentSkillRefConfig, +}) + +/** + * AgentSkillUploadResponse + */ +export const zAgentSkillUploadResponse = z.object({ + manifest: zSkillManifest, + skill: zAgentSkillRefConfig, +}) + +/** + * ModelConfigPartial + */ +export const zModelConfigPartial = z.object({ + created_at: z.int().nullish(), + created_by: z.string().nullish(), + model: zJsonValue.nullish(), + pre_prompt: z.string().nullish(), + updated_at: z.int().nullish(), + updated_by: z.string().nullish(), +}) + +/** + * AppPartial + */ +export const zAppPartial = z.object({ + access_mode: z.string().nullish(), + author_name: z.string().nullish(), + bound_agent_id: z.string().nullish(), + create_user_name: z.string().nullish(), + created_at: z.int().nullish(), + created_by: z.string().nullish(), + description: z.string().nullish(), + has_draft_trigger: z.boolean().nullish(), + icon: z.string().nullish(), + icon_background: z.string().nullish(), + icon_type: z.string().nullish(), + icon_url: z.string().nullable(), + id: z.string(), + is_starred: z.boolean().optional().default(false), + max_active_requests: z.int().nullish(), + mode: z.string(), + model_config: zModelConfigPartial.nullish(), + name: z.string(), + tags: z.array(zTag).optional(), + updated_at: z.int().nullish(), + updated_by: z.string().nullish(), + use_icon_as_answer_icon: z.boolean().nullish(), + workflow: zWorkflowPartial.nullish(), +}) + +/** + * AppPagination + */ +export const zAppPagination = z.object({ + data: z.array(zAppPartial), + has_more: z.boolean(), + limit: z.int(), + page: z.int(), + total: z.int(), +}) + +/** + * LLMMode + * + * Enum class for large language model mode. + */ +export const zLlmMode = z.enum(['chat', 'completion']) + +/** + * ModelConfig + */ +export const zModelConfig = z.object({ + completion_params: z.record(z.string(), z.unknown()).optional(), + mode: zLlmMode, + name: z.string(), + provider: z.string(), +}) + +/** + * AppDetailWithSite + */ +export const zAppDetailWithSite = z.object({ + access_mode: z.string().nullish(), + api_base_url: z.string().nullish(), + bound_agent_id: z.string().nullish(), + created_at: z.int().nullish(), + created_by: z.string().nullish(), + deleted_tools: z.array(zDeletedTool).optional(), + description: z.string().nullish(), + enable_api: z.boolean(), + enable_site: z.boolean(), + icon: z.string().nullish(), + icon_background: z.string().nullish(), + icon_type: z.string().nullish(), + icon_url: z.string().nullable(), + id: z.string(), + max_active_requests: z.int().nullish(), + mode: z.string(), + model_config: zModelConfig.nullish(), + name: z.string(), + site: zSite.nullish(), + tags: z.array(zTag).optional(), + tracing: zJsonValue.nullish(), + updated_at: z.int().nullish(), + updated_by: z.string().nullish(), + use_icon_as_answer_icon: z.boolean().nullish(), + workflow: zWorkflowPartial.nullish(), +}) + +/** + * AgentKind + * + * Agent implementation family. + * + * This leaves room for future non-Dify agent implementations while keeping + * the current roster/workflow APIs scoped to Dify Agent. + */ +export const zAgentKind = z.enum(['dify_agent']) + +/** + * AgentIconType + * + * Supported icon storage formats for Agent roster entries. + */ +export const zAgentIconType = z.enum(['emoji', 'image', 'link']) + +/** + * AgentPublishedReferenceResponse + */ +export const zAgentPublishedReferenceResponse = z.object({ + app_id: z.string(), + app_mode: z.string(), + app_name: z.string(), + node_ids: z.array(z.string()).optional(), + workflow_id: z.string(), + workflow_version: z.string(), +}) + +/** + * AgentScope + * + * Visibility and lifecycle scope of an Agent record. + */ +export const zAgentScope = z.enum(['roster', 'workflow_only']) + +/** + * AgentSource + * + * Origin that created or imported the Agent. + */ +export const zAgentSource = z.enum(['agent_app', 'imported', 'roster', 'system', 'workflow']) + +/** + * AgentStatus + * + * Soft lifecycle state for Agent records. + */ +export const zAgentStatus = z.enum(['active', 'archived']) + +/** + * AgentInviteOptionResponse + */ +export const zAgentInviteOptionResponse = z.object({ + active_config_snapshot: zAgentConfigSnapshotSummaryResponse.nullish(), + active_config_snapshot_id: z.string().nullish(), + agent_kind: zAgentKind, + app_id: z.string().nullish(), + archived_at: z.int().nullish(), + archived_by: z.string().nullish(), + created_at: z.int().nullish(), + created_by: z.string().nullish(), + description: z.string(), + existing_node_ids: z.array(z.string()).optional(), + icon: z.string().nullish(), + icon_background: z.string().nullish(), + icon_type: zAgentIconType.nullish(), + id: z.string(), + in_current_workflow_count: z.int().optional().default(0), + is_in_current_workflow: z.boolean().optional().default(false), + name: z.string(), + published_node_reference_count: z.int().optional().default(0), + published_reference_count: z.int().optional().default(0), + published_references: z.array(zAgentPublishedReferenceResponse).optional(), + role: z.string().optional().default(''), + scope: zAgentScope, + source: zAgentSource, + status: zAgentStatus, + updated_at: z.int().nullish(), + updated_by: z.string().nullish(), + workflow_id: z.string().nullish(), + workflow_node_id: z.string().nullish(), +}) + +/** + * AgentInviteOptionsResponse + */ +export const zAgentInviteOptionsResponse = z.object({ + data: z.array(zAgentInviteOptionResponse), + has_more: z.boolean(), + limit: z.int(), + page: z.int(), + total: z.int(), +}) + +/** + * AgentComposerAgentResponse + */ +export const zAgentComposerAgentResponse = z.object({ + active_config_snapshot_id: z.string().nullish(), + description: z.string(), + id: z.string(), + name: z.string(), + scope: zAgentScope, + status: zAgentStatus, +}) + +/** + * AppVariableConfig + */ +export const zAppVariableConfig = z.object({ + default: z.unknown().optional(), + name: z.string().min(1).max(255), + required: z.boolean().optional().default(false), + type: z.string().min(1).max(64), +}) + +/** + * AgentSoulPromptConfig + */ +export const zAgentSoulPromptConfig = z.object({ + system_prompt: z.string().optional().default(''), +}) + +/** + * AgentHumanContactConfig + */ +export const zAgentHumanContactConfig = z.object({ + channel: z.string().max(64).nullish(), + contact_id: z.string().max(255).nullish(), + contact_method: z.string().max(64).nullish(), + email: z.string().max(255).nullish(), + human_id: z.string().max(255).nullish(), + id: z.string().max(255).nullish(), + method: z.string().max(64).nullish(), + name: z.string().max(255).nullish(), + tenant_id: z.string().max(255).nullish(), +}) + +/** + * WorkflowNodeJobMode + */ +export const zWorkflowNodeJobMode = z.enum(['let_agent_figure_it_out', 'tell_agent_what_to_do']) + +/** + * WorkflowPreviousNodeOutputRef + */ +export const zWorkflowPreviousNodeOutputRef = z.object({ + key: z.string().max(255).nullish(), + name: z.string().max(255).nullish(), + node_id: z.string().max(255).nullish(), + output: z.string().max(255).nullish(), + selector: z.array(z.union([z.string(), z.int(), z.number(), z.boolean(), z.null()])).nullish(), + value_selector: z + .array(z.union([z.string(), z.int(), z.number(), z.boolean(), z.null()])) + .nullish(), + variable: z.string().max(255).nullish(), + variable_selector: z + .array(z.union([z.string(), z.int(), z.number(), z.boolean(), z.null()])) + .nullish(), +}) + +/** + * DeclaredOutputType + */ +export const zDeclaredOutputType = z.enum([ + 'array', + 'boolean', + 'file', + 'number', + 'object', + 'string', +]) + +/** + * AgentComposerNodeJobCandidatesResponse + */ +export const zAgentComposerNodeJobCandidatesResponse = z.object({ + declare_output_types: z.array(zDeclaredOutputType).optional(), + human_contacts: z.array(zAgentHumanContactConfig).optional(), + previous_node_outputs: z.array(zWorkflowPreviousNodeOutputRef).optional(), +}) + +/** + * AgentComposerDifyToolCandidateResponse + */ +export const zAgentComposerDifyToolCandidateResponse = z.object({ + description: z.string().nullish(), + granularity: z.string().nullish(), + id: z.string().nullish(), + name: z.string().nullish(), + plugin_id: z.string().nullish(), + provider: z.string().nullish(), + provider_id: z.string().nullish(), + tools_count: z.int().nullish(), +}) + +/** + * AgentKnowledgeDatasetConfig + */ +export const zAgentKnowledgeDatasetConfig = z.object({ + description: z.string().nullish(), + id: z.string().max(255).nullish(), + name: z.string().max(255).nullish(), +}) + +/** + * AgentComposerSkillCandidateResponse + */ +export const zAgentComposerSkillCandidateResponse = z.object({ + description: z.string().nullish(), + file_id: z.string().max(255).nullish(), + full_archive_file_id: z.string().max(255).nullish(), + full_archive_key: z.string().max(512).nullish(), + id: z.string().max(255).nullish(), + kind: z.literal('skill').optional().default('skill'), + manifest_files: z.array(z.string()).nullish(), + name: z.string().max(255).nullish(), + path: z.string().nullish(), + skill_md_file_id: z.string().max(255).nullish(), + skill_md_key: z.string().max(512).nullish(), +}) + +/** + * AgentComposerFileCandidateResponse + */ +export const zAgentComposerFileCandidateResponse = z.object({ + drive_key: z.string().max(512).nullish(), + file_id: z.string().max(255).nullish(), + id: z.string().max(255).nullish(), + kind: z.literal('file').optional().default('file'), + name: z.string().max(255).nullish(), + reference: z.string().max(255).nullish(), + remote_url: z.string().nullish(), + tenant_id: z.string().max(255).nullish(), + transfer_method: z.string().max(64).nullish(), + type: z.string().max(64).nullish(), + upload_file_id: z.string().max(255).nullish(), + url: z.string().nullish(), +}) + +/** + * EnvSuggestion + */ +export const zEnvSuggestion = z.object({ + key: z.string(), + reason: z.string().optional().default(''), + secret_likely: z.boolean().optional().default(false), +}) + +/** + * CliToolSuggestion + */ +export const zCliToolSuggestion = z.object({ + command: z.string().optional().default(''), + description: z.string().optional().default(''), + env_suggestions: z.array(zEnvSuggestion).optional(), + inferred_from: z.string().optional().default(''), + install_commands: z.array(z.string()).optional(), + name: z.string(), +}) + +/** + * SkillToolInferenceResult + */ +export const zSkillToolInferenceResult = z.object({ + cli_tools: z.array(zCliToolSuggestion).optional(), + inferable: z.boolean(), + reason: z.string().nullish(), +}) + +/** + * AgentConfigRevisionOperation + * + * Audit operation recorded for Agent Soul version/revision changes. + */ +export const zAgentConfigRevisionOperation = z.enum([ + 'create_version', + 'save_current_version', + 'save_new_agent', + 'save_new_version', + 'save_to_roster', +]) + +/** + * AgentConfigRevisionResponse + */ +export const zAgentConfigRevisionResponse = z.object({ + created_at: z.int().nullish(), + created_by: z.string().nullish(), + current_snapshot_id: z.string(), + id: z.string(), + operation: zAgentConfigRevisionOperation, + previous_snapshot_id: z.string().nullish(), + revision: z.int(), + summary: z.string().nullish(), + version_note: z.string().nullish(), +}) + +/** + * AgentEnvVariableConfig + */ +export const zAgentEnvVariableConfig = z.object({ + default: z + .union([ + z.string(), + z.int(), + z.number(), + z.boolean(), + z.array(z.string()), + z.array(z.int()), + z.array(z.number()), + z.array(z.boolean()), + ]) + .nullish(), + env_name: z.string().max(255).nullish(), + key: z.string().max(255).nullish(), + name: z.string().max(255).nullish(), + required: z.boolean().optional().default(false), + type: z.string().max(64).nullish(), + value: z + .union([ + z.string(), + z.int(), + z.number(), + z.boolean(), + z.array(z.string()), + z.array(z.int()), + z.array(z.number()), + z.array(z.boolean()), + ]) + .nullish(), + variable: z.string().max(255).nullish(), +}) + +/** + * AgentHumanToolConfig + */ +export const zAgentHumanToolConfig = z.object({ + description: z.string().nullish(), + enabled: z.boolean().optional().default(true), + name: z.string().max(255).nullish(), +}) + +/** + * AgentSoulHumanConfig + */ +export const zAgentSoulHumanConfig = z.object({ + contacts: z.array(zAgentHumanContactConfig).optional(), + tools: z.array(zAgentHumanToolConfig).optional(), +}) + +/** + * AgentKnowledgeQueryConfig + */ +export const zAgentKnowledgeQueryConfig = z.object({ + query: z.string().nullish(), + score_threshold: z.number().gte(0).lte(1).nullish(), + score_threshold_enabled: z.boolean().nullish(), + top_k: z.int().gte(1).nullish(), +}) + +/** + * AgentKnowledgeQueryMode + */ +export const zAgentKnowledgeQueryMode = z.enum(['generated_query', 'user_query']) + +/** + * AgentSoulKnowledgeConfig + */ +export const zAgentSoulKnowledgeConfig = z.object({ + datasets: z.array(zAgentKnowledgeDatasetConfig).optional(), + query_config: zAgentKnowledgeQueryConfig.optional(), + query_mode: zAgentKnowledgeQueryMode.nullish(), +}) + +/** + * AgentMemoryArtifactConfig + */ +export const zAgentMemoryArtifactConfig = z.object({ + id: z.string().max(255).nullish(), + name: z.string().max(255).nullish(), + type: z.string().max(64).nullish(), + url: z.string().nullish(), +}) + +/** + * AgentSoulMemoryConfig + */ +export const zAgentSoulMemoryConfig = z.object({ + artifacts: z.array(zAgentMemoryArtifactConfig).optional(), + budget: z.string().nullish(), + scope: z.string().nullish(), +}) + +/** + * AgentSoulModelCredentialRef + * + * Reference to model credentials resolved only at runtime. + */ +export const zAgentSoulModelCredentialRef = z.object({ + id: z.string().max(255).nullish(), + provider: z.string().max(255).nullish(), + type: z.string().min(1).max(64), +}) + +/** + * AgentSandboxProviderConfig + */ +export const zAgentSandboxProviderConfig = z.object({ + cpu: z.int().gte(1).nullish(), + env: z.array(zAgentEnvVariableConfig).optional(), + image: z.string().nullish(), + working_dir: z.string().nullish(), +}) + +/** + * AgentSoulSandboxConfig + */ +export const zAgentSoulSandboxConfig = z.object({ + config: zAgentSandboxProviderConfig.optional(), + provider: z.string().nullish(), +}) + +/** + * AgentFileRefConfig + */ +export const zAgentFileRefConfig = z.object({ + drive_key: z.string().max(512).nullish(), + file_id: z.string().max(255).nullish(), + id: z.string().max(255).nullish(), + name: z.string().max(255).nullish(), + reference: z.string().max(255).nullish(), + remote_url: z.string().nullish(), + tenant_id: z.string().max(255).nullish(), + transfer_method: z.string().max(64).nullish(), + type: z.string().max(64).nullish(), + upload_file_id: z.string().max(255).nullish(), + url: z.string().nullish(), +}) + +/** + * AgentSoulSkillsFilesConfig + */ +export const zAgentSoulSkillsFilesConfig = z.object({ + files: z.array(zAgentFileRefConfig).optional(), + skills: z.array(zAgentSkillRefConfig).optional(), +}) + +/** + * WorkflowNodeJobMetadata + */ +export const zWorkflowNodeJobMetadata = z.object({ + agent_soul: z.record(z.string(), z.unknown()).nullish(), + file_refs: z.array(zAgentFileRefConfig).nullish(), +}) + +/** + * DeclaredArrayItem + * + * Per-item shape for an ``array``-typed declared output. + * + * PRD §OUTPUT 配置框 keeps arrays one level deep on first version; nested arrays + * are rejected so the runtime type checker and JSON Schema stay easy to reason + * about. Stage 4 §4.2. + */ +export const zDeclaredArrayItem = z.object({ + description: z.string().nullish(), + type: zDeclaredOutputType, +}) + +/** + * DeclaredOutputFileConfig + * + * File-type output metadata. Both lists empty means "any file accepted". + */ +export const zDeclaredOutputFileConfig = z.object({ + extensions: z.array(z.string()).optional(), + mime_types: z.array(z.string()).optional(), +}) + +/** + * AgentCliToolAuthorizationStatus + * + * Authorization state for Agent-scoped CLI tools. + * + * Missing status keeps backward compatibility with draft rows and CLI tools that + * do not need pre-authorization. Explicit denied-like states are blocked by the + * composer/publish validators and skipped by runtime request builders. + */ +export const zAgentCliToolAuthorizationStatus = z.enum([ + 'allowed', + 'authorized', + 'denied', + 'forbidden', + 'not_required', + 'pending', + 'pre_authorized', + 'unauthorized', +]) + +/** + * AgentPermissionConfig + */ +export const zAgentPermissionConfig = z.object({ + allowed: z.boolean().nullish(), + state: z.string().max(64).nullish(), + status: z.string().max(64).nullish(), +}) + +/** + * AgentSecretRefConfig + */ +export const zAgentSecretRefConfig = z.object({ + credential_id: z.string().max(255).nullish(), + env_name: z.string().max(255).nullish(), + id: z.string().max(255).nullish(), + key: z.string().max(255).nullish(), + name: z.string().max(255).nullish(), + permission: zAgentPermissionConfig.nullish(), + permission_status: z.string().max(64).nullish(), + provider: z.string().max(255).nullish(), + provider_credential_id: z.string().max(255).nullish(), + ref: z.string().max(255).nullish(), + type: z.string().max(64).nullish(), + variable: z.string().max(255).nullish(), +}) + +/** + * AgentSoulEnvConfig + */ +export const zAgentSoulEnvConfig = z.object({ + secret_refs: z.array(zAgentSecretRefConfig).optional(), + variables: z.array(zAgentEnvVariableConfig).optional(), +}) + +/** + * AgentCliToolEnvConfig + */ +export const zAgentCliToolEnvConfig = z.object({ + secret_refs: z.array(zAgentSecretRefConfig).optional(), + variables: z.array(zAgentEnvVariableConfig).optional(), +}) + +/** + * AgentCliToolRiskLevel + * + * Risk marker for CLI tool bootstrap commands. + */ +export const zAgentCliToolRiskLevel = z.enum(['dangerous', 'safe', 'unknown']) + +/** + * AgentCliToolConfig + */ +export const zAgentCliToolConfig = z.object({ + approved: z.boolean().optional().default(false), + authorization_status: zAgentCliToolAuthorizationStatus.nullish(), + command: z.string().nullish(), + dangerous: z.boolean().optional().default(false), + dangerous_accepted: z.boolean().optional().default(false), + dangerous_acknowledged: z.boolean().optional().default(false), + dangerous_command: z.boolean().optional().default(false), + description: z.string().nullish(), + enabled: z.boolean().optional().default(true), + env: zAgentCliToolEnvConfig.optional(), + id: z.string().max(255).nullish(), + inferred_from: z.string().max(255).nullish(), + install: z.string().nullish(), + install_command: z.string().nullish(), + install_commands: z.array(z.string()).optional(), + invoke_metadata: z.record(z.string(), z.unknown()).optional(), + label: z.string().max(255).nullish(), + name: z.string().max(255).nullish(), + permission: zAgentPermissionConfig.nullish(), + pre_authorized: z.boolean().nullish(), + requires_confirmation: z.boolean().optional().default(false), + risk_accepted: z.boolean().optional().default(false), + risk_level: zAgentCliToolRiskLevel.nullish(), + setup_command: z.string().nullish(), + tool_name: z.string().max(255).nullish(), +}) + +/** + * AgentComposerSoulCandidatesResponse + */ +export const zAgentComposerSoulCandidatesResponse = z.object({ + cli_tools: z.array(zAgentCliToolConfig).optional(), + dify_tools: z.array(zAgentComposerDifyToolCandidateResponse).optional(), + human_contacts: z.array(zAgentHumanContactConfig).optional(), + knowledge_datasets: z.array(zAgentKnowledgeDatasetConfig).optional(), + skills_files: z + .array( + z.union([ + z + .object({ + kind: z.literal('skill'), + }) + .and(zAgentComposerSkillCandidateResponse), + z + .object({ + kind: z.literal('file'), + }) + .and(zAgentComposerFileCandidateResponse), + ]), + ) + .optional(), +}) + +/** + * AgentComposerCandidatesResponse + */ +export const zAgentComposerCandidatesResponse = z.object({ + allowed_node_job_candidates: zAgentComposerNodeJobCandidatesResponse.optional(), + allowed_soul_candidates: zAgentComposerSoulCandidatesResponse.optional(), + capabilities: zComposerCandidateCapabilities.optional(), + truncated: z.boolean().optional().default(false), + variant: zComposerVariant, +}) + +/** + * AgentModerationIOConfig + */ +export const zAgentModerationIoConfig = z.object({ + enabled: z.boolean().optional().default(false), + preset_response: z.string().nullish(), +}) + +/** + * AgentModerationProviderConfig + */ +export const zAgentModerationProviderConfig = z.object({ + api_based_extension_id: z.string().nullish(), + inputs_config: zAgentModerationIoConfig.nullish(), + keywords: z.string().nullish(), + outputs_config: zAgentModerationIoConfig.nullish(), +}) + +/** + * AgentSensitiveWordAvoidanceFeatureConfig + */ +export const zAgentSensitiveWordAvoidanceFeatureConfig = z.object({ + config: zAgentModerationProviderConfig.nullish(), + enabled: z.boolean().optional().default(false), + type: z.string().nullish(), +}) + +/** + * AgentModelResponseFormatConfig + */ +export const zAgentModelResponseFormatConfig = z.object({ + type: z.string().max(64).nullish(), +}) + +/** + * AgentSoulModelSettings + */ +export const zAgentSoulModelSettings = z.object({ + frequency_penalty: z.number().nullish(), + max_tokens: z.int().nullish(), + presence_penalty: z.number().nullish(), + response_format: zAgentModelResponseFormatConfig.nullish(), + stop: z.array(z.string()).nullish(), + temperature: z.number().nullish(), + top_p: z.number().nullish(), +}) + +/** + * AgentSoulModelConfig + * + * Stable model selection for Agent runtime without storing secret values. + */ +export const zAgentSoulModelConfig = z.object({ + credential_ref: zAgentSoulModelCredentialRef.nullish(), + model: z.string().min(1).max(255), + model_provider: z.string().min(1).max(255), + model_settings: zAgentSoulModelSettings.optional(), + plugin_id: z.string().min(1).max(255), +}) + +/** + * AgentSuggestedQuestionsAfterAnswerFeatureConfig + */ +export const zAgentSuggestedQuestionsAfterAnswerFeatureConfig = z.object({ + enabled: z.boolean().optional().default(false), + model: zAgentSoulModelConfig.nullish(), + prompt: z.string().nullish(), +}) + +/** + * AgentAppFeaturesPayload + * + * Presentation features configurable on an Agent App. + * + * All fields are optional; an omitted field is reset to its disabled/empty + * default (the config form sends the full desired feature state on save). + */ +export const zAgentAppFeaturesPayload = z.object({ + opening_statement: z.string().nullish(), + retriever_resource: zAgentFeatureToggleConfig.nullish(), + sensitive_word_avoidance: zAgentSensitiveWordAvoidanceFeatureConfig.nullish(), + speech_to_text: zAgentFeatureToggleConfig.nullish(), + suggested_questions: z.array(z.string()).nullish(), + suggested_questions_after_answer: zAgentSuggestedQuestionsAfterAnswerFeatureConfig.nullish(), + text_to_speech: zAgentTextToSpeechFeatureConfig.nullish(), +}) + +/** + * AgentSoulAppFeaturesConfig + */ +export const zAgentSoulAppFeaturesConfig = z.object({ + opening_statement: z.string().nullish(), + retriever_resource: zAgentFeatureToggleConfig.nullish(), + sensitive_word_avoidance: zAgentSensitiveWordAvoidanceFeatureConfig.nullish(), + speech_to_text: zAgentFeatureToggleConfig.nullish(), + suggested_questions: z.array(z.string()).nullish(), + suggested_questions_after_answer: zAgentSuggestedQuestionsAfterAnswerFeatureConfig.nullish(), + text_to_speech: zAgentTextToSpeechFeatureConfig.nullish(), +}) + +/** + * DeclaredOutputCheckConfig + * + * File-output content check via a model-based comparison against a benchmark file. + * + * Per PRD §OUTPUT 配置框, output check is **file-only** and optional. Stage 4 §4.3. + */ +export const zDeclaredOutputCheckConfig = z.object({ + benchmark_file_ref: zAgentFileRefConfig.nullish(), + enabled: z.boolean().optional().default(false), + model_ref: zAgentSoulModelConfig.nullish(), + prompt: z.string().nullish(), +}) + +/** + * AgentSoulDifyToolCredentialRef + * + * Reference to a stored Dify Plugin Tool credential. + * + * Secret values are resolved only at runtime. The legacy ``credential_id`` + * field is accepted by :class:`AgentSoulDifyToolConfig` and normalized here so + * old Agent tool payloads can be read while new payloads stay explicit. + */ +export const zAgentSoulDifyToolCredentialRef = z.object({ + id: z.string().max(255).nullish(), + provider: z.string().max(255).nullish(), + type: z.enum(['provider', 'tool']).optional().default('tool'), +}) + +/** + * AgentSoulDifyToolConfig + * + * One Dify Plugin Tool configured on Agent Soul. + * + * The API backend prepares this persisted product shape into + * ``DifyPluginToolConfig`` before sending a run request to Agent backend. + * ``provider_id`` keeps compatibility with existing Agent tool config payloads; + * new callers should send ``plugin_id`` + ``provider`` when available. + */ +export const zAgentSoulDifyToolConfig = z.object({ + credential_ref: zAgentSoulDifyToolCredentialRef.nullish(), + credential_type: z.enum(['api-key', 'oauth2', 'unauthorized']).optional().default('api-key'), + description: z.string().nullish(), + enabled: z.boolean().optional().default(true), + name: z.string().max(255).nullish(), + plugin_id: z.string().max(255).nullish(), + provider: z.string().max(255).nullish(), + provider_id: z.string().max(255).nullish(), + provider_type: z.string().optional().default('plugin'), + runtime_parameters: z + .record( + z.string(), + z + .union([ + z.string(), + z.int(), + z.number(), + z.boolean(), + z.array(z.string()), + z.array(z.int()), + z.array(z.number()), + z.array(z.boolean()), + ]) + .nullable(), + ) + .optional(), + tool_name: z.string().min(1).max(255).nullish(), +}) + +/** + * AgentSoulToolsConfig + */ +export const zAgentSoulToolsConfig = z.object({ + cli_tools: z.array(zAgentCliToolConfig).optional(), + dify_tools: z.array(zAgentSoulDifyToolConfig).optional(), +}) + +/** + * AgentSoulConfig + */ +export const zAgentSoulConfig = z.object({ + app_features: zAgentSoulAppFeaturesConfig.optional(), + app_variables: z.array(zAppVariableConfig).optional(), + env: zAgentSoulEnvConfig.optional(), + human: zAgentSoulHumanConfig.optional(), + knowledge: zAgentSoulKnowledgeConfig.optional(), + memory: zAgentSoulMemoryConfig.optional(), + misc_legacy: zAgentSoulAppFeaturesConfig.optional(), + model: zAgentSoulModelConfig.nullish(), + prompt: zAgentSoulPromptConfig.optional(), + sandbox: zAgentSoulSandboxConfig.optional(), + schema_version: z.int().optional().default(1), + skills_files: zAgentSoulSkillsFilesConfig.optional(), + tools: zAgentSoulToolsConfig.optional(), +}) + +/** + * AgentAppComposerResponse + */ +export const zAgentAppComposerResponse = z.object({ + active_config_snapshot: zAgentConfigSnapshotSummaryResponse, + agent: zAgentComposerAgentResponse, + agent_soul: zAgentSoulConfig, + save_options: z.array(zComposerSaveStrategy), + validation: zComposerValidationFindingsResponse.nullish(), + variant: z.literal('agent_app'), +}) + +/** + * AgentConfigSnapshotDetailResponse + */ +export const zAgentConfigSnapshotDetailResponse = z.object({ + agent_id: z.string().nullish(), + config_snapshot: zAgentSoulConfig, + created_at: z.int().nullish(), + created_by: z.string().nullish(), + id: z.string(), + revisions: z.array(zAgentConfigRevisionResponse).optional(), + summary: z.string().nullish(), + version: z.int(), + version_note: z.string().nullish(), +}) + +/** + * OutputErrorStrategy + * + * Per-output failure handling strategy. + * + * Mirrors ``graphon.ErrorStrategy`` but scoped to a single declared output of + * a Workflow Agent Node. The runtime applies the strategy after type check or + * output check fails and any configured retry attempts have been exhausted. + */ +export const zOutputErrorStrategy = z.enum(['default_value', 'fail_branch', 'stop']) + +/** + * DeclaredOutputRetryConfig + * + * Per-output retry configuration that mirrors ``graphon.RetryConfig`` shape. + */ +export const zDeclaredOutputRetryConfig = z.object({ + enabled: z.boolean().optional().default(false), + max_retries: z.int().gte(0).lte(10).optional().default(0), + retry_interval_ms: z.int().gte(0).lte(60000).optional().default(0), +}) + +/** + * DeclaredOutputFailureStrategy + * + * Per-output failure handling. + * + * A single strategy applies to both ``type_check`` and ``output_check`` failures + * (PRD does not distinguish them at the UX level). Stage 4 §4.4. + */ +export const zDeclaredOutputFailureStrategy = z.object({ + default_value: z.unknown().optional(), + on_failure: zOutputErrorStrategy.optional().default('stop'), + retry: zDeclaredOutputRetryConfig.optional(), +}) + +/** + * DeclaredOutputConfig + * + * One declared output of a Workflow Agent Node. + * + * Stage 4 normalizes the shape: ``check`` is singular (was ``checks: list`` in + * stage 3), and ``failure_strategy`` defaults to a populated value so runtime + * code can call ``output.failure_strategy.on_failure`` without None-guards. + */ +export const zDeclaredOutputConfig = z.object({ + array_item: zDeclaredArrayItem.nullish(), + check: zDeclaredOutputCheckConfig.nullish(), + description: z.string().nullish(), + failure_strategy: zDeclaredOutputFailureStrategy.optional(), + file: zDeclaredOutputFileConfig.nullish(), + id: z.string().nullish(), + name: z.string().min(1).max(255), + required: z.boolean().optional().default(true), + type: zDeclaredOutputType, +}) + +/** + * WorkflowNodeJobConfig + */ +export const zWorkflowNodeJobConfig = z.object({ + declared_outputs: z.array(zDeclaredOutputConfig).optional(), + human_contacts: z.array(zAgentHumanContactConfig).optional(), + metadata: zWorkflowNodeJobMetadata.optional(), + mode: zWorkflowNodeJobMode.optional().default('tell_agent_what_to_do'), + previous_node_output_refs: z.array(zWorkflowPreviousNodeOutputRef).optional(), + schema_version: z.int().optional().default(1), + workflow_prompt: z.string().optional().default(''), +}) + +/** + * ComposerSavePayload + */ +export const zComposerSavePayload = z.object({ + agent_soul: zAgentSoulConfig.nullish(), + binding: zComposerBindingPayload.nullish(), + client_revision_id: z.string().nullish(), + idempotency_key: z.string().nullish(), + new_agent_name: z.string().min(1).max(255).nullish(), + node_job: zWorkflowNodeJobConfig.nullish(), + save_strategy: zComposerSaveStrategy, + soul_lock: zComposerSoulLockPayload.optional(), + variant: zComposerVariant, + version_note: z.string().nullish(), +}) + +/** + * AppPartial + */ +export const zAppPartialWritable = z.object({ + access_mode: z.string().nullish(), + author_name: z.string().nullish(), + bound_agent_id: z.string().nullish(), + create_user_name: z.string().nullish(), + created_at: z.int().nullish(), + created_by: z.string().nullish(), + description: z.string().nullish(), + has_draft_trigger: z.boolean().nullish(), + icon: z.string().nullish(), + icon_background: z.string().nullish(), + icon_type: z.string().nullish(), + id: z.string(), + is_starred: z.boolean().optional().default(false), + max_active_requests: z.int().nullish(), + mode: z.string(), + model_config: zModelConfigPartial.nullish(), + name: z.string(), + tags: z.array(zTag).optional(), + updated_at: z.int().nullish(), + updated_by: z.string().nullish(), + use_icon_as_answer_icon: z.boolean().nullish(), + workflow: zWorkflowPartial.nullish(), +}) + +/** + * AppPagination + */ +export const zAppPaginationWritable = z.object({ + data: z.array(zAppPartialWritable), + has_more: z.boolean(), + limit: z.int(), + page: z.int(), + total: z.int(), +}) + +/** + * Site + */ +export const zSiteWritable = z.object({ + chat_color_theme: z.string().nullish(), + chat_color_theme_inverted: z.boolean(), + copyright: z.string().nullish(), + custom_disclaimer: z.string().nullish(), + default_language: z.string(), + description: z.string().nullish(), + icon: z.string().nullish(), + icon_background: z.string().nullish(), + icon_type: z.string().nullish(), + privacy_policy: z.string().nullish(), + show_workflow_steps: z.boolean(), + title: z.string(), + use_icon_as_answer_icon: z.boolean(), +}) + +/** + * AppDetailWithSite + */ +export const zAppDetailWithSiteWritable = z.object({ + access_mode: z.string().nullish(), + api_base_url: z.string().nullish(), + bound_agent_id: z.string().nullish(), + created_at: z.int().nullish(), + created_by: z.string().nullish(), + deleted_tools: z.array(zDeletedTool).optional(), + description: z.string().nullish(), + enable_api: z.boolean(), + enable_site: z.boolean(), + icon: z.string().nullish(), + icon_background: z.string().nullish(), + icon_type: z.string().nullish(), + id: z.string(), + max_active_requests: z.int().nullish(), + mode: z.string(), + model_config: zModelConfig.nullish(), + name: z.string(), + site: zSiteWritable.nullish(), + tags: z.array(zTag).optional(), + tracing: zJsonValue.nullish(), + updated_at: z.int().nullish(), + updated_by: z.string().nullish(), + use_icon_as_answer_icon: z.boolean().nullish(), + workflow: zWorkflowPartial.nullish(), +}) + +export const zGetAgentQuery = z.object({ + creator_ids: z.array(z.string()).optional(), + is_created_by_me: z.boolean().optional(), + limit: z.int().gte(1).lte(100).optional().default(20), + mode: z + .enum([ + 'advanced-chat', + 'agent', + 'agent-chat', + 'all', + 'channel', + 'chat', + 'completion', + 'workflow', + ]) + .optional() + .default('all'), + name: z.string().optional(), + page: z.int().gte(1).lte(99999).optional().default(1), + sort_by: z + .enum(['earliest_created', 'last_modified', 'recently_created']) + .optional() + .default('last_modified'), + tag_ids: z.array(z.string()).optional(), +}) + +/** + * Agent app list + */ +export const zGetAgentResponse = zAppPagination + +export const zPostAgentBody = zAgentAppCreatePayload + +/** + * Agent app created successfully + */ +export const zPostAgentResponse = zAppDetailWithSite + +export const zGetAgentInviteOptionsQuery = z.object({ + app_id: z.string().optional(), + keyword: z.string().optional(), + limit: z.int().gte(1).lte(100).optional().default(20), + page: z.int().gte(1).optional().default(1), +}) + +/** + * Agent invite options + */ +export const zGetAgentInviteOptionsResponse = zAgentInviteOptionsResponse + +export const zDeleteAgentByAgentIdPath = z.object({ + agent_id: z.string(), +}) + +/** + * Agent app deleted successfully + */ +export const zDeleteAgentByAgentIdResponse = z.void() + +export const zGetAgentByAgentIdPath = z.object({ + agent_id: z.string(), +}) + +/** + * Agent app detail + */ +export const zGetAgentByAgentIdResponse = zAppDetailWithSite + +export const zPutAgentByAgentIdBody = zUpdateAppPayload + +export const zPutAgentByAgentIdPath = z.object({ + agent_id: z.string(), +}) + +/** + * Agent app updated successfully + */ +export const zPutAgentByAgentIdResponse = zAppDetailWithSite + +export const zGetAgentByAgentIdComposerPath = z.object({ + agent_id: z.string(), +}) + +/** + * Agent app composer state + */ +export const zGetAgentByAgentIdComposerResponse = zAgentAppComposerResponse + +export const zPutAgentByAgentIdComposerBody = zComposerSavePayload + +export const zPutAgentByAgentIdComposerPath = z.object({ + agent_id: z.string(), +}) + +/** + * Agent app composer saved + */ +export const zPutAgentByAgentIdComposerResponse = zAgentAppComposerResponse + +export const zGetAgentByAgentIdComposerCandidatesPath = z.object({ + agent_id: z.string(), +}) + +/** + * Agent app composer candidates + */ +export const zGetAgentByAgentIdComposerCandidatesResponse = zAgentComposerCandidatesResponse + +export const zPostAgentByAgentIdComposerValidateBody = zComposerSavePayload + +export const zPostAgentByAgentIdComposerValidatePath = z.object({ + agent_id: z.string(), +}) + +/** + * Agent app composer validation result + */ +export const zPostAgentByAgentIdComposerValidateResponse = zAgentComposerValidateResponse + +export const zGetAgentByAgentIdDriveFilesPath = z.object({ + agent_id: z.string(), +}) + +export const zGetAgentByAgentIdDriveFilesQuery = z.object({ + prefix: z.string().optional().default(''), +}) + +/** + * Drive entries + */ +export const zGetAgentByAgentIdDriveFilesResponse = zAgentDriveListResponse + +export const zGetAgentByAgentIdDriveFilesDownloadPath = z.object({ + agent_id: z.string(), +}) + +export const zGetAgentByAgentIdDriveFilesDownloadQuery = z.object({ + key: z.string().min(1), +}) + +/** + * Signed URL + */ +export const zGetAgentByAgentIdDriveFilesDownloadResponse = zAgentDriveDownloadResponse + +export const zGetAgentByAgentIdDriveFilesPreviewPath = z.object({ + agent_id: z.string(), +}) + +export const zGetAgentByAgentIdDriveFilesPreviewQuery = z.object({ + key: z.string().min(1), +}) + +/** + * Preview + */ +export const zGetAgentByAgentIdDriveFilesPreviewResponse = zAgentDrivePreviewResponse + +export const zPostAgentByAgentIdFeaturesBody = zAgentAppFeaturesPayload + +export const zPostAgentByAgentIdFeaturesPath = z.object({ + agent_id: z.string(), +}) + +/** + * Features updated successfully + */ +export const zPostAgentByAgentIdFeaturesResponse = zSimpleResultResponse + +export const zDeleteAgentByAgentIdFilesPath = z.object({ + agent_id: z.string(), +}) + +export const zDeleteAgentByAgentIdFilesQuery = z.object({ + key: z.string().min(1), +}) + +/** + * File removed + */ +export const zDeleteAgentByAgentIdFilesResponse = zAgentDriveDeleteResponse + +export const zPostAgentByAgentIdFilesBody = zAgentDriveFilePayload + +export const zPostAgentByAgentIdFilesPath = z.object({ + agent_id: z.string(), +}) + +/** + * File committed into the agent drive + */ +export const zPostAgentByAgentIdFilesResponse = zAgentDriveFileCommitResponse + +export const zGetAgentByAgentIdReferencingWorkflowsPath = z.object({ + agent_id: z.string(), +}) + +/** + * Referencing workflows listed successfully + */ +export const zGetAgentByAgentIdReferencingWorkflowsResponse = zAgentReferencingWorkflowsResponse + +export const zGetAgentByAgentIdSandboxFilesPath = z.object({ + agent_id: z.string(), +}) + +export const zGetAgentByAgentIdSandboxFilesQuery = z.object({ + conversation_id: z.string().min(1), + path: z.string().optional().default('.'), +}) + +/** + * Listing returned + */ +export const zGetAgentByAgentIdSandboxFilesResponse = zSandboxListResponse + +export const zGetAgentByAgentIdSandboxFilesReadPath = z.object({ + agent_id: z.string(), +}) + +export const zGetAgentByAgentIdSandboxFilesReadQuery = z.object({ + conversation_id: z.string().min(1), + path: z.string().min(1), +}) + +/** + * Preview returned + */ +export const zGetAgentByAgentIdSandboxFilesReadResponse = zSandboxReadResponse + +export const zPostAgentByAgentIdSandboxFilesUploadBody = zAgentSandboxUploadPayload + +export const zPostAgentByAgentIdSandboxFilesUploadPath = z.object({ + agent_id: z.string(), +}) + +/** + * Uploaded + */ +export const zPostAgentByAgentIdSandboxFilesUploadResponse = zSandboxUploadResponse + +export const zPostAgentByAgentIdSkillsStandardizePath = z.object({ + agent_id: z.string(), +}) + +/** + * Skill standardized into drive + */ +export const zPostAgentByAgentIdSkillsStandardizeResponse = zAgentSkillStandardizeResponse + +export const zPostAgentByAgentIdSkillsUploadPath = z.object({ + agent_id: z.string(), +}) + +/** + * Skill validated + */ +export const zPostAgentByAgentIdSkillsUploadResponse = zAgentSkillUploadResponse + +export const zDeleteAgentByAgentIdSkillsBySlugPath = z.object({ + agent_id: z.string(), + slug: z.string(), +}) + +/** + * Skill removed + */ +export const zDeleteAgentByAgentIdSkillsBySlugResponse = zAgentDriveDeleteResponse + +export const zPostAgentByAgentIdSkillsBySlugInferToolsPath = z.object({ + agent_id: z.string(), + slug: z.string(), +}) + +/** + * Inference result (draft suggestions, nothing persisted) + */ +export const zPostAgentByAgentIdSkillsBySlugInferToolsResponse = zSkillToolInferenceResult + +export const zGetAgentByAgentIdVersionsPath = z.object({ + agent_id: z.string(), +}) + +/** + * Agent versions + */ +export const zGetAgentByAgentIdVersionsResponse = zAgentConfigSnapshotListResponse + +export const zGetAgentByAgentIdVersionsByVersionIdPath = z.object({ + agent_id: z.string(), + version_id: z.string(), +}) + +/** + * Agent version detail + */ +export const zGetAgentByAgentIdVersionsByVersionIdResponse = zAgentConfigSnapshotDetailResponse diff --git a/packages/contracts/generated/api/console/agents/orpc.gen.ts b/packages/contracts/generated/api/console/agents/orpc.gen.ts deleted file mode 100644 index 0a01a8f3c9..0000000000 --- a/packages/contracts/generated/api/console/agents/orpc.gen.ts +++ /dev/null @@ -1,100 +0,0 @@ -// This file is auto-generated by @hey-api/openapi-ts - -import { oc } from '@orpc/contract' -import * as z from 'zod' - -import { - zGetAgentsByAgentIdPath, - zGetAgentsByAgentIdResponse, - zGetAgentsByAgentIdVersionsByVersionIdPath, - zGetAgentsByAgentIdVersionsByVersionIdResponse, - zGetAgentsByAgentIdVersionsPath, - zGetAgentsByAgentIdVersionsResponse, - zGetAgentsInviteOptionsQuery, - zGetAgentsInviteOptionsResponse, - zGetAgentsQuery, - zGetAgentsResponse, -} from './zod.gen' - -export const get = oc - .route({ - inputStructure: 'detailed', - method: 'GET', - operationId: 'getAgentsInviteOptions', - path: '/agents/invite-options', - tags: ['console'], - }) - .input(z.object({ query: zGetAgentsInviteOptionsQuery.optional() })) - .output(zGetAgentsInviteOptionsResponse) - -export const inviteOptions = { - get, -} - -export const get2 = oc - .route({ - inputStructure: 'detailed', - method: 'GET', - operationId: 'getAgentsByAgentIdVersionsByVersionId', - path: '/agents/{agent_id}/versions/{version_id}', - tags: ['console'], - }) - .input(z.object({ params: zGetAgentsByAgentIdVersionsByVersionIdPath })) - .output(zGetAgentsByAgentIdVersionsByVersionIdResponse) - -export const byVersionId = { - get: get2, -} - -export const get3 = oc - .route({ - inputStructure: 'detailed', - method: 'GET', - operationId: 'getAgentsByAgentIdVersions', - path: '/agents/{agent_id}/versions', - tags: ['console'], - }) - .input(z.object({ params: zGetAgentsByAgentIdVersionsPath })) - .output(zGetAgentsByAgentIdVersionsResponse) - -export const versions = { - get: get3, - byVersionId, -} - -export const get4 = oc - .route({ - inputStructure: 'detailed', - method: 'GET', - operationId: 'getAgentsByAgentId', - path: '/agents/{agent_id}', - tags: ['console'], - }) - .input(z.object({ params: zGetAgentsByAgentIdPath })) - .output(zGetAgentsByAgentIdResponse) - -export const byAgentId = { - get: get4, - versions, -} - -export const get5 = oc - .route({ - inputStructure: 'detailed', - method: 'GET', - operationId: 'getAgents', - path: '/agents', - tags: ['console'], - }) - .input(z.object({ query: zGetAgentsQuery.optional() })) - .output(zGetAgentsResponse) - -export const agents = { - get: get5, - inviteOptions, - byAgentId, -} - -export const contract = { - agents, -} diff --git a/packages/contracts/generated/api/console/agents/types.gen.ts b/packages/contracts/generated/api/console/agents/types.gen.ts deleted file mode 100644 index eab4cbea18..0000000000 --- a/packages/contracts/generated/api/console/agents/types.gen.ts +++ /dev/null @@ -1,587 +0,0 @@ -// This file is auto-generated by @hey-api/openapi-ts - -export type ClientOptions = { - baseUrl: `${string}://${string}/console/api` | (string & {}) -} - -export type AgentRosterListResponse = { - data: Array - has_more: boolean - limit: number - page: number - total: number -} - -export type AgentInviteOptionsResponse = { - data: Array - has_more: boolean - limit: number - page: number - total: number -} - -export type AgentRosterResponse = { - active_config_snapshot?: AgentConfigSnapshotSummaryResponse | null - active_config_snapshot_id?: string | null - agent_kind: AgentKind - app_id?: string | null - archived_at?: number | null - archived_by?: string | null - created_at?: number | null - created_by?: string | null - description: string - icon?: string | null - icon_background?: string | null - icon_type?: AgentIconType | null - id: string - name: string - published_node_reference_count?: number - published_reference_count?: number - published_references?: Array - role?: string - scope: AgentScope - source: AgentSource - status: AgentStatus - updated_at?: number | null - updated_by?: string | null - workflow_id?: string | null - workflow_node_id?: string | null -} - -export type AgentConfigSnapshotListResponse = { - data: Array -} - -export type AgentConfigSnapshotDetailResponse = { - agent_id?: string | null - config_snapshot: AgentSoulConfig - created_at?: number | null - created_by?: string | null - id: string - revisions?: Array - summary?: string | null - version: number - version_note?: string | null -} - -export type AgentInviteOptionResponse = { - active_config_snapshot?: AgentConfigSnapshotSummaryResponse | null - active_config_snapshot_id?: string | null - agent_kind: AgentKind - app_id?: string | null - archived_at?: number | null - archived_by?: string | null - created_at?: number | null - created_by?: string | null - description: string - existing_node_ids?: Array - icon?: string | null - icon_background?: string | null - icon_type?: AgentIconType | null - id: string - in_current_workflow_count?: number - is_in_current_workflow?: boolean - name: string - published_node_reference_count?: number - published_reference_count?: number - published_references?: Array - role?: string - scope: AgentScope - source: AgentSource - status: AgentStatus - updated_at?: number | null - updated_by?: string | null - workflow_id?: string | null - workflow_node_id?: string | null -} - -export type AgentConfigSnapshotSummaryResponse = { - agent_id?: string | null - created_at?: number | null - created_by?: string | null - id: string - summary?: string | null - version: number - version_note?: string | null -} - -export type AgentKind = 'dify_agent' - -export type AgentIconType = 'emoji' | 'image' | 'link' - -export type AgentPublishedReferenceResponse = { - app_id: string - app_mode: string - app_name: string - node_ids?: Array - workflow_id: string - workflow_version: string -} - -export type AgentScope = 'roster' | 'workflow_only' - -export type AgentSource = 'agent_app' | 'imported' | 'roster' | 'system' | 'workflow' - -export type AgentStatus = 'active' | 'archived' - -export type AgentSoulConfig = { - app_features?: AgentSoulAppFeaturesConfig - app_variables?: Array - env?: AgentSoulEnvConfig - human?: AgentSoulHumanConfig - knowledge?: AgentSoulKnowledgeConfig - memory?: AgentSoulMemoryConfig - misc_legacy?: AgentSoulAppFeaturesConfig - model?: AgentSoulModelConfig | null - prompt?: AgentSoulPromptConfig - sandbox?: AgentSoulSandboxConfig - schema_version?: number - skills_files?: AgentSoulSkillsFilesConfig - tools?: AgentSoulToolsConfig -} - -export type AgentConfigRevisionResponse = { - created_at?: number | null - created_by?: string | null - current_snapshot_id: string - id: string - operation: AgentConfigRevisionOperation - previous_snapshot_id?: string | null - revision: number - summary?: string | null - version_note?: string | null -} - -export type AgentSoulAppFeaturesConfig = { - opening_statement?: string | null - retriever_resource?: AgentFeatureToggleConfig | null - sensitive_word_avoidance?: AgentSensitiveWordAvoidanceFeatureConfig | null - speech_to_text?: AgentFeatureToggleConfig | null - suggested_questions?: Array | null - suggested_questions_after_answer?: AgentSuggestedQuestionsAfterAnswerFeatureConfig | null - text_to_speech?: AgentTextToSpeechFeatureConfig | null - [key: string]: unknown -} - -export type AppVariableConfig = { - default?: unknown - name: string - required?: boolean - type: string -} - -export type AgentSoulEnvConfig = { - secret_refs?: Array - variables?: Array -} - -export type AgentSoulHumanConfig = { - contacts?: Array - tools?: Array -} - -export type AgentSoulKnowledgeConfig = { - datasets?: Array - query_config?: AgentKnowledgeQueryConfig - query_mode?: AgentKnowledgeQueryMode | null -} - -export type AgentSoulMemoryConfig = { - artifacts?: Array - budget?: string | null - scope?: string | null -} - -export type AgentSoulModelConfig = { - credential_ref?: AgentSoulModelCredentialRef | null - model: string - model_provider: string - model_settings?: AgentSoulModelSettings - plugin_id: string -} - -export type AgentSoulPromptConfig = { - system_prompt?: string -} - -export type AgentSoulSandboxConfig = { - config?: AgentSandboxProviderConfig - provider?: string | null -} - -export type AgentSoulSkillsFilesConfig = { - files?: Array - skills?: Array -} - -export type AgentSoulToolsConfig = { - cli_tools?: Array - dify_tools?: Array -} - -export type AgentConfigRevisionOperation - = | 'create_version' - | 'save_current_version' - | 'save_new_agent' - | 'save_new_version' - | 'save_to_roster' - -export type AgentFeatureToggleConfig = { - enabled?: boolean - [key: string]: unknown -} - -export type AgentSensitiveWordAvoidanceFeatureConfig = { - config?: AgentModerationProviderConfig | null - enabled?: boolean - type?: string | null - [key: string]: unknown -} - -export type AgentSuggestedQuestionsAfterAnswerFeatureConfig = { - enabled?: boolean - model?: AgentSoulModelConfig | null - prompt?: string | null - [key: string]: unknown -} - -export type AgentTextToSpeechFeatureConfig = { - autoPlay?: string | null - enabled?: boolean - language?: string | null - voice?: string | null - [key: string]: unknown -} - -export type AgentSecretRefConfig = { - credential_id?: string | null - env_name?: string | null - id?: string | null - key?: string | null - name?: string | null - permission?: AgentPermissionConfig | null - permission_status?: string | null - provider?: string | null - provider_credential_id?: string | null - ref?: string | null - type?: string | null - variable?: string | null - [key: string]: unknown -} - -export type AgentEnvVariableConfig = { - default?: - | string - | number - | number - | boolean - | Array - | Array - | Array - | Array - | null - env_name?: string | null - key?: string | null - name?: string | null - required?: boolean - type?: string | null - value?: - | string - | number - | number - | boolean - | Array - | Array - | Array - | Array - | null - variable?: string | null - [key: string]: unknown -} - -export type AgentHumanContactConfig = { - channel?: string | null - contact_id?: string | null - contact_method?: string | null - email?: string | null - human_id?: string | null - id?: string | null - method?: string | null - name?: string | null - tenant_id?: string | null - [key: string]: unknown -} - -export type AgentHumanToolConfig = { - description?: string | null - enabled?: boolean - name?: string | null - [key: string]: unknown -} - -export type AgentKnowledgeDatasetConfig = { - description?: string | null - id?: string | null - name?: string | null - [key: string]: unknown -} - -export type AgentKnowledgeQueryConfig = { - query?: string | null - score_threshold?: number | null - score_threshold_enabled?: boolean | null - top_k?: number | null - [key: string]: unknown -} - -export type AgentKnowledgeQueryMode = 'generated_query' | 'user_query' - -export type AgentMemoryArtifactConfig = { - id?: string | null - name?: string | null - type?: string | null - url?: string | null - [key: string]: unknown -} - -export type AgentSoulModelCredentialRef = { - id?: string | null - provider?: string | null - type: string -} - -export type AgentSoulModelSettings = { - frequency_penalty?: number | null - max_tokens?: number | null - presence_penalty?: number | null - response_format?: AgentModelResponseFormatConfig | null - stop?: Array | null - temperature?: number | null - top_p?: number | null -} - -export type AgentSandboxProviderConfig = { - cpu?: number | null - env?: Array - image?: string | null - working_dir?: string | null - [key: string]: unknown -} - -export type AgentFileRefConfig = { - drive_key?: string | null - file_id?: string | null - id?: string | null - name?: string | null - reference?: string | null - remote_url?: string | null - tenant_id?: string | null - transfer_method?: string | null - type?: string | null - upload_file_id?: string | null - url?: string | null - [key: string]: unknown -} - -export type AgentSkillRefConfig = { - description?: string | null - file_id?: string | null - full_archive_file_id?: string | null - full_archive_key?: string | null - id?: string | null - manifest_files?: Array | null - name?: string | null - path?: string | null - skill_md_file_id?: string | null - skill_md_key?: string | null - [key: string]: unknown -} - -export type AgentCliToolConfig = { - approved?: boolean - authorization_status?: AgentCliToolAuthorizationStatus | null - command?: string | null - dangerous?: boolean - dangerous_accepted?: boolean - dangerous_acknowledged?: boolean - dangerous_command?: boolean - description?: string | null - enabled?: boolean - env?: AgentCliToolEnvConfig - id?: string | null - inferred_from?: string | null - install?: string | null - install_command?: string | null - install_commands?: Array - invoke_metadata?: { - [key: string]: unknown - } - label?: string | null - name?: string | null - permission?: AgentPermissionConfig | null - pre_authorized?: boolean | null - requires_confirmation?: boolean - risk_accepted?: boolean - risk_level?: AgentCliToolRiskLevel | null - setup_command?: string | null - tool_name?: string | null - [key: string]: unknown -} - -export type AgentSoulDifyToolConfig = { - credential_ref?: AgentSoulDifyToolCredentialRef | null - credential_type?: 'api-key' | 'oauth2' | 'unauthorized' - description?: string | null - enabled?: boolean - name?: string | null - plugin_id?: string | null - provider?: string | null - provider_id?: string | null - provider_type?: string - runtime_parameters?: { - [key: string]: - | string - | number - | number - | boolean - | Array - | Array - | Array - | Array - | null - } - tool_name?: string | null -} - -export type AgentModerationProviderConfig = { - api_based_extension_id?: string | null - inputs_config?: AgentModerationIoConfig | null - keywords?: string | null - outputs_config?: AgentModerationIoConfig | null - [key: string]: unknown -} - -export type AgentPermissionConfig = { - allowed?: boolean | null - state?: string | null - status?: string | null -} - -export type AgentModelResponseFormatConfig = { - type?: string | null - [key: string]: unknown -} - -export type AgentCliToolAuthorizationStatus - = | 'allowed' - | 'authorized' - | 'denied' - | 'forbidden' - | 'not_required' - | 'pending' - | 'pre_authorized' - | 'unauthorized' - -export type AgentCliToolEnvConfig = { - secret_refs?: Array - variables?: Array -} - -export type AgentCliToolRiskLevel = 'dangerous' | 'safe' | 'unknown' - -export type AgentSoulDifyToolCredentialRef = { - id?: string | null - provider?: string | null - type?: 'provider' | 'tool' -} - -export type AgentModerationIoConfig = { - enabled?: boolean - preset_response?: string | null - [key: string]: unknown -} - -export type GetAgentsData = { - body?: never - path?: never - query?: { - keyword?: string - limit?: number - page?: number - } - url: '/agents' -} - -export type GetAgentsResponses = { - 200: AgentRosterListResponse -} - -export type GetAgentsResponse = GetAgentsResponses[keyof GetAgentsResponses] - -export type GetAgentsInviteOptionsData = { - body?: never - path?: never - query?: { - app_id?: string - keyword?: string - limit?: number - page?: number - } - url: '/agents/invite-options' -} - -export type GetAgentsInviteOptionsResponses = { - 200: AgentInviteOptionsResponse -} - -export type GetAgentsInviteOptionsResponse - = GetAgentsInviteOptionsResponses[keyof GetAgentsInviteOptionsResponses] - -export type GetAgentsByAgentIdData = { - body?: never - path: { - agent_id: string - } - query?: never - url: '/agents/{agent_id}' -} - -export type GetAgentsByAgentIdResponses = { - 200: AgentRosterResponse -} - -export type GetAgentsByAgentIdResponse - = GetAgentsByAgentIdResponses[keyof GetAgentsByAgentIdResponses] - -export type GetAgentsByAgentIdVersionsData = { - body?: never - path: { - agent_id: string - } - query?: never - url: '/agents/{agent_id}/versions' -} - -export type GetAgentsByAgentIdVersionsResponses = { - 200: AgentConfigSnapshotListResponse -} - -export type GetAgentsByAgentIdVersionsResponse - = GetAgentsByAgentIdVersionsResponses[keyof GetAgentsByAgentIdVersionsResponses] - -export type GetAgentsByAgentIdVersionsByVersionIdData = { - body?: never - path: { - agent_id: string - version_id: string - } - query?: never - url: '/agents/{agent_id}/versions/{version_id}' -} - -export type GetAgentsByAgentIdVersionsByVersionIdResponses = { - 200: AgentConfigSnapshotDetailResponse -} - -export type GetAgentsByAgentIdVersionsByVersionIdResponse - = GetAgentsByAgentIdVersionsByVersionIdResponses[keyof GetAgentsByAgentIdVersionsByVersionIdResponses] diff --git a/packages/contracts/generated/api/console/agents/zod.gen.ts b/packages/contracts/generated/api/console/agents/zod.gen.ts deleted file mode 100644 index cee741afdb..0000000000 --- a/packages/contracts/generated/api/console/agents/zod.gen.ts +++ /dev/null @@ -1,743 +0,0 @@ -// This file is auto-generated by @hey-api/openapi-ts - -import * as z from 'zod' - -/** - * AgentConfigSnapshotSummaryResponse - */ -export const zAgentConfigSnapshotSummaryResponse = z.object({ - agent_id: z.string().nullish(), - created_at: z.int().nullish(), - created_by: z.string().nullish(), - id: z.string(), - summary: z.string().nullish(), - version: z.int(), - version_note: z.string().nullish(), -}) - -/** - * AgentConfigSnapshotListResponse - */ -export const zAgentConfigSnapshotListResponse = z.object({ - data: z.array(zAgentConfigSnapshotSummaryResponse), -}) - -/** - * AgentKind - * - * Agent implementation family. - * - * This leaves room for future non-Dify agent implementations while keeping - * the current roster/workflow APIs scoped to Dify Agent. - */ -export const zAgentKind = z.enum(['dify_agent']) - -/** - * AgentIconType - * - * Supported icon storage formats for Agent roster entries. - */ -export const zAgentIconType = z.enum(['emoji', 'image', 'link']) - -/** - * AgentPublishedReferenceResponse - */ -export const zAgentPublishedReferenceResponse = z.object({ - app_id: z.string(), - app_mode: z.string(), - app_name: z.string(), - node_ids: z.array(z.string()).optional(), - workflow_id: z.string(), - workflow_version: z.string(), -}) - -/** - * AgentScope - * - * Visibility and lifecycle scope of an Agent record. - */ -export const zAgentScope = z.enum(['roster', 'workflow_only']) - -/** - * AgentSource - * - * Origin that created or imported the Agent. - */ -export const zAgentSource = z.enum(['agent_app', 'imported', 'roster', 'system', 'workflow']) - -/** - * AgentStatus - * - * Soft lifecycle state for Agent records. - */ -export const zAgentStatus = z.enum(['active', 'archived']) - -/** - * AgentRosterResponse - */ -export const zAgentRosterResponse = z.object({ - active_config_snapshot: zAgentConfigSnapshotSummaryResponse.nullish(), - active_config_snapshot_id: z.string().nullish(), - agent_kind: zAgentKind, - app_id: z.string().nullish(), - archived_at: z.int().nullish(), - archived_by: z.string().nullish(), - created_at: z.int().nullish(), - created_by: z.string().nullish(), - description: z.string(), - icon: z.string().nullish(), - icon_background: z.string().nullish(), - icon_type: zAgentIconType.nullish(), - id: z.string(), - name: z.string(), - published_node_reference_count: z.int().optional().default(0), - published_reference_count: z.int().optional().default(0), - published_references: z.array(zAgentPublishedReferenceResponse).optional(), - role: z.string().optional().default(''), - scope: zAgentScope, - source: zAgentSource, - status: zAgentStatus, - updated_at: z.int().nullish(), - updated_by: z.string().nullish(), - workflow_id: z.string().nullish(), - workflow_node_id: z.string().nullish(), -}) - -/** - * AgentRosterListResponse - */ -export const zAgentRosterListResponse = z.object({ - data: z.array(zAgentRosterResponse), - has_more: z.boolean(), - limit: z.int(), - page: z.int(), - total: z.int(), -}) - -/** - * AgentInviteOptionResponse - */ -export const zAgentInviteOptionResponse = z.object({ - active_config_snapshot: zAgentConfigSnapshotSummaryResponse.nullish(), - active_config_snapshot_id: z.string().nullish(), - agent_kind: zAgentKind, - app_id: z.string().nullish(), - archived_at: z.int().nullish(), - archived_by: z.string().nullish(), - created_at: z.int().nullish(), - created_by: z.string().nullish(), - description: z.string(), - existing_node_ids: z.array(z.string()).optional(), - icon: z.string().nullish(), - icon_background: z.string().nullish(), - icon_type: zAgentIconType.nullish(), - id: z.string(), - in_current_workflow_count: z.int().optional().default(0), - is_in_current_workflow: z.boolean().optional().default(false), - name: z.string(), - published_node_reference_count: z.int().optional().default(0), - published_reference_count: z.int().optional().default(0), - published_references: z.array(zAgentPublishedReferenceResponse).optional(), - role: z.string().optional().default(''), - scope: zAgentScope, - source: zAgentSource, - status: zAgentStatus, - updated_at: z.int().nullish(), - updated_by: z.string().nullish(), - workflow_id: z.string().nullish(), - workflow_node_id: z.string().nullish(), -}) - -/** - * AgentInviteOptionsResponse - */ -export const zAgentInviteOptionsResponse = z.object({ - data: z.array(zAgentInviteOptionResponse), - has_more: z.boolean(), - limit: z.int(), - page: z.int(), - total: z.int(), -}) - -/** - * AppVariableConfig - */ -export const zAppVariableConfig = z.object({ - default: z.unknown().optional(), - name: z.string().min(1).max(255), - required: z.boolean().optional().default(false), - type: z.string().min(1).max(64), -}) - -/** - * AgentSoulPromptConfig - */ -export const zAgentSoulPromptConfig = z.object({ - system_prompt: z.string().optional().default(''), -}) - -/** - * AgentConfigRevisionOperation - * - * Audit operation recorded for Agent Soul version/revision changes. - */ -export const zAgentConfigRevisionOperation = z.enum([ - 'create_version', - 'save_current_version', - 'save_new_agent', - 'save_new_version', - 'save_to_roster', -]) - -/** - * AgentConfigRevisionResponse - */ -export const zAgentConfigRevisionResponse = z.object({ - created_at: z.int().nullish(), - created_by: z.string().nullish(), - current_snapshot_id: z.string(), - id: z.string(), - operation: zAgentConfigRevisionOperation, - previous_snapshot_id: z.string().nullish(), - revision: z.int(), - summary: z.string().nullish(), - version_note: z.string().nullish(), -}) - -/** - * AgentFeatureToggleConfig - */ -export const zAgentFeatureToggleConfig = z.object({ - enabled: z.boolean().optional().default(false), -}) - -/** - * AgentTextToSpeechFeatureConfig - */ -export const zAgentTextToSpeechFeatureConfig = z.object({ - autoPlay: z.string().nullish(), - enabled: z.boolean().optional().default(false), - language: z.string().nullish(), - voice: z.string().nullish(), -}) - -/** - * AgentEnvVariableConfig - */ -export const zAgentEnvVariableConfig = z.object({ - default: z - .union([ - z.string(), - z.int(), - z.number(), - z.boolean(), - z.array(z.string()), - z.array(z.int()), - z.array(z.number()), - z.array(z.boolean()), - ]) - .nullish(), - env_name: z.string().max(255).nullish(), - key: z.string().max(255).nullish(), - name: z.string().max(255).nullish(), - required: z.boolean().optional().default(false), - type: z.string().max(64).nullish(), - value: z - .union([ - z.string(), - z.int(), - z.number(), - z.boolean(), - z.array(z.string()), - z.array(z.int()), - z.array(z.number()), - z.array(z.boolean()), - ]) - .nullish(), - variable: z.string().max(255).nullish(), -}) - -/** - * AgentHumanContactConfig - */ -export const zAgentHumanContactConfig = z.object({ - channel: z.string().max(64).nullish(), - contact_id: z.string().max(255).nullish(), - contact_method: z.string().max(64).nullish(), - email: z.string().max(255).nullish(), - human_id: z.string().max(255).nullish(), - id: z.string().max(255).nullish(), - method: z.string().max(64).nullish(), - name: z.string().max(255).nullish(), - tenant_id: z.string().max(255).nullish(), -}) - -/** - * AgentHumanToolConfig - */ -export const zAgentHumanToolConfig = z.object({ - description: z.string().nullish(), - enabled: z.boolean().optional().default(true), - name: z.string().max(255).nullish(), -}) - -/** - * AgentSoulHumanConfig - */ -export const zAgentSoulHumanConfig = z.object({ - contacts: z.array(zAgentHumanContactConfig).optional(), - tools: z.array(zAgentHumanToolConfig).optional(), -}) - -/** - * AgentKnowledgeDatasetConfig - */ -export const zAgentKnowledgeDatasetConfig = z.object({ - description: z.string().nullish(), - id: z.string().max(255).nullish(), - name: z.string().max(255).nullish(), -}) - -/** - * AgentKnowledgeQueryConfig - */ -export const zAgentKnowledgeQueryConfig = z.object({ - query: z.string().nullish(), - score_threshold: z.number().gte(0).lte(1).nullish(), - score_threshold_enabled: z.boolean().nullish(), - top_k: z.int().gte(1).nullish(), -}) - -/** - * AgentKnowledgeQueryMode - */ -export const zAgentKnowledgeQueryMode = z.enum(['generated_query', 'user_query']) - -/** - * AgentSoulKnowledgeConfig - */ -export const zAgentSoulKnowledgeConfig = z.object({ - datasets: z.array(zAgentKnowledgeDatasetConfig).optional(), - query_config: zAgentKnowledgeQueryConfig.optional(), - query_mode: zAgentKnowledgeQueryMode.nullish(), -}) - -/** - * AgentMemoryArtifactConfig - */ -export const zAgentMemoryArtifactConfig = z.object({ - id: z.string().max(255).nullish(), - name: z.string().max(255).nullish(), - type: z.string().max(64).nullish(), - url: z.string().nullish(), -}) - -/** - * AgentSoulMemoryConfig - */ -export const zAgentSoulMemoryConfig = z.object({ - artifacts: z.array(zAgentMemoryArtifactConfig).optional(), - budget: z.string().nullish(), - scope: z.string().nullish(), -}) - -/** - * AgentSoulModelCredentialRef - * - * Reference to model credentials resolved only at runtime. - */ -export const zAgentSoulModelCredentialRef = z.object({ - id: z.string().max(255).nullish(), - provider: z.string().max(255).nullish(), - type: z.string().min(1).max(64), -}) - -/** - * AgentSandboxProviderConfig - */ -export const zAgentSandboxProviderConfig = z.object({ - cpu: z.int().gte(1).nullish(), - env: z.array(zAgentEnvVariableConfig).optional(), - image: z.string().nullish(), - working_dir: z.string().nullish(), -}) - -/** - * AgentSoulSandboxConfig - */ -export const zAgentSoulSandboxConfig = z.object({ - config: zAgentSandboxProviderConfig.optional(), - provider: z.string().nullish(), -}) - -/** - * AgentFileRefConfig - */ -export const zAgentFileRefConfig = z.object({ - drive_key: z.string().max(512).nullish(), - file_id: z.string().max(255).nullish(), - id: z.string().max(255).nullish(), - name: z.string().max(255).nullish(), - reference: z.string().max(255).nullish(), - remote_url: z.string().nullish(), - tenant_id: z.string().max(255).nullish(), - transfer_method: z.string().max(64).nullish(), - type: z.string().max(64).nullish(), - upload_file_id: z.string().max(255).nullish(), - url: z.string().nullish(), -}) - -/** - * AgentSkillRefConfig - */ -export const zAgentSkillRefConfig = z.object({ - description: z.string().nullish(), - file_id: z.string().max(255).nullish(), - full_archive_file_id: z.string().max(255).nullish(), - full_archive_key: z.string().max(512).nullish(), - id: z.string().max(255).nullish(), - manifest_files: z.array(z.string()).nullish(), - name: z.string().max(255).nullish(), - path: z.string().nullish(), - skill_md_file_id: z.string().max(255).nullish(), - skill_md_key: z.string().max(512).nullish(), -}) - -/** - * AgentSoulSkillsFilesConfig - */ -export const zAgentSoulSkillsFilesConfig = z.object({ - files: z.array(zAgentFileRefConfig).optional(), - skills: z.array(zAgentSkillRefConfig).optional(), -}) - -/** - * AgentPermissionConfig - */ -export const zAgentPermissionConfig = z.object({ - allowed: z.boolean().nullish(), - state: z.string().max(64).nullish(), - status: z.string().max(64).nullish(), -}) - -/** - * AgentSecretRefConfig - */ -export const zAgentSecretRefConfig = z.object({ - credential_id: z.string().max(255).nullish(), - env_name: z.string().max(255).nullish(), - id: z.string().max(255).nullish(), - key: z.string().max(255).nullish(), - name: z.string().max(255).nullish(), - permission: zAgentPermissionConfig.nullish(), - permission_status: z.string().max(64).nullish(), - provider: z.string().max(255).nullish(), - provider_credential_id: z.string().max(255).nullish(), - ref: z.string().max(255).nullish(), - type: z.string().max(64).nullish(), - variable: z.string().max(255).nullish(), -}) - -/** - * AgentSoulEnvConfig - */ -export const zAgentSoulEnvConfig = z.object({ - secret_refs: z.array(zAgentSecretRefConfig).optional(), - variables: z.array(zAgentEnvVariableConfig).optional(), -}) - -/** - * AgentModelResponseFormatConfig - */ -export const zAgentModelResponseFormatConfig = z.object({ - type: z.string().max(64).nullish(), -}) - -/** - * AgentSoulModelSettings - */ -export const zAgentSoulModelSettings = z.object({ - frequency_penalty: z.number().nullish(), - max_tokens: z.int().nullish(), - presence_penalty: z.number().nullish(), - response_format: zAgentModelResponseFormatConfig.nullish(), - stop: z.array(z.string()).nullish(), - temperature: z.number().nullish(), - top_p: z.number().nullish(), -}) - -/** - * AgentSoulModelConfig - * - * Stable model selection for Agent runtime without storing secret values. - */ -export const zAgentSoulModelConfig = z.object({ - credential_ref: zAgentSoulModelCredentialRef.nullish(), - model: z.string().min(1).max(255), - model_provider: z.string().min(1).max(255), - model_settings: zAgentSoulModelSettings.optional(), - plugin_id: z.string().min(1).max(255), -}) - -/** - * AgentSuggestedQuestionsAfterAnswerFeatureConfig - */ -export const zAgentSuggestedQuestionsAfterAnswerFeatureConfig = z.object({ - enabled: z.boolean().optional().default(false), - model: zAgentSoulModelConfig.nullish(), - prompt: z.string().nullish(), -}) - -/** - * AgentCliToolAuthorizationStatus - * - * Authorization state for Agent-scoped CLI tools. - * - * Missing status keeps backward compatibility with draft rows and CLI tools that - * do not need pre-authorization. Explicit denied-like states are blocked by the - * composer/publish validators and skipped by runtime request builders. - */ -export const zAgentCliToolAuthorizationStatus = z.enum([ - 'allowed', - 'authorized', - 'denied', - 'forbidden', - 'not_required', - 'pending', - 'pre_authorized', - 'unauthorized', -]) - -/** - * AgentCliToolEnvConfig - */ -export const zAgentCliToolEnvConfig = z.object({ - secret_refs: z.array(zAgentSecretRefConfig).optional(), - variables: z.array(zAgentEnvVariableConfig).optional(), -}) - -/** - * AgentCliToolRiskLevel - * - * Risk marker for CLI tool bootstrap commands. - */ -export const zAgentCliToolRiskLevel = z.enum(['dangerous', 'safe', 'unknown']) - -/** - * AgentCliToolConfig - */ -export const zAgentCliToolConfig = z.object({ - approved: z.boolean().optional().default(false), - authorization_status: zAgentCliToolAuthorizationStatus.nullish(), - command: z.string().nullish(), - dangerous: z.boolean().optional().default(false), - dangerous_accepted: z.boolean().optional().default(false), - dangerous_acknowledged: z.boolean().optional().default(false), - dangerous_command: z.boolean().optional().default(false), - description: z.string().nullish(), - enabled: z.boolean().optional().default(true), - env: zAgentCliToolEnvConfig.optional(), - id: z.string().max(255).nullish(), - inferred_from: z.string().max(255).nullish(), - install: z.string().nullish(), - install_command: z.string().nullish(), - install_commands: z.array(z.string()).optional(), - invoke_metadata: z.record(z.string(), z.unknown()).optional(), - label: z.string().max(255).nullish(), - name: z.string().max(255).nullish(), - permission: zAgentPermissionConfig.nullish(), - pre_authorized: z.boolean().nullish(), - requires_confirmation: z.boolean().optional().default(false), - risk_accepted: z.boolean().optional().default(false), - risk_level: zAgentCliToolRiskLevel.nullish(), - setup_command: z.string().nullish(), - tool_name: z.string().max(255).nullish(), -}) - -/** - * AgentSoulDifyToolCredentialRef - * - * Reference to a stored Dify Plugin Tool credential. - * - * Secret values are resolved only at runtime. The legacy ``credential_id`` - * field is accepted by :class:`AgentSoulDifyToolConfig` and normalized here so - * old Agent tool payloads can be read while new payloads stay explicit. - */ -export const zAgentSoulDifyToolCredentialRef = z.object({ - id: z.string().max(255).nullish(), - provider: z.string().max(255).nullish(), - type: z.enum(['provider', 'tool']).optional().default('tool'), -}) - -/** - * AgentSoulDifyToolConfig - * - * One Dify Plugin Tool configured on Agent Soul. - * - * The API backend prepares this persisted product shape into - * ``DifyPluginToolConfig`` before sending a run request to Agent backend. - * ``provider_id`` keeps compatibility with existing Agent tool config payloads; - * new callers should send ``plugin_id`` + ``provider`` when available. - */ -export const zAgentSoulDifyToolConfig = z.object({ - credential_ref: zAgentSoulDifyToolCredentialRef.nullish(), - credential_type: z.enum(['api-key', 'oauth2', 'unauthorized']).optional().default('api-key'), - description: z.string().nullish(), - enabled: z.boolean().optional().default(true), - name: z.string().max(255).nullish(), - plugin_id: z.string().max(255).nullish(), - provider: z.string().max(255).nullish(), - provider_id: z.string().max(255).nullish(), - provider_type: z.string().optional().default('plugin'), - runtime_parameters: z - .record( - z.string(), - z - .union([ - z.string(), - z.int(), - z.number(), - z.boolean(), - z.array(z.string()), - z.array(z.int()), - z.array(z.number()), - z.array(z.boolean()), - ]) - .nullable(), - ) - .optional(), - tool_name: z.string().min(1).max(255).nullish(), -}) - -/** - * AgentSoulToolsConfig - */ -export const zAgentSoulToolsConfig = z.object({ - cli_tools: z.array(zAgentCliToolConfig).optional(), - dify_tools: z.array(zAgentSoulDifyToolConfig).optional(), -}) - -/** - * AgentModerationIOConfig - */ -export const zAgentModerationIoConfig = z.object({ - enabled: z.boolean().optional().default(false), - preset_response: z.string().nullish(), -}) - -/** - * AgentModerationProviderConfig - */ -export const zAgentModerationProviderConfig = z.object({ - api_based_extension_id: z.string().nullish(), - inputs_config: zAgentModerationIoConfig.nullish(), - keywords: z.string().nullish(), - outputs_config: zAgentModerationIoConfig.nullish(), -}) - -/** - * AgentSensitiveWordAvoidanceFeatureConfig - */ -export const zAgentSensitiveWordAvoidanceFeatureConfig = z.object({ - config: zAgentModerationProviderConfig.nullish(), - enabled: z.boolean().optional().default(false), - type: z.string().nullish(), -}) - -/** - * AgentSoulAppFeaturesConfig - */ -export const zAgentSoulAppFeaturesConfig = z.object({ - opening_statement: z.string().nullish(), - retriever_resource: zAgentFeatureToggleConfig.nullish(), - sensitive_word_avoidance: zAgentSensitiveWordAvoidanceFeatureConfig.nullish(), - speech_to_text: zAgentFeatureToggleConfig.nullish(), - suggested_questions: z.array(z.string()).nullish(), - suggested_questions_after_answer: zAgentSuggestedQuestionsAfterAnswerFeatureConfig.nullish(), - text_to_speech: zAgentTextToSpeechFeatureConfig.nullish(), -}) - -/** - * AgentSoulConfig - */ -export const zAgentSoulConfig = z.object({ - app_features: zAgentSoulAppFeaturesConfig.optional(), - app_variables: z.array(zAppVariableConfig).optional(), - env: zAgentSoulEnvConfig.optional(), - human: zAgentSoulHumanConfig.optional(), - knowledge: zAgentSoulKnowledgeConfig.optional(), - memory: zAgentSoulMemoryConfig.optional(), - misc_legacy: zAgentSoulAppFeaturesConfig.optional(), - model: zAgentSoulModelConfig.nullish(), - prompt: zAgentSoulPromptConfig.optional(), - sandbox: zAgentSoulSandboxConfig.optional(), - schema_version: z.int().optional().default(1), - skills_files: zAgentSoulSkillsFilesConfig.optional(), - tools: zAgentSoulToolsConfig.optional(), -}) - -/** - * AgentConfigSnapshotDetailResponse - */ -export const zAgentConfigSnapshotDetailResponse = z.object({ - agent_id: z.string().nullish(), - config_snapshot: zAgentSoulConfig, - created_at: z.int().nullish(), - created_by: z.string().nullish(), - id: z.string(), - revisions: z.array(zAgentConfigRevisionResponse).optional(), - summary: z.string().nullish(), - version: z.int(), - version_note: z.string().nullish(), -}) - -export const zGetAgentsQuery = z.object({ - keyword: z.string().optional(), - limit: z.int().gte(1).lte(100).optional().default(20), - page: z.int().gte(1).optional().default(1), -}) - -/** - * Agent roster list - */ -export const zGetAgentsResponse = zAgentRosterListResponse - -export const zGetAgentsInviteOptionsQuery = z.object({ - app_id: z.string().optional(), - keyword: z.string().optional(), - limit: z.int().gte(1).lte(100).optional().default(20), - page: z.int().gte(1).optional().default(1), -}) - -/** - * Agent invite options - */ -export const zGetAgentsInviteOptionsResponse = zAgentInviteOptionsResponse - -export const zGetAgentsByAgentIdPath = z.object({ - agent_id: z.string(), -}) - -/** - * Agent detail - */ -export const zGetAgentsByAgentIdResponse = zAgentRosterResponse - -export const zGetAgentsByAgentIdVersionsPath = z.object({ - agent_id: z.string(), -}) - -/** - * Agent versions - */ -export const zGetAgentsByAgentIdVersionsResponse = zAgentConfigSnapshotListResponse - -export const zGetAgentsByAgentIdVersionsByVersionIdPath = z.object({ - agent_id: z.string(), - version_id: z.string(), -}) - -/** - * Agent version detail - */ -export const zGetAgentsByAgentIdVersionsByVersionIdResponse = zAgentConfigSnapshotDetailResponse diff --git a/packages/contracts/generated/api/console/apps/orpc.gen.ts b/packages/contracts/generated/api/console/apps/orpc.gen.ts index bd97b260ee..3952812a5a 100644 --- a/packages/contracts/generated/api/console/apps/orpc.gen.ts +++ b/packages/contracts/generated/api/console/apps/orpc.gen.ts @@ -45,10 +45,6 @@ import { zGetAppsByAppIdAdvancedChatWorkflowRunsPath, zGetAppsByAppIdAdvancedChatWorkflowRunsQuery, zGetAppsByAppIdAdvancedChatWorkflowRunsResponse, - zGetAppsByAppIdAgentComposerCandidatesPath, - zGetAppsByAppIdAgentComposerCandidatesResponse, - zGetAppsByAppIdAgentComposerPath, - zGetAppsByAppIdAgentComposerResponse, zGetAppsByAppIdAgentDriveFilesDownloadPath, zGetAppsByAppIdAgentDriveFilesDownloadQuery, zGetAppsByAppIdAgentDriveFilesDownloadResponse, @@ -61,14 +57,6 @@ import { zGetAppsByAppIdAgentLogsPath, zGetAppsByAppIdAgentLogsQuery, zGetAppsByAppIdAgentLogsResponse, - zGetAppsByAppIdAgentReferencingWorkflowsPath, - zGetAppsByAppIdAgentReferencingWorkflowsResponse, - zGetAppsByAppIdAgentSandboxFilesPath, - zGetAppsByAppIdAgentSandboxFilesQuery, - zGetAppsByAppIdAgentSandboxFilesReadPath, - zGetAppsByAppIdAgentSandboxFilesReadQuery, - zGetAppsByAppIdAgentSandboxFilesReadResponse, - zGetAppsByAppIdAgentSandboxFilesResponse, zGetAppsByAppIdAnnotationReplyByActionStatusByJobIdPath, zGetAppsByAppIdAnnotationReplyByActionStatusByJobIdResponse, zGetAppsByAppIdAnnotationsBatchImportStatusByJobIdPath, @@ -276,19 +264,10 @@ import { zPostAppsByAppIdAdvancedChatWorkflowsDraftRunBody, zPostAppsByAppIdAdvancedChatWorkflowsDraftRunPath, zPostAppsByAppIdAdvancedChatWorkflowsDraftRunResponse, - zPostAppsByAppIdAgentComposerValidateBody, - zPostAppsByAppIdAgentComposerValidatePath, - zPostAppsByAppIdAgentComposerValidateResponse, - zPostAppsByAppIdAgentFeaturesBody, - zPostAppsByAppIdAgentFeaturesPath, - zPostAppsByAppIdAgentFeaturesResponse, zPostAppsByAppIdAgentFilesBody, zPostAppsByAppIdAgentFilesPath, zPostAppsByAppIdAgentFilesQuery, zPostAppsByAppIdAgentFilesResponse, - zPostAppsByAppIdAgentSandboxFilesUploadBody, - zPostAppsByAppIdAgentSandboxFilesUploadPath, - zPostAppsByAppIdAgentSandboxFilesUploadResponse, zPostAppsByAppIdAgentSkillsBySlugInferToolsPath, zPostAppsByAppIdAgentSkillsBySlugInferToolsQuery, zPostAppsByAppIdAgentSkillsBySlugInferToolsResponse, @@ -445,9 +424,6 @@ import { zPostAppsResponse, zPostAppsWorkflowsOnlineUsersBody, zPostAppsWorkflowsOnlineUsersResponse, - zPutAppsByAppIdAgentComposerBody, - zPutAppsByAppIdAgentComposerPath, - zPutAppsByAppIdAgentComposerResponse, zPutAppsByAppIdBody, zPutAppsByAppIdPath, zPutAppsByAppIdResponse, @@ -811,197 +787,10 @@ export const advancedChat = { workflows: workflows2, } -export const get5 = oc - .route({ - inputStructure: 'detailed', - method: 'GET', - operationId: 'getAppsByAppIdAgentComposerCandidates', - path: '/apps/{app_id}/agent-composer/candidates', - tags: ['console'], - }) - .input(z.object({ params: zGetAppsByAppIdAgentComposerCandidatesPath })) - .output(zGetAppsByAppIdAgentComposerCandidatesResponse) - -export const candidates = { - get: get5, -} - -export const post9 = oc - .route({ - inputStructure: 'detailed', - method: 'POST', - operationId: 'postAppsByAppIdAgentComposerValidate', - path: '/apps/{app_id}/agent-composer/validate', - tags: ['console'], - }) - .input( - z.object({ - body: zPostAppsByAppIdAgentComposerValidateBody, - params: zPostAppsByAppIdAgentComposerValidatePath, - }), - ) - .output(zPostAppsByAppIdAgentComposerValidateResponse) - -export const validate = { - post: post9, -} - -export const get6 = oc - .route({ - inputStructure: 'detailed', - method: 'GET', - operationId: 'getAppsByAppIdAgentComposer', - path: '/apps/{app_id}/agent-composer', - tags: ['console'], - }) - .input(z.object({ params: zGetAppsByAppIdAgentComposerPath })) - .output(zGetAppsByAppIdAgentComposerResponse) - -export const put = oc - .route({ - inputStructure: 'detailed', - method: 'PUT', - operationId: 'putAppsByAppIdAgentComposer', - path: '/apps/{app_id}/agent-composer', - tags: ['console'], - }) - .input( - z.object({ body: zPutAppsByAppIdAgentComposerBody, params: zPutAppsByAppIdAgentComposerPath }), - ) - .output(zPutAppsByAppIdAgentComposerResponse) - -export const agentComposer = { - get: get6, - put, - candidates, - validate, -} - -/** - * Update an Agent App's presentation features (opener, follow-up, citations, ...) - */ -export const post10 = oc - .route({ - description: 'Update an Agent App\'s presentation features (opener, follow-up, citations, ...)', - inputStructure: 'detailed', - method: 'POST', - operationId: 'postAppsByAppIdAgentFeatures', - path: '/apps/{app_id}/agent-features', - tags: ['console'], - }) - .input( - z.object({ - body: zPostAppsByAppIdAgentFeaturesBody, - params: zPostAppsByAppIdAgentFeaturesPath, - }), - ) - .output(zPostAppsByAppIdAgentFeaturesResponse) - -export const agentFeatures = { - post: post10, -} - -/** - * List workflow apps that reference this Agent App's bound Agent (read-only) - */ -export const get7 = oc - .route({ - description: 'List workflow apps that reference this Agent App\'s bound Agent (read-only)', - inputStructure: 'detailed', - method: 'GET', - operationId: 'getAppsByAppIdAgentReferencingWorkflows', - path: '/apps/{app_id}/agent-referencing-workflows', - tags: ['console'], - }) - .input(z.object({ params: zGetAppsByAppIdAgentReferencingWorkflowsPath })) - .output(zGetAppsByAppIdAgentReferencingWorkflowsResponse) - -export const agentReferencingWorkflows = { - get: get7, -} - -/** - * Read a text/binary preview file in an Agent App conversation sandbox - */ -export const get8 = oc - .route({ - description: 'Read a text/binary preview file in an Agent App conversation sandbox', - inputStructure: 'detailed', - method: 'GET', - operationId: 'getAppsByAppIdAgentSandboxFilesRead', - path: '/apps/{app_id}/agent-sandbox/files/read', - tags: ['console'], - }) - .input( - z.object({ - params: zGetAppsByAppIdAgentSandboxFilesReadPath, - query: zGetAppsByAppIdAgentSandboxFilesReadQuery, - }), - ) - .output(zGetAppsByAppIdAgentSandboxFilesReadResponse) - -export const read = { - get: get8, -} - -/** - * Upload one Agent App sandbox file as a Dify ToolFile mapping - */ -export const post11 = oc - .route({ - description: 'Upload one Agent App sandbox file as a Dify ToolFile mapping', - inputStructure: 'detailed', - method: 'POST', - operationId: 'postAppsByAppIdAgentSandboxFilesUpload', - path: '/apps/{app_id}/agent-sandbox/files/upload', - tags: ['console'], - }) - .input( - z.object({ - body: zPostAppsByAppIdAgentSandboxFilesUploadBody, - params: zPostAppsByAppIdAgentSandboxFilesUploadPath, - }), - ) - .output(zPostAppsByAppIdAgentSandboxFilesUploadResponse) - -export const upload = { - post: post11, -} - -/** - * List a directory in an Agent App conversation sandbox - */ -export const get9 = oc - .route({ - description: 'List a directory in an Agent App conversation sandbox', - inputStructure: 'detailed', - method: 'GET', - operationId: 'getAppsByAppIdAgentSandboxFiles', - path: '/apps/{app_id}/agent-sandbox/files', - tags: ['console'], - }) - .input( - z.object({ - params: zGetAppsByAppIdAgentSandboxFilesPath, - query: zGetAppsByAppIdAgentSandboxFilesQuery, - }), - ) - .output(zGetAppsByAppIdAgentSandboxFilesResponse) - -export const files = { - get: get9, - read, - upload, -} - -export const agentSandbox = { - files, -} - /** * Time-limited external signed URL for one drive value (no streaming proxy) */ -export const get10 = oc +export const get5 = oc .route({ description: 'Time-limited external signed URL for one drive value (no streaming proxy)', inputStructure: 'detailed', @@ -1019,13 +808,13 @@ export const get10 = oc .output(zGetAppsByAppIdAgentDriveFilesDownloadResponse) export const download = { - get: get10, + get: get5, } /** * Truncated text preview of one drive value (binary-safe; SKILL.md is the main case) */ -export const get11 = oc +export const get6 = oc .route({ description: 'Truncated text preview of one drive value (binary-safe; SKILL.md is the main case)', @@ -1044,13 +833,13 @@ export const get11 = oc .output(zGetAppsByAppIdAgentDriveFilesPreviewResponse) export const preview2 = { - get: get11, + get: get6, } /** * List agent drive entries (read-only inspector; one endpoint for both tabs) */ -export const get12 = oc +export const get7 = oc .route({ description: 'List agent drive entries (read-only inspector; one endpoint for both tabs)', inputStructure: 'detailed', @@ -1067,14 +856,14 @@ export const get12 = oc ) .output(zGetAppsByAppIdAgentDriveFilesResponse) -export const files2 = { - get: get12, +export const files = { + get: get7, download, preview: preview2, } export const drive = { - files: files2, + files, } /** @@ -1102,7 +891,7 @@ export const delete_ = oc * * Commit an uploaded file into the agent drive under files/ (ENG-625 D3) */ -export const post12 = oc +export const post9 = oc .route({ description: 'Commit an uploaded file into the agent drive under files/ (ENG-625 D3)', inputStructure: 'detailed', @@ -1122,9 +911,9 @@ export const post12 = oc ) .output(zPostAppsByAppIdAgentFilesResponse) -export const files3 = { +export const files2 = { delete: delete_, - post: post12, + post: post9, } /** @@ -1132,7 +921,7 @@ export const files3 = { * * Get agent execution logs for an application */ -export const get13 = oc +export const get8 = oc .route({ description: 'Get agent execution logs for an application', inputStructure: 'detailed', @@ -1146,7 +935,7 @@ export const get13 = oc .output(zGetAppsByAppIdAgentLogsResponse) export const logs = { - get: get13, + get: get8, } /** @@ -1154,7 +943,7 @@ export const logs = { * * Validate + standardize a Skill into the agent drive (ENG-594) */ -export const post13 = oc +export const post10 = oc .route({ description: 'Validate + standardize a Skill into the agent drive (ENG-594)', inputStructure: 'detailed', @@ -1174,7 +963,7 @@ export const post13 = oc .output(zPostAppsByAppIdAgentSkillsStandardizeResponse) export const standardize = { - post: post13, + post: post10, } /** @@ -1184,7 +973,7 @@ export const standardize = { * Returns a validated skill ref (to bind into the Agent soul config on save) * plus its manifest. Standardizing into the agent drive is ENG-594. */ -export const post14 = oc +export const post11 = oc .route({ description: 'Upload + validate a Skill package (.zip/.skill) and extract its manifest\nReturns a validated skill ref (to bind into the Agent soul config on save)\nplus its manifest. Standardizing into the agent drive is ENG-594.', @@ -1199,8 +988,8 @@ export const post14 = oc .input(z.object({ params: zPostAppsByAppIdAgentSkillsUploadPath })) .output(zPostAppsByAppIdAgentSkillsUploadResponse) -export const upload2 = { - post: post14, +export const upload = { + post: post11, } /** @@ -1209,7 +998,7 @@ export const upload2 = { * Infer CLI tool + ENV suggestions from a standardized skill's SKILL.md (draft only, ENG-371) * Saving still goes through composer validation. */ -export const post15 = oc +export const post12 = oc .route({ description: 'Infer CLI tool + ENV suggestions from a standardized skill\'s SKILL.md (draft only, ENG-371)\nSaving still goes through composer validation.', @@ -1229,7 +1018,7 @@ export const post15 = oc .output(zPostAppsByAppIdAgentSkillsBySlugInferToolsResponse) export const inferTools = { - post: post15, + post: post12, } /** @@ -1260,13 +1049,13 @@ export const bySlug = { export const skills = { standardize, - upload: upload2, + upload, bySlug, } export const agent = { drive, - files: files3, + files: files2, logs, skills, } @@ -1274,7 +1063,7 @@ export const agent = { /** * Get status of annotation reply action job */ -export const get14 = oc +export const get9 = oc .route({ description: 'Get status of annotation reply action job', inputStructure: 'detailed', @@ -1287,7 +1076,7 @@ export const get14 = oc .output(zGetAppsByAppIdAnnotationReplyByActionStatusByJobIdResponse) export const byJobId = { - get: get14, + get: get9, } export const status = { @@ -1297,7 +1086,7 @@ export const status = { /** * Enable or disable annotation reply for an app */ -export const post16 = oc +export const post13 = oc .route({ description: 'Enable or disable annotation reply for an app', inputStructure: 'detailed', @@ -1315,7 +1104,7 @@ export const post16 = oc .output(zPostAppsByAppIdAnnotationReplyByActionResponse) export const byAction = { - post: post16, + post: post13, status, } @@ -1326,7 +1115,7 @@ export const annotationReply = { /** * Get annotation settings for an app */ -export const get15 = oc +export const get10 = oc .route({ description: 'Get annotation settings for an app', inputStructure: 'detailed', @@ -1339,13 +1128,13 @@ export const get15 = oc .output(zGetAppsByAppIdAnnotationSettingResponse) export const annotationSetting = { - get: get15, + get: get10, } /** * Update annotation settings for an app */ -export const post17 = oc +export const post14 = oc .route({ description: 'Update annotation settings for an app', inputStructure: 'detailed', @@ -1363,7 +1152,7 @@ export const post17 = oc .output(zPostAppsByAppIdAnnotationSettingsByAnnotationSettingIdResponse) export const byAnnotationSettingId = { - post: post17, + post: post14, } export const annotationSettings = { @@ -1373,7 +1162,7 @@ export const annotationSettings = { /** * Batch import annotations from CSV file with rate limiting and security checks */ -export const post18 = oc +export const post15 = oc .route({ description: 'Batch import annotations from CSV file with rate limiting and security checks', inputStructure: 'detailed', @@ -1386,13 +1175,13 @@ export const post18 = oc .output(zPostAppsByAppIdAnnotationsBatchImportResponse) export const batchImport = { - post: post18, + post: post15, } /** * Get status of batch import job */ -export const get16 = oc +export const get11 = oc .route({ description: 'Get status of batch import job', inputStructure: 'detailed', @@ -1405,7 +1194,7 @@ export const get16 = oc .output(zGetAppsByAppIdAnnotationsBatchImportStatusByJobIdResponse) export const byJobId2 = { - get: get16, + get: get11, } export const batchImportStatus = { @@ -1415,7 +1204,7 @@ export const batchImportStatus = { /** * Get count of message annotations for the app */ -export const get17 = oc +export const get12 = oc .route({ description: 'Get count of message annotations for the app', inputStructure: 'detailed', @@ -1428,13 +1217,13 @@ export const get17 = oc .output(zGetAppsByAppIdAnnotationsCountResponse) export const count2 = { - get: get17, + get: get12, } /** * Export all annotations for an app with CSV injection protection */ -export const get18 = oc +export const get13 = oc .route({ description: 'Export all annotations for an app with CSV injection protection', inputStructure: 'detailed', @@ -1447,13 +1236,13 @@ export const get18 = oc .output(zGetAppsByAppIdAnnotationsExportResponse) export const export_ = { - get: get18, + get: get13, } /** * Get hit histories for an annotation */ -export const get19 = oc +export const get14 = oc .route({ description: 'Get hit histories for an annotation', inputStructure: 'detailed', @@ -1471,7 +1260,7 @@ export const get19 = oc .output(zGetAppsByAppIdAnnotationsByAnnotationIdHitHistoriesResponse) export const hitHistories = { - get: get19, + get: get14, } export const delete3 = oc @@ -1489,7 +1278,7 @@ export const delete3 = oc /** * Update or delete an annotation */ -export const post19 = oc +export const post16 = oc .route({ description: 'Update or delete an annotation', inputStructure: 'detailed', @@ -1508,7 +1297,7 @@ export const post19 = oc export const byAnnotationId = { delete: delete3, - post: post19, + post: post16, hitHistories, } @@ -1527,7 +1316,7 @@ export const delete4 = oc /** * Get annotations for an app with pagination */ -export const get20 = oc +export const get15 = oc .route({ description: 'Get annotations for an app with pagination', inputStructure: 'detailed', @@ -1547,7 +1336,7 @@ export const get20 = oc /** * Create a new annotation for an app */ -export const post20 = oc +export const post17 = oc .route({ description: 'Create a new annotation for an app', inputStructure: 'detailed', @@ -1564,8 +1353,8 @@ export const post20 = oc export const annotations = { delete: delete4, - get: get20, - post: post20, + get: get15, + post: post17, batchImport, batchImportStatus, count: count2, @@ -1576,7 +1365,7 @@ export const annotations = { /** * Enable or disable app API */ -export const post21 = oc +export const post18 = oc .route({ description: 'Enable or disable app API', inputStructure: 'detailed', @@ -1589,13 +1378,13 @@ export const post21 = oc .output(zPostAppsByAppIdApiEnableResponse) export const apiEnable = { - post: post21, + post: post18, } /** * Transcript audio to text for chat messages */ -export const post22 = oc +export const post19 = oc .route({ description: 'Transcript audio to text for chat messages', inputStructure: 'detailed', @@ -1608,7 +1397,7 @@ export const post22 = oc .output(zPostAppsByAppIdAudioToTextResponse) export const audioToText = { - post: post22, + post: post19, } /** @@ -1630,7 +1419,7 @@ export const delete5 = oc /** * Get chat conversation details */ -export const get21 = oc +export const get16 = oc .route({ description: 'Get chat conversation details', inputStructure: 'detailed', @@ -1644,13 +1433,13 @@ export const get21 = oc export const byConversationId = { delete: delete5, - get: get21, + get: get16, } /** * Get chat conversations with pagination, filtering and summary */ -export const get22 = oc +export const get17 = oc .route({ description: 'Get chat conversations with pagination, filtering and summary', inputStructure: 'detailed', @@ -1668,14 +1457,14 @@ export const get22 = oc .output(zGetAppsByAppIdChatConversationsResponse) export const chatConversations = { - get: get22, + get: get17, byConversationId, } /** * Get suggested questions for a message */ -export const get23 = oc +export const get18 = oc .route({ description: 'Get suggested questions for a message', inputStructure: 'detailed', @@ -1688,7 +1477,7 @@ export const get23 = oc .output(zGetAppsByAppIdChatMessagesByMessageIdSuggestedQuestionsResponse) export const suggestedQuestions = { - get: get23, + get: get18, } export const byMessageId = { @@ -1698,7 +1487,7 @@ export const byMessageId = { /** * Stop a running chat message generation */ -export const post23 = oc +export const post20 = oc .route({ description: 'Stop a running chat message generation', inputStructure: 'detailed', @@ -1711,7 +1500,7 @@ export const post23 = oc .output(zPostAppsByAppIdChatMessagesByTaskIdStopResponse) export const stop = { - post: post23, + post: post20, } export const byTaskId = { @@ -1721,7 +1510,7 @@ export const byTaskId = { /** * Get chat messages for a conversation with pagination */ -export const get24 = oc +export const get19 = oc .route({ description: 'Get chat messages for a conversation with pagination', inputStructure: 'detailed', @@ -1736,7 +1525,7 @@ export const get24 = oc .output(zGetAppsByAppIdChatMessagesResponse) export const chatMessages = { - get: get24, + get: get19, byMessageId, byTaskId, } @@ -1760,7 +1549,7 @@ export const delete6 = oc /** * Get completion conversation details with messages */ -export const get25 = oc +export const get20 = oc .route({ description: 'Get completion conversation details with messages', inputStructure: 'detailed', @@ -1774,13 +1563,13 @@ export const get25 = oc export const byConversationId2 = { delete: delete6, - get: get25, + get: get20, } /** * Get completion conversations with pagination and filtering */ -export const get26 = oc +export const get21 = oc .route({ description: 'Get completion conversations with pagination and filtering', inputStructure: 'detailed', @@ -1798,14 +1587,14 @@ export const get26 = oc .output(zGetAppsByAppIdCompletionConversationsResponse) export const completionConversations = { - get: get26, + get: get21, byConversationId: byConversationId2, } /** * Stop a running completion message generation */ -export const post24 = oc +export const post21 = oc .route({ description: 'Stop a running completion message generation', inputStructure: 'detailed', @@ -1818,7 +1607,7 @@ export const post24 = oc .output(zPostAppsByAppIdCompletionMessagesByTaskIdStopResponse) export const stop2 = { - post: post24, + post: post21, } export const byTaskId2 = { @@ -1828,7 +1617,7 @@ export const byTaskId2 = { /** * Generate completion message for debugging */ -export const post25 = oc +export const post22 = oc .route({ description: 'Generate completion message for debugging', inputStructure: 'detailed', @@ -1846,14 +1635,14 @@ export const post25 = oc .output(zPostAppsByAppIdCompletionMessagesResponse) export const completionMessages = { - post: post25, + post: post22, byTaskId: byTaskId2, } /** * Get conversation variables for an application */ -export const get27 = oc +export const get22 = oc .route({ description: 'Get conversation variables for an application', inputStructure: 'detailed', @@ -1871,7 +1660,7 @@ export const get27 = oc .output(zGetAppsByAppIdConversationVariablesResponse) export const conversationVariables = { - get: get27, + get: get22, } /** @@ -1881,7 +1670,7 @@ export const conversationVariables = { * Convert expert mode of chatbot app to workflow mode * Convert Completion App to Workflow App */ -export const post26 = oc +export const post23 = oc .route({ description: 'Convert application to workflow mode\nConvert expert mode of chatbot app to workflow mode\nConvert Completion App to Workflow App', @@ -1901,7 +1690,7 @@ export const post26 = oc .output(zPostAppsByAppIdConvertToWorkflowResponse) export const convertToWorkflow = { - post: post26, + post: post23, } /** @@ -1909,7 +1698,7 @@ export const convertToWorkflow = { * * Create a copy of an existing application */ -export const post27 = oc +export const post24 = oc .route({ description: 'Create a copy of an existing application', inputStructure: 'detailed', @@ -1924,7 +1713,7 @@ export const post27 = oc .output(zPostAppsByAppIdCopyResponse) export const copy = { - post: post27, + post: post24, } /** @@ -1932,7 +1721,7 @@ export const copy = { * * Export application configuration as DSL */ -export const get28 = oc +export const get23 = oc .route({ description: 'Export application configuration as DSL', inputStructure: 'detailed', @@ -1948,13 +1737,13 @@ export const get28 = oc .output(zGetAppsByAppIdExportResponse) export const export2 = { - get: get28, + get: get23, } /** * Export user feedback data for Google Sheets */ -export const get29 = oc +export const get24 = oc .route({ description: 'Export user feedback data for Google Sheets', inputStructure: 'detailed', @@ -1972,13 +1761,13 @@ export const get29 = oc .output(zGetAppsByAppIdFeedbacksExportResponse) export const export3 = { - get: get29, + get: get24, } /** * Create or update message feedback (like/dislike) */ -export const post28 = oc +export const post25 = oc .route({ description: 'Create or update message feedback (like/dislike)', inputStructure: 'detailed', @@ -1991,14 +1780,14 @@ export const post28 = oc .output(zPostAppsByAppIdFeedbacksResponse) export const feedbacks = { - post: post28, + post: post25, export: export3, } /** * Update application icon */ -export const post29 = oc +export const post26 = oc .route({ description: 'Update application icon', inputStructure: 'detailed', @@ -2011,13 +1800,13 @@ export const post29 = oc .output(zPostAppsByAppIdIconResponse) export const icon = { - post: post29, + post: post26, } /** * Get message details by ID */ -export const get30 = oc +export const get25 = oc .route({ description: 'Get message details by ID', inputStructure: 'detailed', @@ -2030,7 +1819,7 @@ export const get30 = oc .output(zGetAppsByAppIdMessagesByMessageIdResponse) export const byMessageId2 = { - get: get30, + get: get25, } export const messages = { @@ -2042,7 +1831,7 @@ export const messages = { * * Update application model configuration */ -export const post30 = oc +export const post27 = oc .route({ description: 'Update application model configuration', inputStructure: 'detailed', @@ -2058,13 +1847,13 @@ export const post30 = oc .output(zPostAppsByAppIdModelConfigResponse) export const modelConfig = { - post: post30, + post: post27, } /** * Check if app name is available */ -export const post31 = oc +export const post28 = oc .route({ description: 'Check if app name is available', inputStructure: 'detailed', @@ -2077,13 +1866,13 @@ export const post31 = oc .output(zPostAppsByAppIdNameResponse) export const name = { - post: post31, + post: post28, } /** * Publish app to Creators Platform */ -export const post32 = oc +export const post29 = oc .route({ inputStructure: 'detailed', method: 'POST', @@ -2096,13 +1885,13 @@ export const post32 = oc .output(zPostAppsByAppIdPublishToCreatorsPlatformResponse) export const publishToCreatorsPlatform = { - post: post32, + post: post29, } /** * Get MCP server configuration for an application */ -export const get31 = oc +export const get26 = oc .route({ description: 'Get MCP server configuration for an application', inputStructure: 'detailed', @@ -2117,7 +1906,7 @@ export const get31 = oc /** * Create MCP server configuration for an application */ -export const post33 = oc +export const post30 = oc .route({ description: 'Create MCP server configuration for an application', inputStructure: 'detailed', @@ -2133,7 +1922,7 @@ export const post33 = oc /** * Update MCP server configuration for an application */ -export const put2 = oc +export const put = oc .route({ description: 'Update MCP server configuration for an application', inputStructure: 'detailed', @@ -2146,15 +1935,15 @@ export const put2 = oc .output(zPutAppsByAppIdServerResponse) export const server = { - get: get31, - post: post33, - put: put2, + get: get26, + post: post30, + put, } /** * Reset access token for application site */ -export const post34 = oc +export const post31 = oc .route({ description: 'Reset access token for application site', inputStructure: 'detailed', @@ -2167,13 +1956,13 @@ export const post34 = oc .output(zPostAppsByAppIdSiteAccessTokenResetResponse) export const accessTokenReset = { - post: post34, + post: post31, } /** * Update application site configuration */ -export const post35 = oc +export const post32 = oc .route({ description: 'Update application site configuration', inputStructure: 'detailed', @@ -2186,14 +1975,14 @@ export const post35 = oc .output(zPostAppsByAppIdSiteResponse) export const site = { - post: post35, + post: post32, accessTokenReset, } /** * Enable or disable app site */ -export const post36 = oc +export const post33 = oc .route({ description: 'Enable or disable app site', inputStructure: 'detailed', @@ -2206,7 +1995,7 @@ export const post36 = oc .output(zPostAppsByAppIdSiteEnableResponse) export const siteEnable = { - post: post36, + post: post33, } /** @@ -2227,7 +2016,7 @@ export const delete7 = oc /** * Star an application for the current account */ -export const post37 = oc +export const post34 = oc .route({ description: 'Star an application for the current account', inputStructure: 'detailed', @@ -2241,13 +2030,13 @@ export const post37 = oc export const star = { delete: delete7, - post: post37, + post: post34, } /** * Get average response time statistics for an application */ -export const get32 = oc +export const get27 = oc .route({ description: 'Get average response time statistics for an application', inputStructure: 'detailed', @@ -2265,13 +2054,13 @@ export const get32 = oc .output(zGetAppsByAppIdStatisticsAverageResponseTimeResponse) export const averageResponseTime = { - get: get32, + get: get27, } /** * Get average session interaction statistics for an application */ -export const get33 = oc +export const get28 = oc .route({ description: 'Get average session interaction statistics for an application', inputStructure: 'detailed', @@ -2289,13 +2078,13 @@ export const get33 = oc .output(zGetAppsByAppIdStatisticsAverageSessionInteractionsResponse) export const averageSessionInteractions = { - get: get33, + get: get28, } /** * Get daily conversation statistics for an application */ -export const get34 = oc +export const get29 = oc .route({ description: 'Get daily conversation statistics for an application', inputStructure: 'detailed', @@ -2313,13 +2102,13 @@ export const get34 = oc .output(zGetAppsByAppIdStatisticsDailyConversationsResponse) export const dailyConversations = { - get: get34, + get: get29, } /** * Get daily terminal/end-user statistics for an application */ -export const get35 = oc +export const get30 = oc .route({ description: 'Get daily terminal/end-user statistics for an application', inputStructure: 'detailed', @@ -2337,13 +2126,13 @@ export const get35 = oc .output(zGetAppsByAppIdStatisticsDailyEndUsersResponse) export const dailyEndUsers = { - get: get35, + get: get30, } /** * Get daily message statistics for an application */ -export const get36 = oc +export const get31 = oc .route({ description: 'Get daily message statistics for an application', inputStructure: 'detailed', @@ -2361,13 +2150,13 @@ export const get36 = oc .output(zGetAppsByAppIdStatisticsDailyMessagesResponse) export const dailyMessages = { - get: get36, + get: get31, } /** * Get daily token cost statistics for an application */ -export const get37 = oc +export const get32 = oc .route({ description: 'Get daily token cost statistics for an application', inputStructure: 'detailed', @@ -2385,13 +2174,13 @@ export const get37 = oc .output(zGetAppsByAppIdStatisticsTokenCostsResponse) export const tokenCosts = { - get: get37, + get: get32, } /** * Get tokens per second statistics for an application */ -export const get38 = oc +export const get33 = oc .route({ description: 'Get tokens per second statistics for an application', inputStructure: 'detailed', @@ -2409,13 +2198,13 @@ export const get38 = oc .output(zGetAppsByAppIdStatisticsTokensPerSecondResponse) export const tokensPerSecond = { - get: get38, + get: get33, } /** * Get user satisfaction rate statistics for an application */ -export const get39 = oc +export const get34 = oc .route({ description: 'Get user satisfaction rate statistics for an application', inputStructure: 'detailed', @@ -2433,7 +2222,7 @@ export const get39 = oc .output(zGetAppsByAppIdStatisticsUserSatisfactionRateResponse) export const userSatisfactionRate = { - get: get39, + get: get34, } export const statistics = { @@ -2450,7 +2239,7 @@ export const statistics = { /** * Get available TTS voices for a specific language */ -export const get40 = oc +export const get35 = oc .route({ description: 'Get available TTS voices for a specific language', inputStructure: 'detailed', @@ -2468,13 +2257,13 @@ export const get40 = oc .output(zGetAppsByAppIdTextToAudioVoicesResponse) export const voices = { - get: get40, + get: get35, } /** * Convert text to speech for chat messages */ -export const post38 = oc +export const post35 = oc .route({ description: 'Convert text to speech for chat messages', inputStructure: 'detailed', @@ -2489,7 +2278,7 @@ export const post38 = oc .output(zPostAppsByAppIdTextToAudioResponse) export const textToAudio = { - post: post38, + post: post35, voices, } @@ -2498,7 +2287,7 @@ export const textToAudio = { * * Get app tracing configuration */ -export const get41 = oc +export const get36 = oc .route({ description: 'Get app tracing configuration', inputStructure: 'detailed', @@ -2514,7 +2303,7 @@ export const get41 = oc /** * Update app tracing configuration */ -export const post39 = oc +export const post36 = oc .route({ description: 'Update app tracing configuration', inputStructure: 'detailed', @@ -2527,8 +2316,8 @@ export const post39 = oc .output(zPostAppsByAppIdTraceResponse) export const trace = { - get: get41, - post: post39, + get: get36, + post: post36, } /** @@ -2558,7 +2347,7 @@ export const delete8 = oc /** * Get tracing configuration for an application */ -export const get42 = oc +export const get37 = oc .route({ description: 'Get tracing configuration for an application', inputStructure: 'detailed', @@ -2597,7 +2386,7 @@ export const patch = oc * * Create a new tracing configuration for an application */ -export const post40 = oc +export const post37 = oc .route({ description: 'Create a new tracing configuration for an application', inputStructure: 'detailed', @@ -2615,15 +2404,15 @@ export const post40 = oc export const traceConfig = { delete: delete8, - get: get42, + get: get37, patch, - post: post40, + post: post37, } /** * Update app trigger (enable/disable) */ -export const post41 = oc +export const post38 = oc .route({ inputStructure: 'detailed', method: 'POST', @@ -2641,13 +2430,13 @@ export const post41 = oc .output(zPostAppsByAppIdTriggerEnableResponse) export const triggerEnable = { - post: post41, + post: post38, } /** * Get app triggers list */ -export const get43 = oc +export const get38 = oc .route({ inputStructure: 'detailed', method: 'GET', @@ -2660,7 +2449,7 @@ export const get43 = oc .output(zGetAppsByAppIdTriggersResponse) export const triggers = { - get: get43, + get: get38, } /** @@ -2668,7 +2457,7 @@ export const triggers = { * * Get workflow application execution logs */ -export const get44 = oc +export const get39 = oc .route({ description: 'Get workflow application execution logs', inputStructure: 'detailed', @@ -2687,7 +2476,7 @@ export const get44 = oc .output(zGetAppsByAppIdWorkflowAppLogsResponse) export const workflowAppLogs = { - get: get44, + get: get39, } /** @@ -2695,7 +2484,7 @@ export const workflowAppLogs = { * * Get workflow archived execution logs */ -export const get45 = oc +export const get40 = oc .route({ description: 'Get workflow archived execution logs', inputStructure: 'detailed', @@ -2714,7 +2503,7 @@ export const get45 = oc .output(zGetAppsByAppIdWorkflowArchivedLogsResponse) export const workflowArchivedLogs = { - get: get45, + get: get40, } /** @@ -2722,7 +2511,7 @@ export const workflowArchivedLogs = { * * Get workflow runs count statistics */ -export const get46 = oc +export const get41 = oc .route({ description: 'Get workflow runs count statistics', inputStructure: 'detailed', @@ -2741,7 +2530,7 @@ export const get46 = oc .output(zGetAppsByAppIdWorkflowRunsCountResponse) export const count3 = { - get: get46, + get: get41, } /** @@ -2749,7 +2538,7 @@ export const count3 = { * * Stop running workflow task */ -export const post42 = oc +export const post39 = oc .route({ description: 'Stop running workflow task', inputStructure: 'detailed', @@ -2763,7 +2552,7 @@ export const post42 = oc .output(zPostAppsByAppIdWorkflowRunsTasksByTaskIdStopResponse) export const stop3 = { - post: post42, + post: post39, } export const byTaskId3 = { @@ -2777,7 +2566,7 @@ export const tasks = { /** * Generate a download URL for an archived workflow run. */ -export const get47 = oc +export const get42 = oc .route({ description: 'Generate a download URL for an archived workflow run.', inputStructure: 'detailed', @@ -2790,7 +2579,7 @@ export const get47 = oc .output(zGetAppsByAppIdWorkflowRunsByRunIdExportResponse) export const export4 = { - get: get47, + get: get42, } /** @@ -2798,7 +2587,7 @@ export const export4 = { * * Get workflow run node execution list */ -export const get48 = oc +export const get43 = oc .route({ description: 'Get workflow run node execution list', inputStructure: 'detailed', @@ -2812,7 +2601,7 @@ export const get48 = oc .output(zGetAppsByAppIdWorkflowRunsByRunIdNodeExecutionsResponse) export const nodeExecutions = { - get: get48, + get: get43, } /** @@ -2820,7 +2609,7 @@ export const nodeExecutions = { * * Get workflow run detail */ -export const get49 = oc +export const get44 = oc .route({ description: 'Get workflow run detail', inputStructure: 'detailed', @@ -2834,7 +2623,7 @@ export const get49 = oc .output(zGetAppsByAppIdWorkflowRunsByRunIdResponse) export const byRunId = { - get: get49, + get: get44, export: export4, nodeExecutions, } @@ -2842,7 +2631,7 @@ export const byRunId = { /** * Read a text/binary preview file in a workflow Agent node sandbox */ -export const get50 = oc +export const get45 = oc .route({ description: 'Read a text/binary preview file in a workflow Agent node sandbox', inputStructure: 'detailed', @@ -2859,14 +2648,14 @@ export const get50 = oc ) .output(zGetAppsByAppIdWorkflowRunsByWorkflowRunIdAgentNodesByNodeIdSandboxFilesReadResponse) -export const read2 = { - get: get50, +export const read = { + get: get45, } /** * Upload one workflow Agent sandbox file as a Dify ToolFile mapping */ -export const post43 = oc +export const post40 = oc .route({ description: 'Upload one workflow Agent sandbox file as a Dify ToolFile mapping', inputStructure: 'detailed', @@ -2883,14 +2672,14 @@ export const post43 = oc ) .output(zPostAppsByAppIdWorkflowRunsByWorkflowRunIdAgentNodesByNodeIdSandboxFilesUploadResponse) -export const upload3 = { - post: post43, +export const upload2 = { + post: post40, } /** * List a directory in a workflow Agent node sandbox */ -export const get51 = oc +export const get46 = oc .route({ description: 'List a directory in a workflow Agent node sandbox', inputStructure: 'detailed', @@ -2908,14 +2697,14 @@ export const get51 = oc ) .output(zGetAppsByAppIdWorkflowRunsByWorkflowRunIdAgentNodesByNodeIdSandboxFilesResponse) -export const files4 = { - get: get51, - read: read2, - upload: upload3, +export const files3 = { + get: get46, + read, + upload: upload2, } export const sandbox = { - files: files4, + files: files3, } export const byNodeId4 = { @@ -2935,7 +2724,7 @@ export const byWorkflowRunId = { * * Get workflow run list */ -export const get52 = oc +export const get47 = oc .route({ description: 'Get workflow run list', inputStructure: 'detailed', @@ -2954,7 +2743,7 @@ export const get52 = oc .output(zGetAppsByAppIdWorkflowRunsResponse) export const workflowRuns2 = { - get: get52, + get: get47, count: count3, tasks, byRunId, @@ -2966,7 +2755,7 @@ export const workflowRuns2 = { * * Get all users in current tenant for mentions */ -export const get53 = oc +export const get48 = oc .route({ description: 'Get all users in current tenant for mentions', inputStructure: 'detailed', @@ -2980,7 +2769,7 @@ export const get53 = oc .output(zGetAppsByAppIdWorkflowCommentsMentionUsersResponse) export const mentionUsers = { - get: get53, + get: get48, } /** @@ -3007,7 +2796,7 @@ export const delete9 = oc * * Update a comment reply */ -export const put3 = oc +export const put2 = oc .route({ description: 'Update a comment reply', inputStructure: 'detailed', @@ -3027,7 +2816,7 @@ export const put3 = oc export const byReplyId = { delete: delete9, - put: put3, + put: put2, } /** @@ -3035,7 +2824,7 @@ export const byReplyId = { * * Add a reply to a workflow comment */ -export const post44 = oc +export const post41 = oc .route({ description: 'Add a reply to a workflow comment', inputStructure: 'detailed', @@ -3055,7 +2844,7 @@ export const post44 = oc .output(zPostAppsByAppIdWorkflowCommentsByCommentIdRepliesResponse) export const replies = { - post: post44, + post: post41, byReplyId, } @@ -3064,7 +2853,7 @@ export const replies = { * * Resolve a workflow comment */ -export const post45 = oc +export const post42 = oc .route({ description: 'Resolve a workflow comment', inputStructure: 'detailed', @@ -3078,7 +2867,7 @@ export const post45 = oc .output(zPostAppsByAppIdWorkflowCommentsByCommentIdResolveResponse) export const resolve = { - post: post45, + post: post42, } /** @@ -3105,7 +2894,7 @@ export const delete10 = oc * * Get a specific workflow comment */ -export const get54 = oc +export const get49 = oc .route({ description: 'Get a specific workflow comment', inputStructure: 'detailed', @@ -3123,7 +2912,7 @@ export const get54 = oc * * Update a workflow comment */ -export const put4 = oc +export const put3 = oc .route({ description: 'Update a workflow comment', inputStructure: 'detailed', @@ -3143,8 +2932,8 @@ export const put4 = oc export const byCommentId = { delete: delete10, - get: get54, - put: put4, + get: get49, + put: put3, replies, resolve, } @@ -3154,7 +2943,7 @@ export const byCommentId = { * * Get all comments for a workflow */ -export const get55 = oc +export const get50 = oc .route({ description: 'Get all comments for a workflow', inputStructure: 'detailed', @@ -3172,7 +2961,7 @@ export const get55 = oc * * Create a new workflow comment */ -export const post46 = oc +export const post43 = oc .route({ description: 'Create a new workflow comment', inputStructure: 'detailed', @@ -3192,8 +2981,8 @@ export const post46 = oc .output(zPostAppsByAppIdWorkflowCommentsResponse) export const comments = { - get: get55, - post: post46, + get: get50, + post: post43, mentionUsers, byCommentId, } @@ -3201,7 +2990,7 @@ export const comments = { /** * Get workflow average app interaction statistics */ -export const get56 = oc +export const get51 = oc .route({ description: 'Get workflow average app interaction statistics', inputStructure: 'detailed', @@ -3219,13 +3008,13 @@ export const get56 = oc .output(zGetAppsByAppIdWorkflowStatisticsAverageAppInteractionsResponse) export const averageAppInteractions = { - get: get56, + get: get51, } /** * Get workflow daily runs statistics */ -export const get57 = oc +export const get52 = oc .route({ description: 'Get workflow daily runs statistics', inputStructure: 'detailed', @@ -3243,13 +3032,13 @@ export const get57 = oc .output(zGetAppsByAppIdWorkflowStatisticsDailyConversationsResponse) export const dailyConversations2 = { - get: get57, + get: get52, } /** * Get workflow daily terminals statistics */ -export const get58 = oc +export const get53 = oc .route({ description: 'Get workflow daily terminals statistics', inputStructure: 'detailed', @@ -3267,13 +3056,13 @@ export const get58 = oc .output(zGetAppsByAppIdWorkflowStatisticsDailyTerminalsResponse) export const dailyTerminals = { - get: get58, + get: get53, } /** * Get workflow daily token cost statistics */ -export const get59 = oc +export const get54 = oc .route({ description: 'Get workflow daily token cost statistics', inputStructure: 'detailed', @@ -3291,7 +3080,7 @@ export const get59 = oc .output(zGetAppsByAppIdWorkflowStatisticsTokenCostsResponse) export const tokenCosts2 = { - get: get59, + get: get54, } export const statistics2 = { @@ -3311,7 +3100,7 @@ export const workflow = { * * Get default block configuration by type */ -export const get60 = oc +export const get55 = oc .route({ description: 'Get default block configuration by type', inputStructure: 'detailed', @@ -3330,7 +3119,7 @@ export const get60 = oc .output(zGetAppsByAppIdWorkflowsDefaultWorkflowBlockConfigsByBlockTypeResponse) export const byBlockType = { - get: get60, + get: get55, } /** @@ -3338,7 +3127,7 @@ export const byBlockType = { * * Get default block configurations for workflow */ -export const get61 = oc +export const get56 = oc .route({ description: 'Get default block configurations for workflow', inputStructure: 'detailed', @@ -3352,14 +3141,14 @@ export const get61 = oc .output(zGetAppsByAppIdWorkflowsDefaultWorkflowBlockConfigsResponse) export const defaultWorkflowBlockConfigs = { - get: get61, + get: get56, byBlockType, } /** * Get conversation variables for workflow */ -export const get62 = oc +export const get57 = oc .route({ description: 'Get conversation variables for workflow', inputStructure: 'detailed', @@ -3374,7 +3163,7 @@ export const get62 = oc /** * Update conversation variables for workflow draft */ -export const post47 = oc +export const post44 = oc .route({ description: 'Update conversation variables for workflow draft', inputStructure: 'detailed', @@ -3392,8 +3181,8 @@ export const post47 = oc .output(zPostAppsByAppIdWorkflowsDraftConversationVariablesResponse) export const conversationVariables2 = { - get: get62, - post: post47, + get: get57, + post: post44, } /** @@ -3401,7 +3190,7 @@ export const conversationVariables2 = { * * Get environment variables for workflow */ -export const get63 = oc +export const get58 = oc .route({ description: 'Get environment variables for workflow', inputStructure: 'detailed', @@ -3417,7 +3206,7 @@ export const get63 = oc /** * Update environment variables for workflow draft */ -export const post48 = oc +export const post45 = oc .route({ description: 'Update environment variables for workflow draft', inputStructure: 'detailed', @@ -3435,14 +3224,14 @@ export const post48 = oc .output(zPostAppsByAppIdWorkflowsDraftEnvironmentVariablesResponse) export const environmentVariables = { - get: get63, - post: post48, + get: get58, + post: post45, } /** * Update draft workflow features */ -export const post49 = oc +export const post46 = oc .route({ description: 'Update draft workflow features', inputStructure: 'detailed', @@ -3460,7 +3249,7 @@ export const post49 = oc .output(zPostAppsByAppIdWorkflowsDraftFeaturesResponse) export const features = { - post: post49, + post: post46, } /** @@ -3468,7 +3257,7 @@ export const features = { * * Test human input delivery for workflow */ -export const post50 = oc +export const post47 = oc .route({ description: 'Test human input delivery for workflow', inputStructure: 'detailed', @@ -3487,7 +3276,7 @@ export const post50 = oc .output(zPostAppsByAppIdWorkflowsDraftHumanInputNodesByNodeIdDeliveryTestResponse) export const deliveryTest = { - post: post50, + post: post47, } /** @@ -3495,7 +3284,7 @@ export const deliveryTest = { * * Get human input form preview for workflow */ -export const post51 = oc +export const post48 = oc .route({ description: 'Get human input form preview for workflow', inputStructure: 'detailed', @@ -3514,7 +3303,7 @@ export const post51 = oc .output(zPostAppsByAppIdWorkflowsDraftHumanInputNodesByNodeIdFormPreviewResponse) export const preview3 = { - post: post51, + post: post48, } /** @@ -3522,7 +3311,7 @@ export const preview3 = { * * Submit human input form preview for workflow */ -export const post52 = oc +export const post49 = oc .route({ description: 'Submit human input form preview for workflow', inputStructure: 'detailed', @@ -3541,7 +3330,7 @@ export const post52 = oc .output(zPostAppsByAppIdWorkflowsDraftHumanInputNodesByNodeIdFormRunResponse) export const run5 = { - post: post52, + post: post49, } export const form2 = { @@ -3567,7 +3356,7 @@ export const humanInput2 = { * * Run draft workflow iteration node */ -export const post53 = oc +export const post50 = oc .route({ description: 'Run draft workflow iteration node', inputStructure: 'detailed', @@ -3586,7 +3375,7 @@ export const post53 = oc .output(zPostAppsByAppIdWorkflowsDraftIterationNodesByNodeIdRunResponse) export const run6 = { - post: post53, + post: post50, } export const byNodeId6 = { @@ -3606,7 +3395,7 @@ export const iteration2 = { * * Run draft workflow loop node */ -export const post54 = oc +export const post51 = oc .route({ description: 'Run draft workflow loop node', inputStructure: 'detailed', @@ -3625,7 +3414,7 @@ export const post54 = oc .output(zPostAppsByAppIdWorkflowsDraftLoopNodesByNodeIdRunResponse) export const run7 = { - post: post54, + post: post51, } export const byNodeId7 = { @@ -3640,7 +3429,7 @@ export const loop2 = { nodes: nodes6, } -export const get64 = oc +export const get59 = oc .route({ inputStructure: 'detailed', method: 'GET', @@ -3653,11 +3442,11 @@ export const get64 = oc ) .output(zGetAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerCandidatesResponse) -export const candidates2 = { - get: get64, +export const candidates = { + get: get59, } -export const post55 = oc +export const post52 = oc .route({ inputStructure: 'detailed', method: 'POST', @@ -3674,10 +3463,10 @@ export const post55 = oc .output(zPostAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerImpactResponse) export const impact = { - post: post55, + post: post52, } -export const post56 = oc +export const post53 = oc .route({ inputStructure: 'detailed', method: 'POST', @@ -3694,10 +3483,10 @@ export const post56 = oc .output(zPostAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerSaveToRosterResponse) export const saveToRoster = { - post: post56, + post: post53, } -export const post57 = oc +export const post54 = oc .route({ inputStructure: 'detailed', method: 'POST', @@ -3713,11 +3502,11 @@ export const post57 = oc ) .output(zPostAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerValidateResponse) -export const validate2 = { - post: post57, +export const validate = { + post: post54, } -export const get65 = oc +export const get60 = oc .route({ inputStructure: 'detailed', method: 'GET', @@ -3728,7 +3517,7 @@ export const get65 = oc .input(z.object({ params: zGetAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerPath })) .output(zGetAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerResponse) -export const put5 = oc +export const put4 = oc .route({ inputStructure: 'detailed', method: 'PUT', @@ -3744,19 +3533,19 @@ export const put5 = oc ) .output(zPutAppsByAppIdWorkflowsDraftNodesByNodeIdAgentComposerResponse) -export const agentComposer2 = { - get: get65, - put: put5, - candidates: candidates2, +export const agentComposer = { + get: get60, + put: put4, + candidates, impact, saveToRoster, - validate: validate2, + validate, } /** * Get last run result for draft workflow node */ -export const get66 = oc +export const get61 = oc .route({ description: 'Get last run result for draft workflow node', inputStructure: 'detailed', @@ -3769,7 +3558,7 @@ export const get66 = oc .output(zGetAppsByAppIdWorkflowsDraftNodesByNodeIdLastRunResponse) export const lastRun = { - get: get66, + get: get61, } /** @@ -3777,7 +3566,7 @@ export const lastRun = { * * Run draft workflow node */ -export const post58 = oc +export const post55 = oc .route({ description: 'Run draft workflow node', inputStructure: 'detailed', @@ -3796,7 +3585,7 @@ export const post58 = oc .output(zPostAppsByAppIdWorkflowsDraftNodesByNodeIdRunResponse) export const run8 = { - post: post58, + post: post55, } /** @@ -3804,7 +3593,7 @@ export const run8 = { * * Poll for trigger events and execute single node when event arrives */ -export const post59 = oc +export const post56 = oc .route({ description: 'Poll for trigger events and execute single node when event arrives', inputStructure: 'detailed', @@ -3818,7 +3607,7 @@ export const post59 = oc .output(zPostAppsByAppIdWorkflowsDraftNodesByNodeIdTriggerRunResponse) export const run9 = { - post: post59, + post: post56, } export const trigger = { @@ -3844,7 +3633,7 @@ export const delete11 = oc /** * Get variables for a specific node */ -export const get67 = oc +export const get62 = oc .route({ description: 'Get variables for a specific node', inputStructure: 'detailed', @@ -3858,11 +3647,11 @@ export const get67 = oc export const variables = { delete: delete11, - get: get67, + get: get62, } export const byNodeId8 = { - agentComposer: agentComposer2, + agentComposer, lastRun, run: run8, trigger, @@ -3878,7 +3667,7 @@ export const nodes7 = { * * Run draft workflow */ -export const post60 = oc +export const post57 = oc .route({ description: 'Run draft workflow', inputStructure: 'detailed', @@ -3897,13 +3686,13 @@ export const post60 = oc .output(zPostAppsByAppIdWorkflowsDraftRunResponse) export const run10 = { - post: post60, + post: post57, } /** * Server-Sent Events stream of inspector deltas for a draft workflow run. */ -export const get68 = oc +export const get63 = oc .route({ description: 'Server-Sent Events stream of inspector deltas for a draft workflow run.', inputStructure: 'detailed', @@ -3916,13 +3705,13 @@ export const get68 = oc .output(zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsEventsResponse) export const events = { - get: get68, + get: get63, } /** * Full value for one declared output, including signed download URL for files. */ -export const get69 = oc +export const get64 = oc .route({ description: 'Full value for one declared output, including signed download URL for files.', inputStructure: 'detailed', @@ -3939,7 +3728,7 @@ export const get69 = oc .output(zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdByOutputNamePreviewResponse) export const preview4 = { - get: get69, + get: get64, } export const byOutputName = { @@ -3949,7 +3738,7 @@ export const byOutputName = { /** * One node's declared outputs for a draft workflow run. */ -export const get70 = oc +export const get65 = oc .route({ description: 'One node\'s declared outputs for a draft workflow run.', inputStructure: 'detailed', @@ -3962,14 +3751,14 @@ export const get70 = oc .output(zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsByNodeIdResponse) export const byNodeId9 = { - get: get70, + get: get65, byOutputName, } /** * Snapshot of every node's declared outputs for a draft workflow run. */ -export const get71 = oc +export const get66 = oc .route({ description: 'Snapshot of every node\'s declared outputs for a draft workflow run.', inputStructure: 'detailed', @@ -3982,7 +3771,7 @@ export const get71 = oc .output(zGetAppsByAppIdWorkflowsDraftRunsByRunIdNodeOutputsResponse) export const nodeOutputs = { - get: get71, + get: get66, events, byNodeId: byNodeId9, } @@ -3998,7 +3787,7 @@ export const runs = { /** * Get system variables for workflow */ -export const get72 = oc +export const get67 = oc .route({ description: 'Get system variables for workflow', inputStructure: 'detailed', @@ -4011,7 +3800,7 @@ export const get72 = oc .output(zGetAppsByAppIdWorkflowsDraftSystemVariablesResponse) export const systemVariables = { - get: get72, + get: get67, } /** @@ -4019,7 +3808,7 @@ export const systemVariables = { * * Poll for trigger events and execute full workflow when event arrives */ -export const post61 = oc +export const post58 = oc .route({ description: 'Poll for trigger events and execute full workflow when event arrives', inputStructure: 'detailed', @@ -4038,7 +3827,7 @@ export const post61 = oc .output(zPostAppsByAppIdWorkflowsDraftTriggerRunResponse) export const run11 = { - post: post61, + post: post58, } /** @@ -4046,7 +3835,7 @@ export const run11 = { * * Full workflow debug when the start node is a trigger */ -export const post62 = oc +export const post59 = oc .route({ description: 'Full workflow debug when the start node is a trigger', inputStructure: 'detailed', @@ -4065,7 +3854,7 @@ export const post62 = oc .output(zPostAppsByAppIdWorkflowsDraftTriggerRunAllResponse) export const runAll = { - post: post62, + post: post59, } export const trigger2 = { @@ -4076,7 +3865,7 @@ export const trigger2 = { /** * Reset a workflow variable to its default value */ -export const put6 = oc +export const put5 = oc .route({ description: 'Reset a workflow variable to its default value', inputStructure: 'detailed', @@ -4089,7 +3878,7 @@ export const put6 = oc .output(zPutAppsByAppIdWorkflowsDraftVariablesByVariableIdResetResponse) export const reset = { - put: put6, + put: put5, } /** @@ -4111,7 +3900,7 @@ export const delete12 = oc /** * Get a specific workflow variable */ -export const get73 = oc +export const get68 = oc .route({ description: 'Get a specific workflow variable', inputStructure: 'detailed', @@ -4145,7 +3934,7 @@ export const patch2 = oc export const byVariableId = { delete: delete12, - get: get73, + get: get68, patch: patch2, reset, } @@ -4171,7 +3960,7 @@ export const delete13 = oc * * Get draft workflow variables */ -export const get74 = oc +export const get69 = oc .route({ description: 'Get draft workflow variables', inputStructure: 'detailed', @@ -4191,7 +3980,7 @@ export const get74 = oc export const variables2 = { delete: delete13, - get: get74, + get: get69, byVariableId, } @@ -4200,7 +3989,7 @@ export const variables2 = { * * Get draft workflow for an application */ -export const get75 = oc +export const get70 = oc .route({ description: 'Get draft workflow for an application', inputStructure: 'detailed', @@ -4218,7 +4007,7 @@ export const get75 = oc * * Sync draft workflow configuration */ -export const post63 = oc +export const post60 = oc .route({ description: 'Sync draft workflow configuration', inputStructure: 'detailed', @@ -4237,8 +4026,8 @@ export const post63 = oc .output(zPostAppsByAppIdWorkflowsDraftResponse) export const draft2 = { - get: get75, - post: post63, + get: get70, + post: post60, conversationVariables: conversationVariables2, environmentVariables, features, @@ -4258,7 +4047,7 @@ export const draft2 = { * * Get published workflow for an application */ -export const get76 = oc +export const get71 = oc .route({ description: 'Get published workflow for an application', inputStructure: 'detailed', @@ -4274,7 +4063,7 @@ export const get76 = oc /** * Publish workflow */ -export const post64 = oc +export const post61 = oc .route({ inputStructure: 'detailed', method: 'POST', @@ -4292,14 +4081,14 @@ export const post64 = oc .output(zPostAppsByAppIdWorkflowsPublishResponse) export const publish = { - get: get76, - post: post64, + get: get71, + post: post61, } /** * Server-Sent Events stream of inspector deltas for a published workflow run. */ -export const get77 = oc +export const get72 = oc .route({ description: 'Server-Sent Events stream of inspector deltas for a published workflow run.', inputStructure: 'detailed', @@ -4312,13 +4101,13 @@ export const get77 = oc .output(zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsEventsResponse) export const events2 = { - get: get77, + get: get72, } /** * Full value for one declared output of a published run. */ -export const get78 = oc +export const get73 = oc .route({ description: 'Full value for one declared output of a published run.', inputStructure: 'detailed', @@ -4339,7 +4128,7 @@ export const get78 = oc ) export const preview5 = { - get: get78, + get: get73, } export const byOutputName2 = { @@ -4349,7 +4138,7 @@ export const byOutputName2 = { /** * One node's declared outputs for a published workflow run. */ -export const get79 = oc +export const get74 = oc .route({ description: 'One node\'s declared outputs for a published workflow run.', inputStructure: 'detailed', @@ -4362,14 +4151,14 @@ export const get79 = oc .output(zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsByNodeIdResponse) export const byNodeId10 = { - get: get79, + get: get74, byOutputName: byOutputName2, } /** * Snapshot of every node's declared outputs for a published workflow run. */ -export const get80 = oc +export const get75 = oc .route({ description: 'Snapshot of every node\'s declared outputs for a published workflow run.', inputStructure: 'detailed', @@ -4382,7 +4171,7 @@ export const get80 = oc .output(zGetAppsByAppIdWorkflowsPublishedRunsByRunIdNodeOutputsResponse) export const nodeOutputs2 = { - get: get80, + get: get75, events: events2, byNodeId: byNodeId10, } @@ -4402,7 +4191,7 @@ export const published = { /** * Get webhook trigger for a node */ -export const get81 = oc +export const get76 = oc .route({ inputStructure: 'detailed', method: 'GET', @@ -4420,7 +4209,7 @@ export const get81 = oc .output(zGetAppsByAppIdWorkflowsTriggersWebhookResponse) export const webhook = { - get: get81, + get: get76, } export const triggers2 = { @@ -4430,7 +4219,7 @@ export const triggers2 = { /** * Restore a published workflow version into the draft workflow */ -export const post65 = oc +export const post62 = oc .route({ description: 'Restore a published workflow version into the draft workflow', inputStructure: 'detailed', @@ -4443,7 +4232,7 @@ export const post65 = oc .output(zPostAppsByAppIdWorkflowsByWorkflowIdRestoreResponse) export const restore = { - post: post65, + post: post62, } /** @@ -4496,7 +4285,7 @@ export const byWorkflowId = { * * Get all published workflows for an application */ -export const get82 = oc +export const get77 = oc .route({ description: 'Get all published workflows for an application', inputStructure: 'detailed', @@ -4515,7 +4304,7 @@ export const get82 = oc .output(zGetAppsByAppIdWorkflowsResponse) export const workflows3 = { - get: get82, + get: get77, defaultWorkflowBlockConfigs, draft: draft2, publish, @@ -4548,7 +4337,7 @@ export const delete15 = oc * * Get application details */ -export const get83 = oc +export const get78 = oc .route({ description: 'Get application details', inputStructure: 'detailed', @@ -4566,7 +4355,7 @@ export const get83 = oc * * Update application details */ -export const put7 = oc +export const put6 = oc .route({ description: 'Update application details', inputStructure: 'detailed', @@ -4581,13 +4370,9 @@ export const put7 = oc export const byAppId2 = { delete: delete15, - get: get83, - put: put7, + get: get78, + put: put6, advancedChat, - agentComposer, - agentFeatures, - agentReferencingWorkflows, - agentSandbox, agent, annotationReply, annotationSetting, @@ -4654,7 +4439,7 @@ export const byApiKeyId = { * * Get all API keys for an app */ -export const get84 = oc +export const get79 = oc .route({ description: 'Get all API keys for an app', inputStructure: 'detailed', @@ -4672,7 +4457,7 @@ export const get84 = oc * * Create a new API key for an app */ -export const post66 = oc +export const post63 = oc .route({ description: 'Create a new API key for an app', inputStructure: 'detailed', @@ -4687,8 +4472,8 @@ export const post66 = oc .output(zPostAppsByResourceIdApiKeysResponse) export const apiKeys = { - get: get84, - post: post66, + get: get79, + post: post63, byApiKeyId, } @@ -4699,7 +4484,7 @@ export const byResourceId = { /** * Refresh MCP server configuration and regenerate server code */ -export const get85 = oc +export const get80 = oc .route({ description: 'Refresh MCP server configuration and regenerate server code', inputStructure: 'detailed', @@ -4712,7 +4497,7 @@ export const get85 = oc .output(zGetAppsByServerIdServerRefreshResponse) export const refresh = { - get: get85, + get: get80, } export const server2 = { @@ -4728,7 +4513,7 @@ export const byServerId = { * * Get list of applications with pagination and filtering */ -export const get86 = oc +export const get81 = oc .route({ description: 'Get list of applications with pagination and filtering', inputStructure: 'detailed', @@ -4746,7 +4531,7 @@ export const get86 = oc * * Create a new application */ -export const post67 = oc +export const post64 = oc .route({ description: 'Create a new application', inputStructure: 'detailed', @@ -4761,8 +4546,8 @@ export const post67 = oc .output(zPostAppsResponse) export const apps = { - get: get86, - post: post67, + get: get81, + post: post64, imports, starred, workflows, diff --git a/packages/contracts/generated/api/console/apps/types.gen.ts b/packages/contracts/generated/api/console/apps/types.gen.ts index 4265c4843f..4db89cbe63 100644 --- a/packages/contracts/generated/api/console/apps/types.gen.ts +++ b/packages/contracts/generated/api/console/apps/types.gen.ts @@ -5,10 +5,10 @@ export type ClientOptions = { } export type AppPagination = { - has_next: boolean - items: Array + data: Array + has_more: boolean + limit: number page: number - per_page: number total: number } @@ -17,14 +17,13 @@ export type CreateAppPayload = { icon?: string | null icon_background?: string | null icon_type?: IconType | null - mode: 'advanced-chat' | 'agent' | 'agent-chat' | 'chat' | 'completion' | 'workflow' + mode: 'advanced-chat' | 'agent-chat' | 'chat' | 'completion' | 'workflow' name: string } export type AppDetailWithSite = { access_mode?: string | null api_base_url?: string | null - app_model_config?: ModelConfig | null bound_agent_id?: string | null created_at?: number | null created_by?: string | null @@ -35,9 +34,11 @@ export type AppDetailWithSite = { icon?: string | null icon_background?: string | null icon_type?: string | null + readonly icon_url: string | null id: string max_active_requests?: number | null - mode_compatible_with_agent: string + mode: string + model_config?: ModelConfig | null name: string site?: Site | null tags?: Array @@ -172,85 +173,6 @@ export type AdvancedChatWorkflowRunPayload = { query?: string } -export type AgentAppComposerResponse = { - active_config_snapshot: AgentConfigSnapshotSummaryResponse - agent: AgentComposerAgentResponse - agent_soul: AgentSoulConfig - save_options: Array - validation?: ComposerValidationFindingsResponse | null - variant: 'agent_app' -} - -export type ComposerSavePayload = { - agent_soul?: AgentSoulConfig | null - binding?: ComposerBindingPayload | null - client_revision_id?: string | null - idempotency_key?: string | null - new_agent_name?: string | null - node_job?: WorkflowNodeJobConfig | null - save_strategy: ComposerSaveStrategy - soul_lock?: ComposerSoulLockPayload - variant: ComposerVariant - version_note?: string | null -} - -export type AgentComposerCandidatesResponse = { - allowed_node_job_candidates?: AgentComposerNodeJobCandidatesResponse - allowed_soul_candidates?: AgentComposerSoulCandidatesResponse - capabilities?: ComposerCandidateCapabilities - truncated?: boolean - variant: ComposerVariant -} - -export type AgentComposerValidateResponse = { - errors?: Array - knowledge_retrieval_placeholder?: Array - result: 'success' - warnings?: Array -} - -export type AgentAppFeaturesPayload = { - opening_statement?: string | null - retriever_resource?: AgentFeatureToggleConfig | null - sensitive_word_avoidance?: AgentSensitiveWordAvoidanceFeatureConfig | null - speech_to_text?: AgentFeatureToggleConfig | null - suggested_questions?: Array | null - suggested_questions_after_answer?: AgentSuggestedQuestionsAfterAnswerFeatureConfig | null - text_to_speech?: AgentTextToSpeechFeatureConfig | null -} - -export type SimpleResultResponse = { - result: string -} - -export type AgentReferencingWorkflowsResponse = { - data?: Array -} - -export type SandboxListResponse = { - entries?: Array - path: string - truncated?: boolean -} - -export type SandboxReadResponse = { - binary: boolean - path: string - size?: number | null - text?: string | null - truncated: boolean -} - -export type AgentSandboxUploadPayload = { - conversation_id: string - path: string -} - -export type SandboxUploadResponse = { - file: SandboxToolFileResponse - path: string -} - export type AgentDriveListResponse = { items?: Array } @@ -442,6 +364,10 @@ export type SuggestedQuestionsResponse = { data: Array } +export type SimpleResultResponse = { + result: string +} + export type ConversationPagination = { has_next: boolean items: Array @@ -809,11 +735,30 @@ export type WorkflowRunNodeExecutionListResponse = { data: Array } +export type SandboxListResponse = { + entries?: Array + path: string + truncated?: boolean +} + +export type SandboxReadResponse = { + binary: boolean + path: string + size?: number | null + text?: string | null + truncated: boolean +} + export type WorkflowAgentSandboxUploadPayload = { node_execution_id?: string | null path: string } +export type SandboxUploadResponse = { + file: SandboxToolFileResponse + path: string +} + export type WorkflowCommentBasicList = { data: Array } @@ -1014,12 +959,40 @@ export type WorkflowAgentComposerResponse = { workflow_id?: string | null } +export type ComposerSavePayload = { + agent_soul?: AgentSoulConfig | null + binding?: ComposerBindingPayload | null + client_revision_id?: string | null + idempotency_key?: string | null + new_agent_name?: string | null + node_job?: WorkflowNodeJobConfig | null + save_strategy: ComposerSaveStrategy + soul_lock?: ComposerSoulLockPayload + variant: ComposerVariant + version_note?: string | null +} + +export type AgentComposerCandidatesResponse = { + allowed_node_job_candidates?: AgentComposerNodeJobCandidatesResponse + allowed_soul_candidates?: AgentComposerSoulCandidatesResponse + capabilities?: ComposerCandidateCapabilities + truncated?: boolean + variant: ComposerVariant +} + export type AgentComposerImpactResponse = { bindings?: Array current_snapshot_id?: string | null workflow_node_count: number } +export type AgentComposerValidateResponse = { + errors?: Array + knowledge_retrieval_placeholder?: Array + result: 'success' + warnings?: Array +} + export type WorkflowRunNodeExecutionResponse = { created_at?: number | null created_by_account?: SimpleAccount | null @@ -1180,20 +1153,22 @@ export type ApiKeyItem = { export type AppPartial = { access_mode?: string | null - app_model_config?: ModelConfigPartial | null author_name?: string | null + bound_agent_id?: string | null create_user_name?: string | null created_at?: number | null created_by?: string | null - desc_or_prompt?: string | null + description?: string | null has_draft_trigger?: boolean | null icon?: string | null icon_background?: string | null icon_type?: string | null + readonly icon_url: string | null id: string is_starred?: boolean max_active_requests?: number | null - mode_compatible_with_agent: string + mode: string + model_config?: ModelConfigPartial | null name: string tags?: Array updated_at?: number | null @@ -1204,6 +1179,12 @@ export type AppPartial = { export type IconType = 'emoji' | 'image' | 'link' +export type DeletedTool = { + provider_id: string + tool_name: string + type: string +} + export type ModelConfig = { completion_params?: { [key: string]: unknown @@ -1213,12 +1194,6 @@ export type ModelConfig = { provider: string } -export type DeletedTool = { - provider_id: string - tool_name: string - type: string -} - export type Site = { chat_color_theme?: string | null chat_color_theme_inverted: boolean @@ -1290,161 +1265,6 @@ export type AdvancedChatWorkflowRunForListResponse = { version?: string | null } -export type AgentConfigSnapshotSummaryResponse = { - agent_id?: string | null - created_at?: number | null - created_by?: string | null - id: string - summary?: string | null - version: number - version_note?: string | null -} - -export type AgentComposerAgentResponse = { - active_config_snapshot_id?: string | null - description: string - id: string - name: string - scope: AgentScope - status: AgentStatus -} - -export type AgentSoulConfig = { - app_features?: AgentSoulAppFeaturesConfig - app_variables?: Array - env?: AgentSoulEnvConfig - human?: AgentSoulHumanConfig - knowledge?: AgentSoulKnowledgeConfig - memory?: AgentSoulMemoryConfig - misc_legacy?: AgentSoulAppFeaturesConfig - model?: AgentSoulModelConfig | null - prompt?: AgentSoulPromptConfig - sandbox?: AgentSoulSandboxConfig - schema_version?: number - skills_files?: AgentSoulSkillsFilesConfig - tools?: AgentSoulToolsConfig -} - -export type ComposerSaveStrategy - = | 'node_job_only' - | 'save_as_new_agent' - | 'save_as_new_version' - | 'save_to_current_version' - | 'save_to_roster' - -export type ComposerValidationFindingsResponse = { - knowledge_retrieval_placeholder?: Array - warnings?: Array -} - -export type ComposerBindingPayload = { - agent_id?: string | null - binding_type: 'inline_agent' | 'roster_agent' - current_snapshot_id?: string | null -} - -export type WorkflowNodeJobConfig = { - declared_outputs?: Array - human_contacts?: Array - metadata?: WorkflowNodeJobMetadata - mode?: WorkflowNodeJobMode - previous_node_output_refs?: Array - schema_version?: number - workflow_prompt?: string -} - -export type ComposerSoulLockPayload = { - locked?: boolean - unlocked_from_version_id?: string | null -} - -export type ComposerVariant = 'agent_app' | 'workflow' - -export type AgentComposerNodeJobCandidatesResponse = { - declare_output_types?: Array - human_contacts?: Array - previous_node_outputs?: Array -} - -export type AgentComposerSoulCandidatesResponse = { - cli_tools?: Array - dify_tools?: Array - human_contacts?: Array - knowledge_datasets?: Array - skills_files?: Array< - | ({ - kind: 'skill' - } & AgentComposerSkillCandidateResponse) - | ({ - kind: 'file' - } & AgentComposerFileCandidateResponse) - > -} - -export type ComposerCandidateCapabilities = { - human_roster_available?: boolean -} - -export type ComposerKnowledgePlaceholderResponse = { - id: string - placeholder_name: string -} - -export type ComposerValidationWarningResponse = { - code: string - id?: string | null - kind?: string | null - message?: string | null - surface?: string | null -} - -export type AgentFeatureToggleConfig = { - enabled?: boolean - [key: string]: unknown -} - -export type AgentSensitiveWordAvoidanceFeatureConfig = { - config?: AgentModerationProviderConfig | null - enabled?: boolean - type?: string | null - [key: string]: unknown -} - -export type AgentSuggestedQuestionsAfterAnswerFeatureConfig = { - enabled?: boolean - model?: AgentSoulModelConfig | null - prompt?: string | null - [key: string]: unknown -} - -export type AgentTextToSpeechFeatureConfig = { - autoPlay?: string | null - enabled?: boolean - language?: string | null - voice?: string | null - [key: string]: unknown -} - -export type AgentReferencingWorkflowResponse = { - app_id: string - app_mode: string - app_name: string - node_ids?: Array - workflow_id: string -} - -export type SandboxFileEntryResponse = { - mtime?: number | null - name: string - size?: number | null - type: 'dir' | 'file' | 'other' | 'symlink' -} - -export type SandboxToolFileResponse = { - reference: string - transfer_method?: 'tool_file' -} - export type AgentDriveItemResponse = { created_at?: number | null file_kind: string @@ -1760,6 +1580,18 @@ export type SimpleEndUser = { type: string } +export type SandboxFileEntryResponse = { + mtime?: number | null + name: string + size?: number | null + type: 'dir' | 'file' | 'other' | 'symlink' +} + +export type SandboxToolFileResponse = { + reference: string + transfer_method?: 'tool_file' +} + export type WorkflowCommentBasic = { content: string created_at?: number | null @@ -1877,6 +1709,41 @@ export type EnvironmentVariableItemResponse = { visible: boolean } +export type AgentConfigSnapshotSummaryResponse = { + agent_id?: string | null + created_at?: number | null + created_by?: string | null + id: string + summary?: string | null + version: number + version_note?: string | null +} + +export type AgentComposerAgentResponse = { + active_config_snapshot_id?: string | null + description: string + id: string + name: string + scope: AgentScope + status: AgentStatus +} + +export type AgentSoulConfig = { + app_features?: AgentSoulAppFeaturesConfig + app_variables?: Array + env?: AgentSoulEnvConfig + human?: AgentSoulHumanConfig + knowledge?: AgentSoulKnowledgeConfig + memory?: AgentSoulMemoryConfig + misc_legacy?: AgentSoulAppFeaturesConfig + model?: AgentSoulModelConfig | null + prompt?: AgentSoulPromptConfig + sandbox?: AgentSoulSandboxConfig + schema_version?: number + skills_files?: AgentSoulSkillsFilesConfig + tools?: AgentSoulToolsConfig +} + export type AgentComposerBindingResponse = { agent_id?: string | null binding_type: WorkflowAgentBindingType @@ -1898,18 +1765,91 @@ export type DeclaredOutputConfig = { type: DeclaredOutputType } +export type WorkflowNodeJobConfig = { + declared_outputs?: Array + human_contacts?: Array + metadata?: WorkflowNodeJobMetadata + mode?: WorkflowNodeJobMode + previous_node_output_refs?: Array + schema_version?: number + workflow_prompt?: string +} + +export type ComposerSaveStrategy + = | 'node_job_only' + | 'save_as_new_agent' + | 'save_as_new_version' + | 'save_to_current_version' + | 'save_to_roster' + export type AgentComposerSoulLockResponse = { can_unlock?: boolean locked: boolean reason?: string | null } +export type ComposerValidationFindingsResponse = { + knowledge_retrieval_placeholder?: Array + warnings?: Array +} + +export type ComposerBindingPayload = { + agent_id?: string | null + binding_type: 'inline_agent' | 'roster_agent' + current_snapshot_id?: string | null +} + +export type ComposerSoulLockPayload = { + locked?: boolean + unlocked_from_version_id?: string | null +} + +export type ComposerVariant = 'agent_app' | 'workflow' + +export type AgentComposerNodeJobCandidatesResponse = { + declare_output_types?: Array + human_contacts?: Array + previous_node_outputs?: Array +} + +export type AgentComposerSoulCandidatesResponse = { + cli_tools?: Array + dify_tools?: Array + human_contacts?: Array + knowledge_datasets?: Array + skills_files?: Array< + | ({ + kind: 'skill' + } & AgentComposerSkillCandidateResponse) + | ({ + kind: 'file' + } & AgentComposerFileCandidateResponse) + > +} + +export type ComposerCandidateCapabilities = { + human_roster_available?: boolean +} + export type AgentComposerImpactBindingResponse = { app_id: string node_id: string workflow_id: string } +export type ComposerKnowledgePlaceholderResponse = { + id: string + placeholder_name: string +} + +export type ComposerValidationWarningResponse = { + code: string + id?: string | null + kind?: string | null + message?: string | null + surface?: string | null +} + export type WorkflowExecutionStatus = | 'failed' | 'partial-succeeded' @@ -1957,7 +1897,7 @@ export type WorkflowDraftVariableWithoutValue = { export type ModelConfigPartial = { created_at?: number | null created_by?: string | null - model_dict?: JsonValue | null + model?: JsonValue | null pre_prompt?: string | null updated_at?: number | null updated_by?: string | null @@ -1990,6 +1930,101 @@ export type WorkflowOnlineUser = { username: string } +export type AgentToolCallResponse = { + error?: string | null + status: string + time_cost: number | number + tool_icon?: unknown + tool_input: { + [key: string]: unknown + } + tool_label: string + tool_name: string + tool_output: { + [key: string]: unknown + } + tool_parameters: { + [key: string]: unknown + } +} + +export type EnvSuggestion = { + key: string + reason?: string + secret_likely?: boolean +} + +export type SimpleModelConfig = { + model_dict?: JsonValue | null + pre_prompt?: string | null +} + +export type StatusCount = { + failed: number + partial_success: number + paused: number + success: number +} + +export type SimpleMessageDetail = { + answer: string + inputs: { + [key: string]: JsonValue + } + message: string + query: string +} + +export type HumanInputFormDefinition = { + actions?: Array + display_in_ui?: boolean + expiration_time: number + form_content: string + form_id: string + form_token?: string | null + inputs?: Array + node_id: string + node_title: string + resolved_default_values?: { + [key: string]: unknown + } +} + +export type HumanInputFormSubmissionData = { + action_id: string + action_text: string + node_id: string + node_title: string + rendered_content: string + submitted_data?: { + [key: string]: JsonValue2 + } | null +} + +export type ExecutionContentType = 'human_input' + +export type WorkflowRunForLogResponse = { + created_at?: number | null + elapsed_time?: number | null + error?: string | null + exceptions_count?: number | null + finished_at?: number | null + id: string + status?: string | null + total_steps?: number | null + total_tokens?: number | null + triggered_from?: string | null + version?: string | null +} + +export type WorkflowRunForArchivedLogResponse = { + elapsed_time?: number | null + id: string + status?: string | null + total_tokens?: number | null + triggered_from?: string | null +} + export type AgentScope = 'roster' | 'workflow_only' export type AgentStatus = 'active' | 'archived' @@ -2061,6 +2096,31 @@ export type AgentSoulToolsConfig = { dify_tools?: Array } +export type WorkflowAgentBindingType = 'inline_agent' | 'roster_agent' + +export type DeclaredArrayItem = { + description?: string | null + type: DeclaredOutputType +} + +export type DeclaredOutputCheckConfig = { + benchmark_file_ref?: AgentFileRefConfig | null + enabled?: boolean + model_ref?: AgentSoulModelConfig | null + prompt?: string | null +} + +export type DeclaredOutputFailureStrategy = { + default_value?: unknown + on_failure?: OutputErrorStrategy + retry?: DeclaredOutputRetryConfig +} + +export type DeclaredOutputFileConfig = { + extensions?: Array + mime_types?: Array +} + export type AgentHumanContactConfig = { channel?: string | null contact_id?: string | null @@ -2175,139 +2235,60 @@ export type AgentComposerFileCandidateResponse = { [key: string]: unknown } -export type AgentModerationProviderConfig = { - api_based_extension_id?: string | null - inputs_config?: AgentModerationIoConfig | null - keywords?: string | null - outputs_config?: AgentModerationIoConfig | null - [key: string]: unknown -} - -export type AgentToolCallResponse = { - error?: string | null - status: string - time_cost: number | number - tool_icon?: unknown - tool_input: { - [key: string]: unknown - } - tool_label: string - tool_name: string - tool_output: { - [key: string]: unknown - } - tool_parameters: { - [key: string]: unknown - } -} - -export type EnvSuggestion = { - key: string - reason?: string - secret_likely?: boolean -} - -export type SimpleModelConfig = { - model_dict?: JsonValue | null - pre_prompt?: string | null -} - -export type StatusCount = { - failed: number - partial_success: number - paused: number - success: number -} - -export type SimpleMessageDetail = { - answer: string - inputs: { - [key: string]: JsonValue - } - message: string - query: string -} - -export type HumanInputFormDefinition = { - actions?: Array - display_in_ui?: boolean - expiration_time: number - form_content: string - form_id: string - form_token?: string | null - inputs?: Array - node_id: string - node_title: string - resolved_default_values?: { - [key: string]: unknown - } -} - -export type HumanInputFormSubmissionData = { - action_id: string - action_text: string - node_id: string - node_title: string - rendered_content: string - submitted_data?: { - [key: string]: JsonValue2 - } | null -} - -export type ExecutionContentType = 'human_input' - -export type WorkflowRunForLogResponse = { - created_at?: number | null - elapsed_time?: number | null - error?: string | null - exceptions_count?: number | null - finished_at?: number | null - id: string - status?: string | null - total_steps?: number | null - total_tokens?: number | null - triggered_from?: string | null - version?: string | null -} - -export type WorkflowRunForArchivedLogResponse = { - elapsed_time?: number | null - id: string - status?: string | null - total_tokens?: number | null - triggered_from?: string | null -} - -export type WorkflowAgentBindingType = 'inline_agent' | 'roster_agent' - -export type DeclaredArrayItem = { - description?: string | null - type: DeclaredOutputType -} - -export type DeclaredOutputCheckConfig = { - benchmark_file_ref?: AgentFileRefConfig | null - enabled?: boolean - model_ref?: AgentSoulModelConfig | null - prompt?: string | null -} - -export type DeclaredOutputFailureStrategy = { - default_value?: unknown - on_failure?: OutputErrorStrategy - retry?: DeclaredOutputRetryConfig -} - -export type DeclaredOutputFileConfig = { - extensions?: Array - mime_types?: Array -} - export type CheckResultView = { passed: boolean reason?: string | null } +export type UserActionConfig = { + button_style?: ButtonStyle + id: string + title: string +} + +export type FormInputConfig + = | ({ + type: 'paragraph' + } & ParagraphInputConfig) + | ({ + type: 'select' + } & SelectInputConfig) + | ({ + type: 'file' + } & FileInputConfig) + | ({ + type: 'file-list' + } & FileListInputConfig) + +export type JsonValue2 = unknown + +export type AgentFeatureToggleConfig = { + enabled?: boolean + [key: string]: unknown +} + +export type AgentSensitiveWordAvoidanceFeatureConfig = { + config?: AgentModerationProviderConfig | null + enabled?: boolean + type?: string | null + [key: string]: unknown +} + +export type AgentSuggestedQuestionsAfterAnswerFeatureConfig = { + enabled?: boolean + model?: AgentSoulModelConfig | null + prompt?: string | null + [key: string]: unknown +} + +export type AgentTextToSpeechFeatureConfig = { + autoPlay?: string | null + enabled?: boolean + language?: string | null + voice?: string | null + [key: string]: unknown +} + export type AgentSecretRefConfig = { credential_id?: string | null env_name?: string | null @@ -2443,6 +2424,14 @@ export type AgentSoulDifyToolConfig = { tool_name?: string | null } +export type OutputErrorStrategy = 'default_value' | 'fail_branch' | 'stop' + +export type DeclaredOutputRetryConfig = { + enabled?: boolean + max_retries?: number + retry_interval_ms?: number +} + export type AgentCliToolAuthorizationStatus = | 'allowed' | 'authorized' @@ -2466,53 +2455,6 @@ export type AgentPermissionConfig = { export type AgentCliToolRiskLevel = 'dangerous' | 'safe' | 'unknown' -export type AgentModerationIoConfig = { - enabled?: boolean - preset_response?: string | null - [key: string]: unknown -} - -export type UserActionConfig = { - button_style?: ButtonStyle - id: string - title: string -} - -export type FormInputConfig - = | ({ - type: 'paragraph' - } & ParagraphInputConfig) - | ({ - type: 'select' - } & SelectInputConfig) - | ({ - type: 'file' - } & FileInputConfig) - | ({ - type: 'file-list' - } & FileListInputConfig) - -export type JsonValue2 = unknown - -export type OutputErrorStrategy = 'default_value' | 'fail_branch' | 'stop' - -export type DeclaredOutputRetryConfig = { - enabled?: boolean - max_retries?: number - retry_interval_ms?: number -} - -export type AgentModelResponseFormatConfig = { - type?: string | null - [key: string]: unknown -} - -export type AgentSoulDifyToolCredentialRef = { - id?: string | null - provider?: string | null - type?: 'provider' | 'tool' -} - export type ButtonStyle = 'accent' | 'default' | 'ghost' | 'primary' export type ParagraphInputConfig = { @@ -2544,6 +2486,25 @@ export type FileListInputConfig = { type?: 'file-list' } +export type AgentModerationProviderConfig = { + api_based_extension_id?: string | null + inputs_config?: AgentModerationIoConfig | null + keywords?: string | null + outputs_config?: AgentModerationIoConfig | null + [key: string]: unknown +} + +export type AgentModelResponseFormatConfig = { + type?: string | null + [key: string]: unknown +} + +export type AgentSoulDifyToolCredentialRef = { + id?: string | null + provider?: string | null + type?: 'provider' | 'tool' +} + export type StringSource = { selector?: Array type: ValueSourceType @@ -2560,12 +2521,25 @@ export type FileType = 'audio' | 'custom' | 'document' | 'image' | 'video' export type FileTransferMethod = 'datasource_file' | 'local_file' | 'remote_url' | 'tool_file' +export type AgentModerationIoConfig = { + enabled?: boolean + preset_response?: string | null + [key: string]: unknown +} + export type ValueSourceType = 'constant' | 'variable' +export type AppPaginationWritable = { + data: Array + has_more: boolean + limit: number + page: number + total: number +} + export type AppDetailWithSiteWritable = { access_mode?: string | null api_base_url?: string | null - app_model_config?: ModelConfig | null bound_agent_id?: string | null created_at?: number | null created_by?: string | null @@ -2578,7 +2552,8 @@ export type AppDetailWithSiteWritable = { icon_type?: string | null id: string max_active_requests?: number | null - mode_compatible_with_agent: string + mode: string + model_config?: ModelConfig | null name: string site?: SiteWritable | null tags?: Array @@ -2612,6 +2587,31 @@ export type WorkflowCommentDetailWritable = { updated_at?: number | null } +export type AppPartialWritable = { + access_mode?: string | null + author_name?: string | null + bound_agent_id?: string | null + create_user_name?: string | null + created_at?: number | null + created_by?: string | null + description?: string | null + has_draft_trigger?: boolean | null + icon?: string | null + icon_background?: string | null + icon_type?: string | null + id: string + is_starred?: boolean + max_active_requests?: number | null + mode: string + model_config?: ModelConfigPartial | null + name: string + tags?: Array + updated_at?: number | null + updated_by?: string | null + use_icon_as_answer_icon?: boolean | null + workflow?: WorkflowPartial | null +} + export type SiteWritable = { chat_color_theme?: string | null chat_color_theme_inverted: boolean @@ -3011,165 +3011,6 @@ export type PostAppsByAppIdAdvancedChatWorkflowsDraftRunResponses = { export type PostAppsByAppIdAdvancedChatWorkflowsDraftRunResponse = PostAppsByAppIdAdvancedChatWorkflowsDraftRunResponses[keyof PostAppsByAppIdAdvancedChatWorkflowsDraftRunResponses] -export type GetAppsByAppIdAgentComposerData = { - body?: never - path: { - app_id: string - } - query?: never - url: '/apps/{app_id}/agent-composer' -} - -export type GetAppsByAppIdAgentComposerResponses = { - 200: AgentAppComposerResponse -} - -export type GetAppsByAppIdAgentComposerResponse - = GetAppsByAppIdAgentComposerResponses[keyof GetAppsByAppIdAgentComposerResponses] - -export type PutAppsByAppIdAgentComposerData = { - body: ComposerSavePayload - path: { - app_id: string - } - query?: never - url: '/apps/{app_id}/agent-composer' -} - -export type PutAppsByAppIdAgentComposerResponses = { - 200: AgentAppComposerResponse -} - -export type PutAppsByAppIdAgentComposerResponse - = PutAppsByAppIdAgentComposerResponses[keyof PutAppsByAppIdAgentComposerResponses] - -export type GetAppsByAppIdAgentComposerCandidatesData = { - body?: never - path: { - app_id: string - } - query?: never - url: '/apps/{app_id}/agent-composer/candidates' -} - -export type GetAppsByAppIdAgentComposerCandidatesResponses = { - 200: AgentComposerCandidatesResponse -} - -export type GetAppsByAppIdAgentComposerCandidatesResponse - = GetAppsByAppIdAgentComposerCandidatesResponses[keyof GetAppsByAppIdAgentComposerCandidatesResponses] - -export type PostAppsByAppIdAgentComposerValidateData = { - body: ComposerSavePayload - path: { - app_id: string - } - query?: never - url: '/apps/{app_id}/agent-composer/validate' -} - -export type PostAppsByAppIdAgentComposerValidateResponses = { - 200: AgentComposerValidateResponse -} - -export type PostAppsByAppIdAgentComposerValidateResponse - = PostAppsByAppIdAgentComposerValidateResponses[keyof PostAppsByAppIdAgentComposerValidateResponses] - -export type PostAppsByAppIdAgentFeaturesData = { - body: AgentAppFeaturesPayload - path: { - app_id: string - } - query?: never - url: '/apps/{app_id}/agent-features' -} - -export type PostAppsByAppIdAgentFeaturesErrors = { - 400: unknown - 404: unknown -} - -export type PostAppsByAppIdAgentFeaturesResponses = { - 200: SimpleResultResponse -} - -export type PostAppsByAppIdAgentFeaturesResponse - = PostAppsByAppIdAgentFeaturesResponses[keyof PostAppsByAppIdAgentFeaturesResponses] - -export type GetAppsByAppIdAgentReferencingWorkflowsData = { - body?: never - path: { - app_id: string - } - query?: never - url: '/apps/{app_id}/agent-referencing-workflows' -} - -export type GetAppsByAppIdAgentReferencingWorkflowsErrors = { - 404: unknown -} - -export type GetAppsByAppIdAgentReferencingWorkflowsResponses = { - 200: AgentReferencingWorkflowsResponse -} - -export type GetAppsByAppIdAgentReferencingWorkflowsResponse - = GetAppsByAppIdAgentReferencingWorkflowsResponses[keyof GetAppsByAppIdAgentReferencingWorkflowsResponses] - -export type GetAppsByAppIdAgentSandboxFilesData = { - body?: never - path: { - app_id: string - } - query: { - conversation_id: string - path?: string - } - url: '/apps/{app_id}/agent-sandbox/files' -} - -export type GetAppsByAppIdAgentSandboxFilesResponses = { - 200: SandboxListResponse -} - -export type GetAppsByAppIdAgentSandboxFilesResponse - = GetAppsByAppIdAgentSandboxFilesResponses[keyof GetAppsByAppIdAgentSandboxFilesResponses] - -export type GetAppsByAppIdAgentSandboxFilesReadData = { - body?: never - path: { - app_id: string - } - query: { - conversation_id: string - path: string - } - url: '/apps/{app_id}/agent-sandbox/files/read' -} - -export type GetAppsByAppIdAgentSandboxFilesReadResponses = { - 200: SandboxReadResponse -} - -export type GetAppsByAppIdAgentSandboxFilesReadResponse - = GetAppsByAppIdAgentSandboxFilesReadResponses[keyof GetAppsByAppIdAgentSandboxFilesReadResponses] - -export type PostAppsByAppIdAgentSandboxFilesUploadData = { - body: AgentSandboxUploadPayload - path: { - app_id: string - } - query?: never - url: '/apps/{app_id}/agent-sandbox/files/upload' -} - -export type PostAppsByAppIdAgentSandboxFilesUploadResponses = { - 200: SandboxUploadResponse -} - -export type PostAppsByAppIdAgentSandboxFilesUploadResponse - = PostAppsByAppIdAgentSandboxFilesUploadResponses[keyof PostAppsByAppIdAgentSandboxFilesUploadResponses] - export type GetAppsByAppIdAgentDriveFilesData = { body?: never path: { diff --git a/packages/contracts/generated/api/console/apps/zod.gen.ts b/packages/contracts/generated/api/console/apps/zod.gen.ts index ebc87ce2c7..72dd269231 100644 --- a/packages/contracts/generated/api/console/apps/zod.gen.ts +++ b/packages/contracts/generated/api/console/apps/zod.gen.ts @@ -98,32 +98,6 @@ export const zAdvancedChatWorkflowRunPayload = z.object({ query: z.string().optional().default(''), }) -/** - * SimpleResultResponse - */ -export const zSimpleResultResponse = z.object({ - result: z.string(), -}) - -/** - * SandboxReadResponse - */ -export const zSandboxReadResponse = z.object({ - binary: z.boolean(), - path: z.string(), - size: z.int().nullish(), - text: z.string().nullish(), - truncated: z.boolean(), -}) - -/** - * AgentSandboxUploadPayload - */ -export const zAgentSandboxUploadPayload = z.object({ - conversation_id: z.string().min(1), - path: z.string().min(1), -}) - /** * AgentDriveDownloadResponse */ @@ -262,6 +236,13 @@ export const zSuggestedQuestionsResponse = z.object({ data: z.array(z.string()), }) +/** + * SimpleResultResponse + */ +export const zSimpleResultResponse = z.object({ + result: z.string(), +}) + /** * CompletionMessagePayload */ @@ -511,6 +492,17 @@ export const zWorkflowRunExportResponse = z.object({ status: z.string(), }) +/** + * SandboxReadResponse + */ +export const zSandboxReadResponse = z.object({ + binary: z.boolean(), + path: z.string(), + size: z.int().nullish(), + text: z.string().nullish(), + truncated: z.boolean(), +}) + /** * WorkflowAgentSandboxUploadPayload */ @@ -797,7 +789,7 @@ export const zCreateAppPayload = z.object({ icon: z.string().nullish(), icon_background: z.string().nullish(), icon_type: zIconType.nullish(), - mode: z.enum(['advanced-chat', 'agent', 'agent-chat', 'chat', 'completion', 'workflow']), + mode: z.enum(['advanced-chat', 'agent-chat', 'chat', 'completion', 'workflow']), name: z.string().min(1), }) @@ -917,166 +909,6 @@ export const zImport = z.object({ status: zImportStatus, }) -/** - * AgentConfigSnapshotSummaryResponse - */ -export const zAgentConfigSnapshotSummaryResponse = z.object({ - agent_id: z.string().nullish(), - created_at: z.int().nullish(), - created_by: z.string().nullish(), - id: z.string(), - summary: z.string().nullish(), - version: z.int(), - version_note: z.string().nullish(), -}) - -/** - * ComposerSaveStrategy - */ -export const zComposerSaveStrategy = z.enum([ - 'node_job_only', - 'save_as_new_agent', - 'save_as_new_version', - 'save_to_current_version', - 'save_to_roster', -]) - -/** - * ComposerBindingPayload - */ -export const zComposerBindingPayload = z.object({ - agent_id: z.string().nullish(), - binding_type: z.enum(['inline_agent', 'roster_agent']), - current_snapshot_id: z.string().nullish(), -}) - -/** - * ComposerSoulLockPayload - */ -export const zComposerSoulLockPayload = z.object({ - locked: z.boolean().optional().default(true), - unlocked_from_version_id: z.string().nullish(), -}) - -/** - * ComposerVariant - */ -export const zComposerVariant = z.enum(['agent_app', 'workflow']) - -/** - * ComposerCandidateCapabilities - */ -export const zComposerCandidateCapabilities = z.object({ - human_roster_available: z.boolean().optional().default(false), -}) - -/** - * ComposerKnowledgePlaceholderResponse - */ -export const zComposerKnowledgePlaceholderResponse = z.object({ - id: z.string(), - placeholder_name: z.string(), -}) - -/** - * ComposerValidationWarningResponse - */ -export const zComposerValidationWarningResponse = z.object({ - code: z.string(), - id: z.string().nullish(), - kind: z.string().nullish(), - message: z.string().nullish(), - surface: z.string().nullish(), -}) - -/** - * AgentComposerValidateResponse - */ -export const zAgentComposerValidateResponse = z.object({ - errors: z.array(z.string()).optional(), - knowledge_retrieval_placeholder: z.array(zComposerKnowledgePlaceholderResponse).optional(), - result: z.literal('success'), - warnings: z.array(zComposerValidationWarningResponse).optional(), -}) - -/** - * ComposerValidationFindingsResponse - */ -export const zComposerValidationFindingsResponse = z.object({ - knowledge_retrieval_placeholder: z.array(zComposerKnowledgePlaceholderResponse).optional(), - warnings: z.array(zComposerValidationWarningResponse).optional(), -}) - -/** - * AgentFeatureToggleConfig - */ -export const zAgentFeatureToggleConfig = z.object({ - enabled: z.boolean().optional().default(false), -}) - -/** - * AgentTextToSpeechFeatureConfig - */ -export const zAgentTextToSpeechFeatureConfig = z.object({ - autoPlay: z.string().nullish(), - enabled: z.boolean().optional().default(false), - language: z.string().nullish(), - voice: z.string().nullish(), -}) - -/** - * AgentReferencingWorkflowResponse - */ -export const zAgentReferencingWorkflowResponse = z.object({ - app_id: z.string(), - app_mode: z.string(), - app_name: z.string(), - node_ids: z.array(z.string()).optional(), - workflow_id: z.string(), -}) - -/** - * AgentReferencingWorkflowsResponse - */ -export const zAgentReferencingWorkflowsResponse = z.object({ - data: z.array(zAgentReferencingWorkflowResponse).optional(), -}) - -/** - * SandboxFileEntryResponse - */ -export const zSandboxFileEntryResponse = z.object({ - mtime: z.int().nullish(), - name: z.string(), - size: z.int().nullish(), - type: z.enum(['dir', 'file', 'other', 'symlink']), -}) - -/** - * SandboxListResponse - */ -export const zSandboxListResponse = z.object({ - entries: z.array(zSandboxFileEntryResponse).optional(), - path: z.string(), - truncated: z.boolean().optional().default(false), -}) - -/** - * SandboxToolFileResponse - */ -export const zSandboxToolFileResponse = z.object({ - reference: z.string(), - transfer_method: z.literal('tool_file').optional().default('tool_file'), -}) - -/** - * SandboxUploadResponse - */ -export const zSandboxUploadResponse = z.object({ - file: zSandboxToolFileResponse, - path: z.string(), -}) - /** * AgentDriveItemResponse */ @@ -1614,6 +1446,41 @@ export const zWorkflowRunNodeExecutionListResponse = z.object({ data: z.array(zWorkflowRunNodeExecutionResponse), }) +/** + * SandboxFileEntryResponse + */ +export const zSandboxFileEntryResponse = z.object({ + mtime: z.int().nullish(), + name: z.string(), + size: z.int().nullish(), + type: z.enum(['dir', 'file', 'other', 'symlink']), +}) + +/** + * SandboxListResponse + */ +export const zSandboxListResponse = z.object({ + entries: z.array(zSandboxFileEntryResponse).optional(), + path: z.string(), + truncated: z.boolean().optional().default(false), +}) + +/** + * SandboxToolFileResponse + */ +export const zSandboxToolFileResponse = z.object({ + reference: z.string(), + transfer_method: z.literal('tool_file').optional().default('tool_file'), +}) + +/** + * SandboxUploadResponse + */ +export const zSandboxUploadResponse = z.object({ + file: zSandboxToolFileResponse, + path: z.string(), +}) + /** * AccountWithRole */ @@ -1870,6 +1737,30 @@ export const zEnvironmentVariableListResponse = z.object({ items: z.array(zEnvironmentVariableItemResponse), }) +/** + * AgentConfigSnapshotSummaryResponse + */ +export const zAgentConfigSnapshotSummaryResponse = z.object({ + agent_id: z.string().nullish(), + created_at: z.int().nullish(), + created_by: z.string().nullish(), + id: z.string(), + summary: z.string().nullish(), + version: z.int(), + version_note: z.string().nullish(), +}) + +/** + * ComposerSaveStrategy + */ +export const zComposerSaveStrategy = z.enum([ + 'node_job_only', + 'save_as_new_agent', + 'save_as_new_version', + 'save_to_current_version', + 'save_to_roster', +]) + /** * AgentComposerSoulLockResponse */ @@ -1879,6 +1770,35 @@ export const zAgentComposerSoulLockResponse = z.object({ reason: z.string().nullish(), }) +/** + * ComposerBindingPayload + */ +export const zComposerBindingPayload = z.object({ + agent_id: z.string().nullish(), + binding_type: z.enum(['inline_agent', 'roster_agent']), + current_snapshot_id: z.string().nullish(), +}) + +/** + * ComposerSoulLockPayload + */ +export const zComposerSoulLockPayload = z.object({ + locked: z.boolean().optional().default(true), + unlocked_from_version_id: z.string().nullish(), +}) + +/** + * ComposerVariant + */ +export const zComposerVariant = z.enum(['agent_app', 'workflow']) + +/** + * ComposerCandidateCapabilities + */ +export const zComposerCandidateCapabilities = z.object({ + human_roster_available: z.boolean().optional().default(false), +}) + /** * AgentComposerImpactBindingResponse */ @@ -1897,6 +1817,43 @@ export const zAgentComposerImpactResponse = z.object({ workflow_node_count: z.int(), }) +/** + * ComposerKnowledgePlaceholderResponse + */ +export const zComposerKnowledgePlaceholderResponse = z.object({ + id: z.string(), + placeholder_name: z.string(), +}) + +/** + * ComposerValidationWarningResponse + */ +export const zComposerValidationWarningResponse = z.object({ + code: z.string(), + id: z.string().nullish(), + kind: z.string().nullish(), + message: z.string().nullish(), + surface: z.string().nullish(), +}) + +/** + * AgentComposerValidateResponse + */ +export const zAgentComposerValidateResponse = z.object({ + errors: z.array(z.string()).optional(), + knowledge_retrieval_placeholder: z.array(zComposerKnowledgePlaceholderResponse).optional(), + result: z.literal('success'), + warnings: z.array(zComposerValidationWarningResponse).optional(), +}) + +/** + * ComposerValidationFindingsResponse + */ +export const zComposerValidationFindingsResponse = z.object({ + knowledge_retrieval_placeholder: z.array(zComposerKnowledgePlaceholderResponse).optional(), + warnings: z.array(zComposerValidationWarningResponse).optional(), +}) + /** * WorkflowExecutionStatus */ @@ -1978,7 +1935,7 @@ export const zWorkflowDraftVariableListWithoutValue = z.object({ export const zModelConfigPartial = z.object({ created_at: z.int().nullish(), created_by: z.string().nullish(), - model_dict: zJsonValue.nullish(), + model: zJsonValue.nullish(), pre_prompt: z.string().nullish(), updated_at: z.int().nullish(), updated_by: z.string().nullish(), @@ -1989,20 +1946,22 @@ export const zModelConfigPartial = z.object({ */ export const zAppPartial = z.object({ access_mode: z.string().nullish(), - app_model_config: zModelConfigPartial.nullish(), author_name: z.string().nullish(), + bound_agent_id: z.string().nullish(), create_user_name: z.string().nullish(), created_at: z.int().nullish(), created_by: z.string().nullish(), - desc_or_prompt: z.string().nullish(), + description: z.string().nullish(), has_draft_trigger: z.boolean().nullish(), icon: z.string().nullish(), icon_background: z.string().nullish(), icon_type: z.string().nullish(), + icon_url: z.string().nullable(), id: z.string(), is_starred: z.boolean().optional().default(false), max_active_requests: z.int().nullish(), - mode_compatible_with_agent: z.string(), + mode: z.string(), + model_config: zModelConfigPartial.nullish(), name: z.string(), tags: z.array(zTag).optional(), updated_at: z.int().nullish(), @@ -2015,10 +1974,10 @@ export const zAppPartial = z.object({ * AppPagination */ export const zAppPagination = z.object({ - has_next: z.boolean(), - items: z.array(zAppPartial), + data: z.array(zAppPartial), + has_more: z.boolean(), + limit: z.int(), page: z.int(), - per_page: z.int(), total: z.int(), }) @@ -2045,7 +2004,6 @@ export const zModelConfig = z.object({ export const zAppDetailWithSite = z.object({ access_mode: z.string().nullish(), api_base_url: z.string().nullish(), - app_model_config: zModelConfig.nullish(), bound_agent_id: z.string().nullish(), created_at: z.int().nullish(), created_by: z.string().nullish(), @@ -2056,9 +2014,11 @@ export const zAppDetailWithSite = z.object({ icon: z.string().nullish(), icon_background: z.string().nullish(), icon_type: z.string().nullish(), + icon_url: z.string().nullable(), id: z.string(), max_active_requests: z.int().nullish(), - mode_compatible_with_agent: z.string(), + mode: z.string(), + model_config: zModelConfig.nullish(), name: z.string(), site: zSite.nullish(), tags: z.array(zTag).optional(), @@ -2197,154 +2157,6 @@ export const zWorkflowOnlineUsersResponse = z.object({ data: z.array(zWorkflowOnlineUsersByApp), }) -/** - * AgentScope - * - * Visibility and lifecycle scope of an Agent record. - */ -export const zAgentScope = z.enum(['roster', 'workflow_only']) - -/** - * AgentStatus - * - * Soft lifecycle state for Agent records. - */ -export const zAgentStatus = z.enum(['active', 'archived']) - -/** - * AgentComposerAgentResponse - */ -export const zAgentComposerAgentResponse = z.object({ - active_config_snapshot_id: z.string().nullish(), - description: z.string(), - id: z.string(), - name: z.string(), - scope: zAgentScope, - status: zAgentStatus, -}) - -/** - * AppVariableConfig - */ -export const zAppVariableConfig = z.object({ - default: z.unknown().optional(), - name: z.string().min(1).max(255), - required: z.boolean().optional().default(false), - type: z.string().min(1).max(64), -}) - -/** - * AgentSoulPromptConfig - */ -export const zAgentSoulPromptConfig = z.object({ - system_prompt: z.string().optional().default(''), -}) - -/** - * AgentHumanContactConfig - */ -export const zAgentHumanContactConfig = z.object({ - channel: z.string().max(64).nullish(), - contact_id: z.string().max(255).nullish(), - contact_method: z.string().max(64).nullish(), - email: z.string().max(255).nullish(), - human_id: z.string().max(255).nullish(), - id: z.string().max(255).nullish(), - method: z.string().max(64).nullish(), - name: z.string().max(255).nullish(), - tenant_id: z.string().max(255).nullish(), -}) - -/** - * WorkflowNodeJobMode - */ -export const zWorkflowNodeJobMode = z.enum(['let_agent_figure_it_out', 'tell_agent_what_to_do']) - -/** - * WorkflowPreviousNodeOutputRef - */ -export const zWorkflowPreviousNodeOutputRef = z.object({ - key: z.string().max(255).nullish(), - name: z.string().max(255).nullish(), - node_id: z.string().max(255).nullish(), - output: z.string().max(255).nullish(), - selector: z.array(z.union([z.string(), z.int(), z.number(), z.boolean(), z.null()])).nullish(), - value_selector: z - .array(z.union([z.string(), z.int(), z.number(), z.boolean(), z.null()])) - .nullish(), - variable: z.string().max(255).nullish(), - variable_selector: z - .array(z.union([z.string(), z.int(), z.number(), z.boolean(), z.null()])) - .nullish(), -}) - -/** - * AgentComposerNodeJobCandidatesResponse - */ -export const zAgentComposerNodeJobCandidatesResponse = z.object({ - declare_output_types: z.array(zDeclaredOutputType).optional(), - human_contacts: z.array(zAgentHumanContactConfig).optional(), - previous_node_outputs: z.array(zWorkflowPreviousNodeOutputRef).optional(), -}) - -/** - * AgentComposerDifyToolCandidateResponse - */ -export const zAgentComposerDifyToolCandidateResponse = z.object({ - description: z.string().nullish(), - granularity: z.string().nullish(), - id: z.string().nullish(), - name: z.string().nullish(), - plugin_id: z.string().nullish(), - provider: z.string().nullish(), - provider_id: z.string().nullish(), - tools_count: z.int().nullish(), -}) - -/** - * AgentKnowledgeDatasetConfig - */ -export const zAgentKnowledgeDatasetConfig = z.object({ - description: z.string().nullish(), - id: z.string().max(255).nullish(), - name: z.string().max(255).nullish(), -}) - -/** - * AgentComposerSkillCandidateResponse - */ -export const zAgentComposerSkillCandidateResponse = z.object({ - description: z.string().nullish(), - file_id: z.string().max(255).nullish(), - full_archive_file_id: z.string().max(255).nullish(), - full_archive_key: z.string().max(512).nullish(), - id: z.string().max(255).nullish(), - kind: z.literal('skill').optional().default('skill'), - manifest_files: z.array(z.string()).nullish(), - name: z.string().max(255).nullish(), - path: z.string().nullish(), - skill_md_file_id: z.string().max(255).nullish(), - skill_md_key: z.string().max(512).nullish(), -}) - -/** - * AgentComposerFileCandidateResponse - */ -export const zAgentComposerFileCandidateResponse = z.object({ - drive_key: z.string().max(512).nullish(), - file_id: z.string().max(255).nullish(), - id: z.string().max(255).nullish(), - kind: z.literal('file').optional().default('file'), - name: z.string().max(255).nullish(), - reference: z.string().max(255).nullish(), - remote_url: z.string().nullish(), - tenant_id: z.string().max(255).nullish(), - transfer_method: z.string().max(64).nullish(), - type: z.string().max(64).nullish(), - upload_file_id: z.string().max(255).nullish(), - url: z.string().nullish(), -}) - /** * AgentToolCallResponse */ @@ -2587,6 +2399,49 @@ export const zWorkflowArchivedLogPaginationResponse = z.object({ total: z.int(), }) +/** + * AgentScope + * + * Visibility and lifecycle scope of an Agent record. + */ +export const zAgentScope = z.enum(['roster', 'workflow_only']) + +/** + * AgentStatus + * + * Soft lifecycle state for Agent records. + */ +export const zAgentStatus = z.enum(['active', 'archived']) + +/** + * AgentComposerAgentResponse + */ +export const zAgentComposerAgentResponse = z.object({ + active_config_snapshot_id: z.string().nullish(), + description: z.string(), + id: z.string(), + name: z.string(), + scope: zAgentScope, + status: zAgentStatus, +}) + +/** + * AppVariableConfig + */ +export const zAppVariableConfig = z.object({ + default: z.unknown().optional(), + name: z.string().min(1).max(255), + required: z.boolean().optional().default(false), + type: z.string().min(1).max(64), +}) + +/** + * AgentSoulPromptConfig + */ +export const zAgentSoulPromptConfig = z.object({ + system_prompt: z.string().optional().default(''), +}) + /** * WorkflowAgentBindingType * @@ -2630,6 +2485,111 @@ export const zDeclaredOutputFileConfig = z.object({ mime_types: z.array(z.string()).optional(), }) +/** + * AgentHumanContactConfig + */ +export const zAgentHumanContactConfig = z.object({ + channel: z.string().max(64).nullish(), + contact_id: z.string().max(255).nullish(), + contact_method: z.string().max(64).nullish(), + email: z.string().max(255).nullish(), + human_id: z.string().max(255).nullish(), + id: z.string().max(255).nullish(), + method: z.string().max(64).nullish(), + name: z.string().max(255).nullish(), + tenant_id: z.string().max(255).nullish(), +}) + +/** + * WorkflowNodeJobMode + */ +export const zWorkflowNodeJobMode = z.enum(['let_agent_figure_it_out', 'tell_agent_what_to_do']) + +/** + * WorkflowPreviousNodeOutputRef + */ +export const zWorkflowPreviousNodeOutputRef = z.object({ + key: z.string().max(255).nullish(), + name: z.string().max(255).nullish(), + node_id: z.string().max(255).nullish(), + output: z.string().max(255).nullish(), + selector: z.array(z.union([z.string(), z.int(), z.number(), z.boolean(), z.null()])).nullish(), + value_selector: z + .array(z.union([z.string(), z.int(), z.number(), z.boolean(), z.null()])) + .nullish(), + variable: z.string().max(255).nullish(), + variable_selector: z + .array(z.union([z.string(), z.int(), z.number(), z.boolean(), z.null()])) + .nullish(), +}) + +/** + * AgentComposerNodeJobCandidatesResponse + */ +export const zAgentComposerNodeJobCandidatesResponse = z.object({ + declare_output_types: z.array(zDeclaredOutputType).optional(), + human_contacts: z.array(zAgentHumanContactConfig).optional(), + previous_node_outputs: z.array(zWorkflowPreviousNodeOutputRef).optional(), +}) + +/** + * AgentComposerDifyToolCandidateResponse + */ +export const zAgentComposerDifyToolCandidateResponse = z.object({ + description: z.string().nullish(), + granularity: z.string().nullish(), + id: z.string().nullish(), + name: z.string().nullish(), + plugin_id: z.string().nullish(), + provider: z.string().nullish(), + provider_id: z.string().nullish(), + tools_count: z.int().nullish(), +}) + +/** + * AgentKnowledgeDatasetConfig + */ +export const zAgentKnowledgeDatasetConfig = z.object({ + description: z.string().nullish(), + id: z.string().max(255).nullish(), + name: z.string().max(255).nullish(), +}) + +/** + * AgentComposerSkillCandidateResponse + */ +export const zAgentComposerSkillCandidateResponse = z.object({ + description: z.string().nullish(), + file_id: z.string().max(255).nullish(), + full_archive_file_id: z.string().max(255).nullish(), + full_archive_key: z.string().max(512).nullish(), + id: z.string().max(255).nullish(), + kind: z.literal('skill').optional().default('skill'), + manifest_files: z.array(z.string()).nullish(), + name: z.string().max(255).nullish(), + path: z.string().nullish(), + skill_md_file_id: z.string().max(255).nullish(), + skill_md_key: z.string().max(512).nullish(), +}) + +/** + * AgentComposerFileCandidateResponse + */ +export const zAgentComposerFileCandidateResponse = z.object({ + drive_key: z.string().max(512).nullish(), + file_id: z.string().max(255).nullish(), + id: z.string().max(255).nullish(), + kind: z.literal('file').optional().default('file'), + name: z.string().max(255).nullish(), + reference: z.string().max(255).nullish(), + remote_url: z.string().nullish(), + tenant_id: z.string().max(255).nullish(), + transfer_method: z.string().max(64).nullish(), + type: z.string().max(64).nullish(), + upload_file_id: z.string().max(255).nullish(), + url: z.string().nullish(), +}) + /** * CheckResultView * @@ -2675,6 +2635,37 @@ export const zWorkflowRunSnapshotView = z.object({ workflow_run_status: zWorkflowExecutionStatus, }) +export const zJsonValue2 = z.unknown() + +/** + * HumanInputFormSubmissionData + */ +export const zHumanInputFormSubmissionData = z.object({ + action_id: z.string(), + action_text: z.string(), + node_id: z.string(), + node_title: z.string(), + rendered_content: z.string(), + submitted_data: z.record(z.string(), zJsonValue2).nullish(), +}) + +/** + * AgentFeatureToggleConfig + */ +export const zAgentFeatureToggleConfig = z.object({ + enabled: z.boolean().optional().default(false), +}) + +/** + * AgentTextToSpeechFeatureConfig + */ +export const zAgentTextToSpeechFeatureConfig = z.object({ + autoPlay: z.string().nullish(), + enabled: z.boolean().optional().default(false), + language: z.string().nullish(), + voice: z.string().nullish(), +}) + /** * AgentEnvVariableConfig */ @@ -2833,6 +2824,42 @@ export const zWorkflowNodeJobMetadata = z.object({ file_refs: z.array(zAgentFileRefConfig).nullish(), }) +/** + * OutputErrorStrategy + * + * Per-output failure handling strategy. + * + * Mirrors ``graphon.ErrorStrategy`` but scoped to a single declared output of + * a Workflow Agent Node. The runtime applies the strategy after type check or + * output check fails and any configured retry attempts have been exhausted. + */ +export const zOutputErrorStrategy = z.enum(['default_value', 'fail_branch', 'stop']) + +/** + * DeclaredOutputRetryConfig + * + * Per-output retry configuration that mirrors ``graphon.RetryConfig`` shape. + */ +export const zDeclaredOutputRetryConfig = z.object({ + enabled: z.boolean().optional().default(false), + max_retries: z.int().gte(0).lte(10).optional().default(0), + retry_interval_ms: z.int().gte(0).lte(60000).optional().default(0), +}) + +/** + * DeclaredOutputFailureStrategy + * + * Per-output failure handling. + * + * A single strategy applies to both ``type_check`` and ``output_check`` failures + * (PRD does not distinguish them at the UX level). Stage 4 §4.4. + */ +export const zDeclaredOutputFailureStrategy = z.object({ + default_value: z.unknown().optional(), + on_failure: zOutputErrorStrategy.optional().default('stop'), + retry: zDeclaredOutputRetryConfig.optional(), +}) + /** * AgentCliToolAuthorizationStatus * @@ -2972,80 +2999,21 @@ export const zAgentComposerCandidatesResponse = z.object({ }) /** - * AgentModerationIOConfig - */ -export const zAgentModerationIoConfig = z.object({ - enabled: z.boolean().optional().default(false), - preset_response: z.string().nullish(), -}) - -/** - * AgentModerationProviderConfig - */ -export const zAgentModerationProviderConfig = z.object({ - api_based_extension_id: z.string().nullish(), - inputs_config: zAgentModerationIoConfig.nullish(), - keywords: z.string().nullish(), - outputs_config: zAgentModerationIoConfig.nullish(), -}) - -/** - * AgentSensitiveWordAvoidanceFeatureConfig - */ -export const zAgentSensitiveWordAvoidanceFeatureConfig = z.object({ - config: zAgentModerationProviderConfig.nullish(), - enabled: z.boolean().optional().default(false), - type: z.string().nullish(), -}) - -export const zJsonValue2 = z.unknown() - -/** - * HumanInputFormSubmissionData - */ -export const zHumanInputFormSubmissionData = z.object({ - action_id: z.string(), - action_text: z.string(), - node_id: z.string(), - node_title: z.string(), - rendered_content: z.string(), - submitted_data: z.record(z.string(), zJsonValue2).nullish(), -}) - -/** - * OutputErrorStrategy + * ButtonStyle * - * Per-output failure handling strategy. - * - * Mirrors ``graphon.ErrorStrategy`` but scoped to a single declared output of - * a Workflow Agent Node. The runtime applies the strategy after type check or - * output check fails and any configured retry attempts have been exhausted. + * Button styles for user actions. */ -export const zOutputErrorStrategy = z.enum(['default_value', 'fail_branch', 'stop']) +export const zButtonStyle = z.enum(['accent', 'default', 'ghost', 'primary']) /** - * DeclaredOutputRetryConfig + * UserActionConfig * - * Per-output retry configuration that mirrors ``graphon.RetryConfig`` shape. + * User action configuration. */ -export const zDeclaredOutputRetryConfig = z.object({ - enabled: z.boolean().optional().default(false), - max_retries: z.int().gte(0).lte(10).optional().default(0), - retry_interval_ms: z.int().gte(0).lte(60000).optional().default(0), -}) - -/** - * DeclaredOutputFailureStrategy - * - * Per-output failure handling. - * - * A single strategy applies to both ``type_check`` and ``output_check`` failures - * (PRD does not distinguish them at the UX level). Stage 4 §4.4. - */ -export const zDeclaredOutputFailureStrategy = z.object({ - default_value: z.unknown().optional(), - on_failure: zOutputErrorStrategy.optional().default('stop'), - retry: zDeclaredOutputRetryConfig.optional(), +export const zUserActionConfig = z.object({ + button_style: zButtonStyle.optional().default('default'), + id: z.string().max(20), + title: z.string().max(100), }) /** @@ -3081,46 +3049,6 @@ export const zAgentSoulModelConfig = z.object({ plugin_id: z.string().min(1).max(255), }) -/** - * AgentSuggestedQuestionsAfterAnswerFeatureConfig - */ -export const zAgentSuggestedQuestionsAfterAnswerFeatureConfig = z.object({ - enabled: z.boolean().optional().default(false), - model: zAgentSoulModelConfig.nullish(), - prompt: z.string().nullish(), -}) - -/** - * AgentAppFeaturesPayload - * - * Presentation features configurable on an Agent App. - * - * All fields are optional; an omitted field is reset to its disabled/empty - * default (the config form sends the full desired feature state on save). - */ -export const zAgentAppFeaturesPayload = z.object({ - opening_statement: z.string().nullish(), - retriever_resource: zAgentFeatureToggleConfig.nullish(), - sensitive_word_avoidance: zAgentSensitiveWordAvoidanceFeatureConfig.nullish(), - speech_to_text: zAgentFeatureToggleConfig.nullish(), - suggested_questions: z.array(z.string()).nullish(), - suggested_questions_after_answer: zAgentSuggestedQuestionsAfterAnswerFeatureConfig.nullish(), - text_to_speech: zAgentTextToSpeechFeatureConfig.nullish(), -}) - -/** - * AgentSoulAppFeaturesConfig - */ -export const zAgentSoulAppFeaturesConfig = z.object({ - opening_statement: z.string().nullish(), - retriever_resource: zAgentFeatureToggleConfig.nullish(), - sensitive_word_avoidance: zAgentSensitiveWordAvoidanceFeatureConfig.nullish(), - speech_to_text: zAgentFeatureToggleConfig.nullish(), - suggested_questions: z.array(z.string()).nullish(), - suggested_questions_after_answer: zAgentSuggestedQuestionsAfterAnswerFeatureConfig.nullish(), - text_to_speech: zAgentTextToSpeechFeatureConfig.nullish(), -}) - /** * DeclaredOutputCheckConfig * @@ -3169,6 +3097,15 @@ export const zWorkflowNodeJobConfig = z.object({ workflow_prompt: z.string().optional().default(''), }) +/** + * AgentSuggestedQuestionsAfterAnswerFeatureConfig + */ +export const zAgentSuggestedQuestionsAfterAnswerFeatureConfig = z.object({ + enabled: z.boolean().optional().default(false), + model: zAgentSoulModelConfig.nullish(), + prompt: z.string().nullish(), +}) + /** * AgentSoulDifyToolCredentialRef * @@ -3232,91 +3169,6 @@ export const zAgentSoulToolsConfig = z.object({ dify_tools: z.array(zAgentSoulDifyToolConfig).optional(), }) -/** - * AgentSoulConfig - */ -export const zAgentSoulConfig = z.object({ - app_features: zAgentSoulAppFeaturesConfig.optional(), - app_variables: z.array(zAppVariableConfig).optional(), - env: zAgentSoulEnvConfig.optional(), - human: zAgentSoulHumanConfig.optional(), - knowledge: zAgentSoulKnowledgeConfig.optional(), - memory: zAgentSoulMemoryConfig.optional(), - misc_legacy: zAgentSoulAppFeaturesConfig.optional(), - model: zAgentSoulModelConfig.nullish(), - prompt: zAgentSoulPromptConfig.optional(), - sandbox: zAgentSoulSandboxConfig.optional(), - schema_version: z.int().optional().default(1), - skills_files: zAgentSoulSkillsFilesConfig.optional(), - tools: zAgentSoulToolsConfig.optional(), -}) - -/** - * AgentAppComposerResponse - */ -export const zAgentAppComposerResponse = z.object({ - active_config_snapshot: zAgentConfigSnapshotSummaryResponse, - agent: zAgentComposerAgentResponse, - agent_soul: zAgentSoulConfig, - save_options: z.array(zComposerSaveStrategy), - validation: zComposerValidationFindingsResponse.nullish(), - variant: z.literal('agent_app'), -}) - -/** - * ComposerSavePayload - */ -export const zComposerSavePayload = z.object({ - agent_soul: zAgentSoulConfig.nullish(), - binding: zComposerBindingPayload.nullish(), - client_revision_id: z.string().nullish(), - idempotency_key: z.string().nullish(), - new_agent_name: z.string().min(1).max(255).nullish(), - node_job: zWorkflowNodeJobConfig.nullish(), - save_strategy: zComposerSaveStrategy, - soul_lock: zComposerSoulLockPayload.optional(), - variant: zComposerVariant, - version_note: z.string().nullish(), -}) - -/** - * WorkflowAgentComposerResponse - */ -export const zWorkflowAgentComposerResponse = z.object({ - active_config_snapshot: zAgentConfigSnapshotSummaryResponse.nullish(), - agent: zAgentComposerAgentResponse.nullish(), - agent_soul: zAgentSoulConfig, - app_id: z.string().nullish(), - binding: zAgentComposerBindingResponse.nullish(), - effective_declared_outputs: z.array(zDeclaredOutputConfig).optional(), - impact_summary: zAgentComposerImpactResponse.nullish(), - node_id: z.string().nullish(), - node_job: zWorkflowNodeJobConfig, - save_options: z.array(zComposerSaveStrategy), - soul_lock: zAgentComposerSoulLockResponse, - validation: zComposerValidationFindingsResponse.nullish(), - variant: z.literal('workflow'), - workflow_id: z.string().nullish(), -}) - -/** - * ButtonStyle - * - * Button styles for user actions. - */ -export const zButtonStyle = z.enum(['accent', 'default', 'ghost', 'primary']) - -/** - * UserActionConfig - * - * User action configuration. - */ -export const zUserActionConfig = z.object({ - button_style: zButtonStyle.optional().default('default'), - id: z.string().max(20), - title: z.string().max(100), -}) - /** * FileType */ @@ -3355,6 +3207,101 @@ export const zFileListInputConfig = z.object({ type: z.literal('file-list').optional().default('file-list'), }) +/** + * AgentModerationIOConfig + */ +export const zAgentModerationIoConfig = z.object({ + enabled: z.boolean().optional().default(false), + preset_response: z.string().nullish(), +}) + +/** + * AgentModerationProviderConfig + */ +export const zAgentModerationProviderConfig = z.object({ + api_based_extension_id: z.string().nullish(), + inputs_config: zAgentModerationIoConfig.nullish(), + keywords: z.string().nullish(), + outputs_config: zAgentModerationIoConfig.nullish(), +}) + +/** + * AgentSensitiveWordAvoidanceFeatureConfig + */ +export const zAgentSensitiveWordAvoidanceFeatureConfig = z.object({ + config: zAgentModerationProviderConfig.nullish(), + enabled: z.boolean().optional().default(false), + type: z.string().nullish(), +}) + +/** + * AgentSoulAppFeaturesConfig + */ +export const zAgentSoulAppFeaturesConfig = z.object({ + opening_statement: z.string().nullish(), + retriever_resource: zAgentFeatureToggleConfig.nullish(), + sensitive_word_avoidance: zAgentSensitiveWordAvoidanceFeatureConfig.nullish(), + speech_to_text: zAgentFeatureToggleConfig.nullish(), + suggested_questions: z.array(z.string()).nullish(), + suggested_questions_after_answer: zAgentSuggestedQuestionsAfterAnswerFeatureConfig.nullish(), + text_to_speech: zAgentTextToSpeechFeatureConfig.nullish(), +}) + +/** + * AgentSoulConfig + */ +export const zAgentSoulConfig = z.object({ + app_features: zAgentSoulAppFeaturesConfig.optional(), + app_variables: z.array(zAppVariableConfig).optional(), + env: zAgentSoulEnvConfig.optional(), + human: zAgentSoulHumanConfig.optional(), + knowledge: zAgentSoulKnowledgeConfig.optional(), + memory: zAgentSoulMemoryConfig.optional(), + misc_legacy: zAgentSoulAppFeaturesConfig.optional(), + model: zAgentSoulModelConfig.nullish(), + prompt: zAgentSoulPromptConfig.optional(), + sandbox: zAgentSoulSandboxConfig.optional(), + schema_version: z.int().optional().default(1), + skills_files: zAgentSoulSkillsFilesConfig.optional(), + tools: zAgentSoulToolsConfig.optional(), +}) + +/** + * WorkflowAgentComposerResponse + */ +export const zWorkflowAgentComposerResponse = z.object({ + active_config_snapshot: zAgentConfigSnapshotSummaryResponse.nullish(), + agent: zAgentComposerAgentResponse.nullish(), + agent_soul: zAgentSoulConfig, + app_id: z.string().nullish(), + binding: zAgentComposerBindingResponse.nullish(), + effective_declared_outputs: z.array(zDeclaredOutputConfig).optional(), + impact_summary: zAgentComposerImpactResponse.nullish(), + node_id: z.string().nullish(), + node_job: zWorkflowNodeJobConfig, + save_options: z.array(zComposerSaveStrategy), + soul_lock: zAgentComposerSoulLockResponse, + validation: zComposerValidationFindingsResponse.nullish(), + variant: z.literal('workflow'), + workflow_id: z.string().nullish(), +}) + +/** + * ComposerSavePayload + */ +export const zComposerSavePayload = z.object({ + agent_soul: zAgentSoulConfig.nullish(), + binding: zComposerBindingPayload.nullish(), + client_revision_id: z.string().nullish(), + idempotency_key: z.string().nullish(), + new_agent_name: z.string().min(1).max(255).nullish(), + node_job: zWorkflowNodeJobConfig.nullish(), + save_strategy: zComposerSaveStrategy, + soul_lock: zComposerSoulLockPayload.optional(), + variant: zComposerVariant, + version_note: z.string().nullish(), +}) + /** * ValueSourceType * @@ -3481,6 +3428,45 @@ export const zMessageInfiniteScrollPaginationResponse = z.object({ */ export const zGeneratedAppResponseWritable = zJsonValue +/** + * AppPartial + */ +export const zAppPartialWritable = z.object({ + access_mode: z.string().nullish(), + author_name: z.string().nullish(), + bound_agent_id: z.string().nullish(), + create_user_name: z.string().nullish(), + created_at: z.int().nullish(), + created_by: z.string().nullish(), + description: z.string().nullish(), + has_draft_trigger: z.boolean().nullish(), + icon: z.string().nullish(), + icon_background: z.string().nullish(), + icon_type: z.string().nullish(), + id: z.string(), + is_starred: z.boolean().optional().default(false), + max_active_requests: z.int().nullish(), + mode: z.string(), + model_config: zModelConfigPartial.nullish(), + name: z.string(), + tags: z.array(zTag).optional(), + updated_at: z.int().nullish(), + updated_by: z.string().nullish(), + use_icon_as_answer_icon: z.boolean().nullish(), + workflow: zWorkflowPartial.nullish(), +}) + +/** + * AppPagination + */ +export const zAppPaginationWritable = z.object({ + data: z.array(zAppPartialWritable), + has_more: z.boolean(), + limit: z.int(), + page: z.int(), + total: z.int(), +}) + /** * Site */ @@ -3506,7 +3492,6 @@ export const zSiteWritable = z.object({ export const zAppDetailWithSiteWritable = z.object({ access_mode: z.string().nullish(), api_base_url: z.string().nullish(), - app_model_config: zModelConfig.nullish(), bound_agent_id: z.string().nullish(), created_at: z.int().nullish(), created_by: z.string().nullish(), @@ -3519,7 +3504,8 @@ export const zAppDetailWithSiteWritable = z.object({ icon_type: z.string().nullish(), id: z.string(), max_active_requests: z.int().nullish(), - mode_compatible_with_agent: z.string(), + mode: z.string(), + model_config: zModelConfig.nullish(), name: z.string(), site: zSiteWritable.nullish(), tags: z.array(zTag).optional(), @@ -3838,105 +3824,6 @@ export const zPostAppsByAppIdAdvancedChatWorkflowsDraftRunPath = z.object({ */ export const zPostAppsByAppIdAdvancedChatWorkflowsDraftRunResponse = zGeneratedAppResponse -export const zGetAppsByAppIdAgentComposerPath = z.object({ - app_id: z.string(), -}) - -/** - * Agent app composer state - */ -export const zGetAppsByAppIdAgentComposerResponse = zAgentAppComposerResponse - -export const zPutAppsByAppIdAgentComposerBody = zComposerSavePayload - -export const zPutAppsByAppIdAgentComposerPath = z.object({ - app_id: z.string(), -}) - -/** - * Agent app composer saved - */ -export const zPutAppsByAppIdAgentComposerResponse = zAgentAppComposerResponse - -export const zGetAppsByAppIdAgentComposerCandidatesPath = z.object({ - app_id: z.string(), -}) - -/** - * Agent app composer candidates - */ -export const zGetAppsByAppIdAgentComposerCandidatesResponse = zAgentComposerCandidatesResponse - -export const zPostAppsByAppIdAgentComposerValidateBody = zComposerSavePayload - -export const zPostAppsByAppIdAgentComposerValidatePath = z.object({ - app_id: z.string(), -}) - -/** - * Agent app composer validation result - */ -export const zPostAppsByAppIdAgentComposerValidateResponse = zAgentComposerValidateResponse - -export const zPostAppsByAppIdAgentFeaturesBody = zAgentAppFeaturesPayload - -export const zPostAppsByAppIdAgentFeaturesPath = z.object({ - app_id: z.string(), -}) - -/** - * Features updated successfully - */ -export const zPostAppsByAppIdAgentFeaturesResponse = zSimpleResultResponse - -export const zGetAppsByAppIdAgentReferencingWorkflowsPath = z.object({ - app_id: z.string(), -}) - -/** - * Referencing workflows listed successfully - */ -export const zGetAppsByAppIdAgentReferencingWorkflowsResponse = zAgentReferencingWorkflowsResponse - -export const zGetAppsByAppIdAgentSandboxFilesPath = z.object({ - app_id: z.string(), -}) - -export const zGetAppsByAppIdAgentSandboxFilesQuery = z.object({ - conversation_id: z.string().min(1), - path: z.string().optional().default('.'), -}) - -/** - * Listing returned - */ -export const zGetAppsByAppIdAgentSandboxFilesResponse = zSandboxListResponse - -export const zGetAppsByAppIdAgentSandboxFilesReadPath = z.object({ - app_id: z.string(), -}) - -export const zGetAppsByAppIdAgentSandboxFilesReadQuery = z.object({ - conversation_id: z.string().min(1), - path: z.string().min(1), -}) - -/** - * Preview returned - */ -export const zGetAppsByAppIdAgentSandboxFilesReadResponse = zSandboxReadResponse - -export const zPostAppsByAppIdAgentSandboxFilesUploadBody = zAgentSandboxUploadPayload - -export const zPostAppsByAppIdAgentSandboxFilesUploadPath = z.object({ - app_id: z.string(), -}) - -/** - * Uploaded - */ -export const zPostAppsByAppIdAgentSandboxFilesUploadResponse = zSandboxUploadResponse - export const zGetAppsByAppIdAgentDriveFilesPath = z.object({ app_id: z.string(), }) diff --git a/packages/contracts/generated/api/console/orpc.gen.ts b/packages/contracts/generated/api/console/orpc.gen.ts index ec59d8cccd..1d25989f24 100644 --- a/packages/contracts/generated/api/console/orpc.gen.ts +++ b/packages/contracts/generated/api/console/orpc.gen.ts @@ -2,7 +2,7 @@ import { account } from './account/orpc.gen' import { activate } from './activate/orpc.gen' -import { agents } from './agents/orpc.gen' +import { agent } from './agent/orpc.gen' import { allWorkspaces } from './all-workspaces/orpc.gen' import { apiBasedExtension } from './api-based-extension/orpc.gen' import { apiKeyAuth } from './api-key-auth/orpc.gen' @@ -53,7 +53,7 @@ import { workspaces } from './workspaces/orpc.gen' export const contract = { account, activate, - agents, + agent, allWorkspaces, apiBasedExtension, apiKeyAuth,