mirror of
https://github.com/langgenius/dify.git
synced 2026-06-16 22:11:09 +08:00
fix: align agent app backing roster API (#37442)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
12159d6313
commit
d21bf291bb
@ -8,10 +8,8 @@ from controllers.common.schema import query_params_from_model, register_response
|
||||
from controllers.console import console_ns
|
||||
from controllers.console.wraps import (
|
||||
account_initialization_required,
|
||||
edit_permission_required,
|
||||
setup_required,
|
||||
with_current_tenant_id,
|
||||
with_current_user_id,
|
||||
)
|
||||
from extensions.ext_database import db
|
||||
from fields.agent_fields import (
|
||||
@ -25,7 +23,7 @@ from fields.agent_fields import (
|
||||
from libs.helper import dump_response
|
||||
from libs.login import login_required
|
||||
from services.agent.roster_service import AgentRosterService
|
||||
from services.entities.agent_entities import RosterAgentCreatePayload, RosterAgentUpdatePayload, RosterListQuery
|
||||
from services.entities.agent_entities import RosterListQuery
|
||||
|
||||
|
||||
class AgentInviteOptionsQuery(RosterListQuery):
|
||||
@ -40,8 +38,6 @@ register_schema_models(
|
||||
console_ns,
|
||||
AgentInviteOptionsQuery,
|
||||
AgentIdPath,
|
||||
RosterAgentCreatePayload,
|
||||
RosterAgentUpdatePayload,
|
||||
RosterListQuery,
|
||||
)
|
||||
register_response_schema_models(
|
||||
@ -76,23 +72,6 @@ class AgentRosterListApi(Resource):
|
||||
),
|
||||
)
|
||||
|
||||
@console_ns.expect(console_ns.models[RosterAgentCreatePayload.__name__])
|
||||
@console_ns.response(201, "Agent created", console_ns.models[AgentRosterResponse.__name__])
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@edit_permission_required
|
||||
@with_current_user_id
|
||||
@with_current_tenant_id
|
||||
def post(self, tenant_id: str, account_id: str):
|
||||
payload = RosterAgentCreatePayload.model_validate(console_ns.payload or {})
|
||||
service = _agent_roster_service()
|
||||
agent = service.create_roster_agent(tenant_id=tenant_id, account_id=account_id, payload=payload)
|
||||
return dump_response(
|
||||
AgentRosterResponse,
|
||||
service.get_roster_agent_detail(tenant_id=tenant_id, agent_id=agent.id),
|
||||
), 201
|
||||
|
||||
|
||||
@console_ns.route("/agents/invite-options")
|
||||
class AgentInviteOptionsApi(Resource):
|
||||
@ -129,34 +108,6 @@ class AgentRosterDetailApi(Resource):
|
||||
_agent_roster_service().get_roster_agent_detail(tenant_id=tenant_id, agent_id=str(agent_id)),
|
||||
)
|
||||
|
||||
@console_ns.expect(console_ns.models[RosterAgentUpdatePayload.__name__])
|
||||
@console_ns.response(200, "Agent updated", console_ns.models[AgentRosterResponse.__name__])
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@edit_permission_required
|
||||
@with_current_user_id
|
||||
@with_current_tenant_id
|
||||
def patch(self, tenant_id: str, account_id: str, agent_id: UUID):
|
||||
payload = RosterAgentUpdatePayload.model_validate(console_ns.payload or {})
|
||||
return dump_response(
|
||||
AgentRosterResponse,
|
||||
_agent_roster_service().update_roster_agent(
|
||||
tenant_id=tenant_id, agent_id=str(agent_id), account_id=account_id, payload=payload
|
||||
),
|
||||
)
|
||||
|
||||
@console_ns.response(204, "Agent archived")
|
||||
@setup_required
|
||||
@login_required
|
||||
@account_initialization_required
|
||||
@edit_permission_required
|
||||
@with_current_user_id
|
||||
@with_current_tenant_id
|
||||
def delete(self, tenant_id: str, account_id: str, agent_id: UUID):
|
||||
_agent_roster_service().archive_roster_agent(tenant_id=tenant_id, agent_id=str(agent_id), account_id=account_id)
|
||||
return "", 204
|
||||
|
||||
|
||||
@console_ns.route("/agents/<uuid:agent_id>/versions")
|
||||
class AgentRosterVersionsApi(Resource):
|
||||
|
||||
@ -581,7 +581,7 @@ class AppListApi(Resource):
|
||||
@console_ns.doc("create_app")
|
||||
@console_ns.doc(description="Create a new application")
|
||||
@console_ns.expect(console_ns.models[CreateAppPayload.__name__])
|
||||
@console_ns.response(201, "App created successfully", console_ns.models[AppDetail.__name__])
|
||||
@console_ns.response(201, "App created successfully", console_ns.models[AppDetailWithSite.__name__])
|
||||
@console_ns.response(403, "Insufficient permissions")
|
||||
@console_ns.response(400, "Invalid request parameters")
|
||||
@setup_required
|
||||
@ -605,7 +605,7 @@ class AppListApi(Resource):
|
||||
|
||||
app_service = AppService()
|
||||
app = app_service.create_app(current_tenant_id, params, current_user)
|
||||
app_detail = AppDetail.model_validate(app, from_attributes=True)
|
||||
app_detail = AppDetailWithSite.model_validate(app, from_attributes=True)
|
||||
return app_detail.model_dump(mode="json"), 201
|
||||
|
||||
|
||||
|
||||
@ -38,6 +38,8 @@ class AgentScope(StrEnum):
|
||||
class AgentSource(StrEnum):
|
||||
"""Origin that created or imported the Agent."""
|
||||
|
||||
# Created directly as a reusable Agent Roster asset.
|
||||
ROSTER = "roster"
|
||||
# Created from an Agent App composer.
|
||||
AGENT_APP = "agent_app"
|
||||
# Created from a Workflow Agent Composer flow.
|
||||
|
||||
@ -308,19 +308,6 @@ Check if activation token is valid
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Agent roster list | **application/json**: [AgentRosterListResponse](#agentrosterlistresponse)<br> |
|
||||
|
||||
### [POST] /agents
|
||||
#### Request Body
|
||||
|
||||
| Required | Schema |
|
||||
| -------- | ------ |
|
||||
| Yes | **application/json**: [RosterAgentCreatePayload](#rosteragentcreatepayload)<br> |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 201 | Agent created | **application/json**: [AgentRosterResponse](#agentrosterresponse)<br> |
|
||||
|
||||
### [GET] /agents/invite-options
|
||||
#### Parameters
|
||||
|
||||
@ -337,19 +324,6 @@ Check if activation token is valid
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Agent invite options | **application/json**: [AgentInviteOptionsResponse](#agentinviteoptionsresponse)<br> |
|
||||
|
||||
### [DELETE] /agents/{agent_id}
|
||||
#### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| agent_id | path | | Yes | string |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Code | Description |
|
||||
| ---- | ----------- |
|
||||
| 204 | Agent archived |
|
||||
|
||||
### [GET] /agents/{agent_id}
|
||||
#### Parameters
|
||||
|
||||
@ -363,25 +337,6 @@ Check if activation token is valid
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Agent detail | **application/json**: [AgentRosterResponse](#agentrosterresponse)<br> |
|
||||
|
||||
### [PATCH] /agents/{agent_id}
|
||||
#### Parameters
|
||||
|
||||
| Name | Located in | Description | Required | Schema |
|
||||
| ---- | ---------- | ----------- | -------- | ------ |
|
||||
| agent_id | path | | Yes | string |
|
||||
|
||||
#### Request Body
|
||||
|
||||
| Required | Schema |
|
||||
| -------- | ------ |
|
||||
| Yes | **application/json**: [RosterAgentUpdatePayload](#rosteragentupdatepayload)<br> |
|
||||
|
||||
#### Responses
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 200 | Agent updated | **application/json**: [AgentRosterResponse](#agentrosterresponse)<br> |
|
||||
|
||||
### [GET] /agents/{agent_id}/versions
|
||||
#### Parameters
|
||||
|
||||
@ -599,7 +554,7 @@ Create a new application
|
||||
|
||||
| Code | Description | Schema |
|
||||
| ---- | ----------- | ------ |
|
||||
| 201 | App created successfully | **application/json**: [AppDetail](#appdetail)<br> |
|
||||
| 201 | App created successfully | **application/json**: [AppDetailWithSite](#appdetailwithsite)<br> |
|
||||
| 400 | Invalid request parameters | |
|
||||
| 403 | Insufficient permissions | |
|
||||
|
||||
@ -16965,30 +16920,6 @@ Model class for provider quota configuration.
|
||||
| summary | string | | No |
|
||||
| word_count | integer | | No |
|
||||
|
||||
#### RosterAgentCreatePayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| agent_soul | [AgentSoulConfig](#agentsoulconfig) | | No |
|
||||
| description | string | | No |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| icon_type | [AgentIconType](#agenticontype) | | No |
|
||||
| name | string | | Yes |
|
||||
| role | string | | No |
|
||||
| version_note | string | | No |
|
||||
|
||||
#### RosterAgentUpdatePayload
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| description | string | | No |
|
||||
| icon | string | | No |
|
||||
| icon_background | string | | No |
|
||||
| icon_type | [AgentIconType](#agenticontype) | | No |
|
||||
| name | string | | No |
|
||||
| role | string | | No |
|
||||
|
||||
#### RosterListQuery
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
|
||||
@ -213,7 +213,7 @@ class AgentRosterService:
|
||||
tenant_id: str,
|
||||
account_id: str,
|
||||
payload: RosterAgentCreatePayload,
|
||||
source: AgentSource = AgentSource.AGENT_APP,
|
||||
source: AgentSource = AgentSource.ROSTER,
|
||||
) -> Agent:
|
||||
ComposerConfigValidator.validate_agent_soul(payload.agent_soul)
|
||||
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
import json
|
||||
import logging
|
||||
from collections.abc import Sequence
|
||||
from datetime import datetime
|
||||
from typing import Any, Literal, TypedDict, cast, override
|
||||
|
||||
import sqlalchemy as sa
|
||||
@ -23,7 +24,7 @@ from graphon.model_runtime.model_providers.base.large_language_model import Larg
|
||||
from libs.datetime_utils import naive_utc_now
|
||||
from libs.login import current_user
|
||||
from models import Account
|
||||
from models.agent import AgentIconType
|
||||
from models.agent import Agent, AgentIconType, AgentScope, AgentSource, AgentStatus
|
||||
from models.model import App, AppMode, AppModelConfig, IconType, Site
|
||||
from models.tools import ApiToolProvider
|
||||
from services.billing_service import BillingService
|
||||
@ -377,6 +378,62 @@ class AppService:
|
||||
use_icon_as_answer_icon: bool
|
||||
max_active_requests: int
|
||||
|
||||
@staticmethod
|
||||
def _get_backing_agent_for_update(app: App) -> Agent | None:
|
||||
if app.mode != AppMode.AGENT:
|
||||
return None
|
||||
return db.session.scalar(
|
||||
select(Agent).where(
|
||||
Agent.tenant_id == app.tenant_id,
|
||||
Agent.app_id == app.id,
|
||||
Agent.scope == AgentScope.ROSTER,
|
||||
Agent.source == AgentSource.AGENT_APP,
|
||||
Agent.status == AgentStatus.ACTIVE,
|
||||
)
|
||||
)
|
||||
|
||||
@staticmethod
|
||||
def _to_agent_icon_type(icon_type: IconType | str | None) -> AgentIconType | None:
|
||||
if icon_type is None:
|
||||
return None
|
||||
value = icon_type.value if isinstance(icon_type, IconType) else icon_type
|
||||
return AgentIconType(value)
|
||||
|
||||
def _sync_backing_agent_identity(
|
||||
self,
|
||||
app: App,
|
||||
*,
|
||||
name: str | None = None,
|
||||
description: str | None = None,
|
||||
icon_type: IconType | str | None = None,
|
||||
icon: str | None = None,
|
||||
icon_background: str | None = None,
|
||||
account_id: str | None = None,
|
||||
updated_at: datetime | None = None,
|
||||
) -> None:
|
||||
"""Keep the Roster identity aligned with its Agent App shell.
|
||||
|
||||
Agent Soul remains versioned through Composer. This helper only mirrors
|
||||
user-facing identity fields so Roster and Agent Console do not drift.
|
||||
"""
|
||||
agent = self._get_backing_agent_for_update(app)
|
||||
if agent is None:
|
||||
return
|
||||
|
||||
if name is not None:
|
||||
agent.name = name
|
||||
if description is not None:
|
||||
agent.description = description
|
||||
if icon_type is not None:
|
||||
agent.icon_type = self._to_agent_icon_type(icon_type)
|
||||
if icon is not None:
|
||||
agent.icon = icon
|
||||
if icon_background is not None:
|
||||
agent.icon_background = icon_background
|
||||
agent.updated_by = account_id
|
||||
if updated_at is not None:
|
||||
agent.updated_at = updated_at
|
||||
|
||||
def update_app(self, app: App, args: ArgsDict) -> App:
|
||||
"""
|
||||
Update app
|
||||
@ -400,6 +457,16 @@ class AppService:
|
||||
app.max_active_requests = args.get("max_active_requests")
|
||||
app.updated_by = current_user.id
|
||||
app.updated_at = naive_utc_now()
|
||||
self._sync_backing_agent_identity(
|
||||
app,
|
||||
name=app.name,
|
||||
description=app.description,
|
||||
icon_type=app.icon_type,
|
||||
icon=app.icon,
|
||||
icon_background=app.icon_background,
|
||||
account_id=current_user.id,
|
||||
updated_at=app.updated_at,
|
||||
)
|
||||
db.session.commit()
|
||||
|
||||
app_was_updated.send(app)
|
||||
@ -417,6 +484,12 @@ class AppService:
|
||||
app.name = name
|
||||
app.updated_by = current_user.id
|
||||
app.updated_at = naive_utc_now()
|
||||
self._sync_backing_agent_identity(
|
||||
app,
|
||||
name=app.name,
|
||||
account_id=current_user.id,
|
||||
updated_at=app.updated_at,
|
||||
)
|
||||
db.session.commit()
|
||||
|
||||
app_was_updated.send(app)
|
||||
@ -441,6 +514,14 @@ class AppService:
|
||||
app.icon_type = icon_type if isinstance(icon_type, IconType) else IconType(icon_type)
|
||||
app.updated_by = current_user.id
|
||||
app.updated_at = naive_utc_now()
|
||||
self._sync_backing_agent_identity(
|
||||
app,
|
||||
icon_type=app.icon_type,
|
||||
icon=app.icon,
|
||||
icon_background=app.icon_background,
|
||||
account_id=current_user.id,
|
||||
updated_at=app.updated_at,
|
||||
)
|
||||
db.session.commit()
|
||||
|
||||
app_was_updated.send(app)
|
||||
@ -493,6 +574,16 @@ class AppService:
|
||||
"""
|
||||
app_was_deleted.send(app)
|
||||
|
||||
backing_agent = self._get_backing_agent_for_update(app)
|
||||
if backing_agent is not None:
|
||||
now = naive_utc_now()
|
||||
account_id = getattr(current_user, "id", None)
|
||||
backing_agent.status = AgentStatus.ARCHIVED
|
||||
backing_agent.archived_by = account_id
|
||||
backing_agent.archived_at = now
|
||||
backing_agent.updated_by = account_id
|
||||
backing_agent.updated_at = now
|
||||
|
||||
db.session.delete(app)
|
||||
db.session.commit()
|
||||
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
from inspect import unwrap
|
||||
from types import SimpleNamespace
|
||||
from typing import Protocol, cast
|
||||
from typing import cast
|
||||
|
||||
import pytest
|
||||
from flask import Flask
|
||||
@ -128,10 +128,6 @@ def _get_app_model_modes(view) -> list[AppMode]:
|
||||
return []
|
||||
|
||||
|
||||
class _PayloadWithDescription(Protocol):
|
||||
description: object
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def account_id() -> str:
|
||||
return "account-1"
|
||||
@ -153,27 +149,10 @@ def test_roster_list_get_parses_query_and_calls_service(app: Flask, monkeypatch:
|
||||
assert captured == {"tenant_id": "tenant-1", "page": 2, "limit": 5, "keyword": "analyst"}
|
||||
|
||||
|
||||
def test_roster_list_post_creates_agent_and_returns_detail(
|
||||
app: Flask, monkeypatch: pytest.MonkeyPatch, account_id: str
|
||||
) -> None:
|
||||
created_agent = SimpleNamespace(id="agent-1")
|
||||
monkeypatch.setattr(
|
||||
roster_controller.AgentRosterService,
|
||||
"create_roster_agent",
|
||||
lambda _self, **kwargs: created_agent,
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
roster_controller.AgentRosterService,
|
||||
"get_roster_agent_detail",
|
||||
lambda _self, **kwargs: _agent_response(kwargs["agent_id"]),
|
||||
)
|
||||
|
||||
with app.test_request_context(json={"name": "Analyst", "agent_soul": {"prompt": {"system_prompt": "x"}}}):
|
||||
result, status = unwrap(AgentRosterListApi.post)(AgentRosterListApi(), "tenant-1", account_id)
|
||||
|
||||
assert status == 201
|
||||
assert result["id"] == "agent-1"
|
||||
assert result["agent_kind"] == "dify_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_invite_options_get_parses_app_id(app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
@ -192,30 +171,14 @@ def test_invite_options_get_parses_app_id(app: Flask, monkeypatch: pytest.Monkey
|
||||
assert captured == {"tenant_id": "tenant-1", "page": 1, "limit": 10, "keyword": None, "app_id": "app-1"}
|
||||
|
||||
|
||||
def test_roster_detail_patch_delete_and_versions_call_services(
|
||||
app: Flask, monkeypatch: pytest.MonkeyPatch, account_id: str
|
||||
) -> None:
|
||||
def test_roster_detail_and_versions_call_services(app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
agent_id = "00000000-0000-0000-0000-000000000001"
|
||||
version_id = "00000000-0000-0000-0000-000000000002"
|
||||
archived: dict[str, object] = {}
|
||||
monkeypatch.setattr(
|
||||
roster_controller.AgentRosterService,
|
||||
"get_roster_agent_detail",
|
||||
lambda _self, **kwargs: _agent_response(cast(str, kwargs["agent_id"])),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
roster_controller.AgentRosterService,
|
||||
"update_roster_agent",
|
||||
lambda _self, **kwargs: {
|
||||
**_agent_response(cast(str, kwargs["agent_id"])),
|
||||
"description": cast(_PayloadWithDescription, kwargs["payload"]).description,
|
||||
},
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
roster_controller.AgentRosterService,
|
||||
"archive_roster_agent",
|
||||
lambda _self, **kwargs: archived.update(kwargs),
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
roster_controller.AgentRosterService,
|
||||
"list_agent_versions",
|
||||
@ -245,13 +208,6 @@ def test_roster_detail_patch_delete_and_versions_call_services(
|
||||
)
|
||||
|
||||
assert unwrap(AgentRosterDetailApi.get)(AgentRosterDetailApi(), "tenant-1", agent_id)["id"] == agent_id
|
||||
with app.test_request_context(json={"description": "updated"}):
|
||||
assert (
|
||||
unwrap(AgentRosterDetailApi.patch)(AgentRosterDetailApi(), "tenant-1", account_id, agent_id)["description"]
|
||||
== "updated"
|
||||
)
|
||||
assert unwrap(AgentRosterDetailApi.delete)(AgentRosterDetailApi(), "tenant-1", account_id, agent_id) == ("", 204)
|
||||
assert archived["account_id"] == "account-1"
|
||||
assert (
|
||||
unwrap(AgentRosterVersionsApi.get)(AgentRosterVersionsApi(), "tenant-1", agent_id)["data"][0]["id"]
|
||||
== "version-1"
|
||||
|
||||
@ -314,6 +314,39 @@ 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):
|
||||
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"))
|
||||
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"
|
||||
|
||||
|
||||
def test_app_partial_serialization_uses_aliases(app_models):
|
||||
AppPartial = app_models.AppPartial
|
||||
created_at = _ts()
|
||||
@ -389,6 +422,7 @@ def test_app_detail_with_site_includes_nested_serialization(app_models):
|
||||
max_active_requests=5,
|
||||
deleted_tools=[{"type": "api", "tool_name": "search", "provider_id": "prov"}],
|
||||
site=site,
|
||||
bound_agent_id="agent-1",
|
||||
)
|
||||
|
||||
serialized = AppDetailWithSite.model_validate(app_obj, from_attributes=True).model_dump(mode="json")
|
||||
@ -398,6 +432,7 @@ def test_app_detail_with_site_includes_nested_serialization(app_models):
|
||||
assert serialized["deleted_tools"][0]["tool_name"] == "search"
|
||||
assert serialized["site"]["icon_url"] == "signed:site-icon"
|
||||
assert serialized["site"]["created_at"] == int(timestamp.timestamp())
|
||||
assert serialized["bound_agent_id"] == "agent-1"
|
||||
|
||||
|
||||
def test_app_pagination_aliases_per_page_and_has_next(app_models):
|
||||
|
||||
@ -27,6 +27,7 @@ def test_agent_enums_match_prd_boundaries():
|
||||
assert AgentIconType.EMOJI.value == "emoji"
|
||||
assert AgentScope.ROSTER.value == "roster"
|
||||
assert AgentScope.WORKFLOW_ONLY.value == "workflow_only"
|
||||
assert AgentSource.ROSTER.value == "roster"
|
||||
assert AgentSource.AGENT_APP.value == "agent_app"
|
||||
assert AgentSource.WORKFLOW.value == "workflow"
|
||||
assert AgentStatus.ACTIVE.value == "active"
|
||||
|
||||
@ -787,6 +787,7 @@ def test_roster_create_detail_and_lookup_helpers(monkeypatch):
|
||||
assert service._load_versions_by_id([]) == {}
|
||||
|
||||
assert created.name == "Analyst"
|
||||
assert created.source == AgentSource.ROSTER
|
||||
assert created.active_config_snapshot_id is not None
|
||||
assert created.active_config_has_model is False
|
||||
assert backing_agent.active_config_snapshot_id is not None
|
||||
|
||||
@ -1,5 +1,6 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from models.model import App
|
||||
@ -155,3 +156,83 @@ class TestAgentAppType:
|
||||
app = App()
|
||||
app.mode = AppMode.CHAT
|
||||
assert app.bound_agent_id is None
|
||||
|
||||
def test_update_agent_app_syncs_backing_agent_identity(self):
|
||||
from models.agent import AgentIconType
|
||||
from models.model import AppMode, IconType
|
||||
from services.app_service import AppService
|
||||
|
||||
app = SimpleNamespace(
|
||||
id="app-1",
|
||||
tenant_id="tenant-1",
|
||||
mode=AppMode.AGENT,
|
||||
name="Old",
|
||||
description="old",
|
||||
icon_type=IconType.EMOJI,
|
||||
icon="robot",
|
||||
icon_background="#fff",
|
||||
use_icon_as_answer_icon=False,
|
||||
max_active_requests=None,
|
||||
created_by="account-1",
|
||||
)
|
||||
backing_agent = SimpleNamespace(
|
||||
name="Old",
|
||||
description="old",
|
||||
icon_type=AgentIconType.EMOJI,
|
||||
icon="robot",
|
||||
icon_background="#fff",
|
||||
updated_by=None,
|
||||
updated_at=None,
|
||||
)
|
||||
|
||||
with (
|
||||
patch("services.app_service.db") as mock_db,
|
||||
patch("services.app_service.current_user", SimpleNamespace(id="account-2")),
|
||||
):
|
||||
mock_db.session.scalar.return_value = backing_agent
|
||||
updated_app = AppService().update_app(
|
||||
app, # type: ignore[arg-type]
|
||||
{
|
||||
"name": "Iris",
|
||||
"description": "agent app",
|
||||
"icon_type": "image",
|
||||
"icon": "file-id",
|
||||
"icon_background": "#123456",
|
||||
"use_icon_as_answer_icon": False,
|
||||
"max_active_requests": 0,
|
||||
},
|
||||
)
|
||||
|
||||
assert updated_app.name == "Iris"
|
||||
assert backing_agent.name == "Iris"
|
||||
assert backing_agent.description == "agent app"
|
||||
assert backing_agent.icon_type == AgentIconType.IMAGE
|
||||
assert backing_agent.icon == "file-id"
|
||||
assert backing_agent.icon_background == "#123456"
|
||||
assert backing_agent.updated_by == "account-2"
|
||||
assert backing_agent.updated_at == updated_app.updated_at
|
||||
|
||||
def test_delete_agent_app_archives_backing_agent(self):
|
||||
from models.agent import AgentStatus
|
||||
from models.model import AppMode
|
||||
from services.app_service import AppService
|
||||
|
||||
app = SimpleNamespace(id="app-1", tenant_id="tenant-1", mode=AppMode.AGENT)
|
||||
backing_agent = SimpleNamespace(status=AgentStatus.ACTIVE, archived_by=None, archived_at=None)
|
||||
|
||||
with (
|
||||
patch("services.app_service.db") as mock_db,
|
||||
patch("services.app_service.current_user", SimpleNamespace(id="account-2")),
|
||||
patch("services.app_service.BillingService"),
|
||||
patch("services.app_service.EnterpriseService"),
|
||||
patch("services.app_service.FeatureService"),
|
||||
patch("services.app_service.dify_config"),
|
||||
patch("services.app_service.remove_app_and_related_data_task"),
|
||||
):
|
||||
mock_db.session.scalar.return_value = backing_agent
|
||||
AppService().delete_app(app) # type: ignore[arg-type]
|
||||
|
||||
assert backing_agent.status == AgentStatus.ARCHIVED
|
||||
assert backing_agent.archived_by == "account-2"
|
||||
assert backing_agent.archived_at is not None
|
||||
mock_db.session.delete.assert_called_once_with(app)
|
||||
|
||||
@ -4,8 +4,6 @@ import { oc } from '@orpc/contract'
|
||||
import * as z from 'zod'
|
||||
|
||||
import {
|
||||
zDeleteAgentsByAgentIdPath,
|
||||
zDeleteAgentsByAgentIdResponse,
|
||||
zGetAgentsByAgentIdPath,
|
||||
zGetAgentsByAgentIdResponse,
|
||||
zGetAgentsByAgentIdVersionsByVersionIdPath,
|
||||
@ -16,11 +14,6 @@ import {
|
||||
zGetAgentsInviteOptionsResponse,
|
||||
zGetAgentsQuery,
|
||||
zGetAgentsResponse,
|
||||
zPatchAgentsByAgentIdBody,
|
||||
zPatchAgentsByAgentIdPath,
|
||||
zPatchAgentsByAgentIdResponse,
|
||||
zPostAgentsBody,
|
||||
zPostAgentsResponse,
|
||||
} from './zod.gen'
|
||||
|
||||
export const get = oc
|
||||
@ -69,18 +62,6 @@ export const versions = {
|
||||
byVersionId,
|
||||
}
|
||||
|
||||
export const delete_ = oc
|
||||
.route({
|
||||
inputStructure: 'detailed',
|
||||
method: 'DELETE',
|
||||
operationId: 'deleteAgentsByAgentId',
|
||||
path: '/agents/{agent_id}',
|
||||
successStatus: 204,
|
||||
tags: ['console'],
|
||||
})
|
||||
.input(z.object({ params: zDeleteAgentsByAgentIdPath }))
|
||||
.output(zDeleteAgentsByAgentIdResponse)
|
||||
|
||||
export const get4 = oc
|
||||
.route({
|
||||
inputStructure: 'detailed',
|
||||
@ -92,21 +73,8 @@ export const get4 = oc
|
||||
.input(z.object({ params: zGetAgentsByAgentIdPath }))
|
||||
.output(zGetAgentsByAgentIdResponse)
|
||||
|
||||
export const patch = oc
|
||||
.route({
|
||||
inputStructure: 'detailed',
|
||||
method: 'PATCH',
|
||||
operationId: 'patchAgentsByAgentId',
|
||||
path: '/agents/{agent_id}',
|
||||
tags: ['console'],
|
||||
})
|
||||
.input(z.object({ body: zPatchAgentsByAgentIdBody, params: zPatchAgentsByAgentIdPath }))
|
||||
.output(zPatchAgentsByAgentIdResponse)
|
||||
|
||||
export const byAgentId = {
|
||||
delete: delete_,
|
||||
get: get4,
|
||||
patch,
|
||||
versions,
|
||||
}
|
||||
|
||||
@ -121,21 +89,8 @@ export const get5 = oc
|
||||
.input(z.object({ query: zGetAgentsQuery.optional() }))
|
||||
.output(zGetAgentsResponse)
|
||||
|
||||
export const post = oc
|
||||
.route({
|
||||
inputStructure: 'detailed',
|
||||
method: 'POST',
|
||||
operationId: 'postAgents',
|
||||
path: '/agents',
|
||||
successStatus: 201,
|
||||
tags: ['console'],
|
||||
})
|
||||
.input(z.object({ body: zPostAgentsBody }))
|
||||
.output(zPostAgentsResponse)
|
||||
|
||||
export const agents = {
|
||||
get: get5,
|
||||
post,
|
||||
inviteOptions,
|
||||
byAgentId,
|
||||
}
|
||||
|
||||
@ -12,15 +12,12 @@ export type AgentRosterListResponse = {
|
||||
total: number
|
||||
}
|
||||
|
||||
export type RosterAgentCreatePayload = {
|
||||
agent_soul?: AgentSoulConfig
|
||||
description?: string
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: AgentIconType | null
|
||||
name: string
|
||||
role?: string
|
||||
version_note?: string | null
|
||||
export type AgentInviteOptionsResponse = {
|
||||
data: Array<AgentInviteOptionResponse>
|
||||
has_more: boolean
|
||||
limit: number
|
||||
page: number
|
||||
total: number
|
||||
}
|
||||
|
||||
export type AgentRosterResponse = {
|
||||
@ -51,23 +48,6 @@ export type AgentRosterResponse = {
|
||||
workflow_node_id?: string | null
|
||||
}
|
||||
|
||||
export type AgentInviteOptionsResponse = {
|
||||
data: Array<AgentInviteOptionResponse>
|
||||
has_more: boolean
|
||||
limit: number
|
||||
page: number
|
||||
total: number
|
||||
}
|
||||
|
||||
export type RosterAgentUpdatePayload = {
|
||||
description?: string | null
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
icon_type?: AgentIconType | null
|
||||
name?: string | null
|
||||
role?: string | null
|
||||
}
|
||||
|
||||
export type AgentConfigSnapshotListResponse = {
|
||||
data: Array<AgentConfigSnapshotSummaryResponse>
|
||||
}
|
||||
@ -84,51 +64,6 @@ export type AgentConfigSnapshotDetailResponse = {
|
||||
version_note?: string | null
|
||||
}
|
||||
|
||||
export type AgentSoulConfig = {
|
||||
app_features?: AgentSoulAppFeaturesConfig
|
||||
app_variables?: Array<AppVariableConfig>
|
||||
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 AgentIconType = 'emoji' | 'image' | 'link'
|
||||
|
||||
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 AgentPublishedReferenceResponse = {
|
||||
app_id: string
|
||||
app_mode: string
|
||||
app_name: string
|
||||
node_ids?: Array<string>
|
||||
workflow_id: string
|
||||
workflow_version: string
|
||||
}
|
||||
|
||||
export type AgentScope = 'roster' | 'workflow_only'
|
||||
|
||||
export type AgentSource = 'agent_app' | 'imported' | 'system' | 'workflow'
|
||||
|
||||
export type AgentStatus = 'active' | 'archived'
|
||||
|
||||
export type AgentInviteOptionResponse = {
|
||||
active_config_snapshot?: AgentConfigSnapshotSummaryResponse | null
|
||||
active_config_snapshot_id?: string | null
|
||||
@ -160,6 +95,51 @@ export type AgentInviteOptionResponse = {
|
||||
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<string>
|
||||
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<AppVariableConfig>
|
||||
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
|
||||
@ -538,19 +518,6 @@ export type GetAgentsResponses = {
|
||||
|
||||
export type GetAgentsResponse = GetAgentsResponses[keyof GetAgentsResponses]
|
||||
|
||||
export type PostAgentsData = {
|
||||
body: RosterAgentCreatePayload
|
||||
path?: never
|
||||
query?: never
|
||||
url: '/agents'
|
||||
}
|
||||
|
||||
export type PostAgentsResponses = {
|
||||
201: AgentRosterResponse
|
||||
}
|
||||
|
||||
export type PostAgentsResponse = PostAgentsResponses[keyof PostAgentsResponses]
|
||||
|
||||
export type GetAgentsInviteOptionsData = {
|
||||
body?: never
|
||||
path?: never
|
||||
@ -570,22 +537,6 @@ export type GetAgentsInviteOptionsResponses = {
|
||||
export type GetAgentsInviteOptionsResponse
|
||||
= GetAgentsInviteOptionsResponses[keyof GetAgentsInviteOptionsResponses]
|
||||
|
||||
export type DeleteAgentsByAgentIdData = {
|
||||
body?: never
|
||||
path: {
|
||||
agent_id: string
|
||||
}
|
||||
query?: never
|
||||
url: '/agents/{agent_id}'
|
||||
}
|
||||
|
||||
export type DeleteAgentsByAgentIdResponses = {
|
||||
204: void
|
||||
}
|
||||
|
||||
export type DeleteAgentsByAgentIdResponse
|
||||
= DeleteAgentsByAgentIdResponses[keyof DeleteAgentsByAgentIdResponses]
|
||||
|
||||
export type GetAgentsByAgentIdData = {
|
||||
body?: never
|
||||
path: {
|
||||
@ -602,22 +553,6 @@ export type GetAgentsByAgentIdResponses = {
|
||||
export type GetAgentsByAgentIdResponse
|
||||
= GetAgentsByAgentIdResponses[keyof GetAgentsByAgentIdResponses]
|
||||
|
||||
export type PatchAgentsByAgentIdData = {
|
||||
body: RosterAgentUpdatePayload
|
||||
path: {
|
||||
agent_id: string
|
||||
}
|
||||
query?: never
|
||||
url: '/agents/{agent_id}'
|
||||
}
|
||||
|
||||
export type PatchAgentsByAgentIdResponses = {
|
||||
200: AgentRosterResponse
|
||||
}
|
||||
|
||||
export type PatchAgentsByAgentIdResponse
|
||||
= PatchAgentsByAgentIdResponses[keyof PatchAgentsByAgentIdResponses]
|
||||
|
||||
export type GetAgentsByAgentIdVersionsData = {
|
||||
body?: never
|
||||
path: {
|
||||
|
||||
@ -2,25 +2,6 @@
|
||||
|
||||
import * as z from 'zod'
|
||||
|
||||
/**
|
||||
* AgentIconType
|
||||
*
|
||||
* Supported icon storage formats for Agent roster entries.
|
||||
*/
|
||||
export const zAgentIconType = z.enum(['emoji', 'image', 'link'])
|
||||
|
||||
/**
|
||||
* RosterAgentUpdatePayload
|
||||
*/
|
||||
export const zRosterAgentUpdatePayload = z.object({
|
||||
description: z.string().nullish(),
|
||||
icon: z.string().max(255).nullish(),
|
||||
icon_background: z.string().max(255).nullish(),
|
||||
icon_type: zAgentIconType.nullish(),
|
||||
name: z.string().min(1).max(255).nullish(),
|
||||
role: z.string().max(255).nullish(),
|
||||
})
|
||||
|
||||
/**
|
||||
* AgentConfigSnapshotSummaryResponse
|
||||
*/
|
||||
@ -51,6 +32,13 @@ export const zAgentConfigSnapshotListResponse = z.object({
|
||||
*/
|
||||
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
|
||||
*/
|
||||
@ -75,7 +63,7 @@ export const zAgentScope = z.enum(['roster', 'workflow_only'])
|
||||
*
|
||||
* Origin that created or imported the Agent.
|
||||
*/
|
||||
export const zAgentSource = z.enum(['agent_app', 'imported', 'system', 'workflow'])
|
||||
export const zAgentSource = z.enum(['agent_app', 'imported', 'roster', 'system', 'workflow'])
|
||||
|
||||
/**
|
||||
* AgentStatus
|
||||
@ -688,20 +676,6 @@ export const zAgentSoulConfig = z.object({
|
||||
tools: zAgentSoulToolsConfig.optional(),
|
||||
})
|
||||
|
||||
/**
|
||||
* RosterAgentCreatePayload
|
||||
*/
|
||||
export const zRosterAgentCreatePayload = z.object({
|
||||
agent_soul: zAgentSoulConfig.optional(),
|
||||
description: z.string().optional().default(''),
|
||||
icon: z.string().max(255).nullish(),
|
||||
icon_background: z.string().max(255).nullish(),
|
||||
icon_type: zAgentIconType.nullish(),
|
||||
name: z.string().min(1).max(255),
|
||||
role: z.string().max(255).optional().default(''),
|
||||
version_note: z.string().nullish(),
|
||||
})
|
||||
|
||||
/**
|
||||
* AgentConfigSnapshotDetailResponse
|
||||
*/
|
||||
@ -728,13 +702,6 @@ export const zGetAgentsQuery = z.object({
|
||||
*/
|
||||
export const zGetAgentsResponse = zAgentRosterListResponse
|
||||
|
||||
export const zPostAgentsBody = zRosterAgentCreatePayload
|
||||
|
||||
/**
|
||||
* Agent created
|
||||
*/
|
||||
export const zPostAgentsResponse = zAgentRosterResponse
|
||||
|
||||
export const zGetAgentsInviteOptionsQuery = z.object({
|
||||
app_id: z.string().optional(),
|
||||
keyword: z.string().optional(),
|
||||
@ -747,15 +714,6 @@ export const zGetAgentsInviteOptionsQuery = z.object({
|
||||
*/
|
||||
export const zGetAgentsInviteOptionsResponse = zAgentInviteOptionsResponse
|
||||
|
||||
export const zDeleteAgentsByAgentIdPath = z.object({
|
||||
agent_id: z.string(),
|
||||
})
|
||||
|
||||
/**
|
||||
* Agent archived
|
||||
*/
|
||||
export const zDeleteAgentsByAgentIdResponse = z.void()
|
||||
|
||||
export const zGetAgentsByAgentIdPath = z.object({
|
||||
agent_id: z.string(),
|
||||
})
|
||||
@ -765,17 +723,6 @@ export const zGetAgentsByAgentIdPath = z.object({
|
||||
*/
|
||||
export const zGetAgentsByAgentIdResponse = zAgentRosterResponse
|
||||
|
||||
export const zPatchAgentsByAgentIdBody = zRosterAgentUpdatePayload
|
||||
|
||||
export const zPatchAgentsByAgentIdPath = z.object({
|
||||
agent_id: z.string(),
|
||||
})
|
||||
|
||||
/**
|
||||
* Agent updated
|
||||
*/
|
||||
export const zPatchAgentsByAgentIdResponse = zAgentRosterResponse
|
||||
|
||||
export const zGetAgentsByAgentIdVersionsPath = z.object({
|
||||
agent_id: z.string(),
|
||||
})
|
||||
|
||||
@ -21,19 +21,25 @@ export type CreateAppPayload = {
|
||||
name: string
|
||||
}
|
||||
|
||||
export type AppDetail = {
|
||||
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
|
||||
deleted_tools?: Array<DeletedTool>
|
||||
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_compatible_with_agent: string
|
||||
name: string
|
||||
site?: Site | null
|
||||
tags?: Array<Tag>
|
||||
tracing?: JsonValue | null
|
||||
updated_at?: number | null
|
||||
@ -76,33 +82,6 @@ export type WorkflowOnlineUsersResponse = {
|
||||
data: Array<WorkflowOnlineUsersByApp>
|
||||
}
|
||||
|
||||
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
|
||||
deleted_tools?: Array<DeletedTool>
|
||||
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_compatible_with_agent: string
|
||||
name: string
|
||||
site?: Site | null
|
||||
tags?: Array<Tag>
|
||||
tracing?: JsonValue | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
use_icon_as_answer_icon?: boolean | null
|
||||
workflow?: WorkflowPartial | null
|
||||
}
|
||||
|
||||
export type UpdateAppPayload = {
|
||||
description?: string | null
|
||||
icon?: string | null
|
||||
@ -404,6 +383,27 @@ export type AppApiStatusPayload = {
|
||||
enable_api: boolean
|
||||
}
|
||||
|
||||
export type AppDetail = {
|
||||
access_mode?: string | null
|
||||
app_model_config?: ModelConfig | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
description?: string | null
|
||||
enable_api: boolean
|
||||
enable_site: boolean
|
||||
icon?: string | null
|
||||
icon_background?: string | null
|
||||
id: string
|
||||
mode_compatible_with_agent: string
|
||||
name: string
|
||||
tags?: Array<Tag>
|
||||
tracing?: JsonValue | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
use_icon_as_answer_icon?: boolean | null
|
||||
workflow?: WorkflowPartial | null
|
||||
}
|
||||
|
||||
export type AudioTranscriptResponse = {
|
||||
text: string
|
||||
}
|
||||
@ -1212,6 +1212,29 @@ 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
|
||||
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
|
||||
@ -1250,29 +1273,6 @@ export type WorkflowOnlineUsersByApp = {
|
||||
users: Array<WorkflowOnlineUser>
|
||||
}
|
||||
|
||||
export type DeletedTool = {
|
||||
provider_id: string
|
||||
tool_name: string
|
||||
type: 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 AdvancedChatWorkflowRunForListResponse = {
|
||||
conversation_id?: string | null
|
||||
created_at?: number | null
|
||||
@ -2707,7 +2707,7 @@ export type PostAppsErrors = {
|
||||
}
|
||||
|
||||
export type PostAppsResponses = {
|
||||
201: AppDetail
|
||||
201: AppDetailWithSite
|
||||
}
|
||||
|
||||
export type PostAppsResponse = PostAppsResponses[keyof PostAppsResponses]
|
||||
|
||||
@ -834,6 +834,35 @@ export const zAppIconPayload = z.object({
|
||||
icon_type: zIconType.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
|
||||
*/
|
||||
@ -888,35 +917,6 @@ export const zImport = z.object({
|
||||
status: zImportStatus,
|
||||
})
|
||||
|
||||
/**
|
||||
* 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(),
|
||||
})
|
||||
|
||||
/**
|
||||
* AgentConfigSnapshotSummaryResponse
|
||||
*/
|
||||
@ -2038,30 +2038,6 @@ export const zModelConfig = z.object({
|
||||
provider: z.string(),
|
||||
})
|
||||
|
||||
/**
|
||||
* AppDetail
|
||||
*/
|
||||
export const zAppDetail = z.object({
|
||||
access_mode: z.string().nullish(),
|
||||
app_model_config: zModelConfig.nullish(),
|
||||
created_at: z.int().nullish(),
|
||||
created_by: z.string().nullish(),
|
||||
description: z.string().nullish(),
|
||||
enable_api: z.boolean(),
|
||||
enable_site: z.boolean(),
|
||||
icon: z.string().nullish(),
|
||||
icon_background: z.string().nullish(),
|
||||
id: z.string(),
|
||||
mode_compatible_with_agent: z.string(),
|
||||
name: z.string(),
|
||||
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(),
|
||||
})
|
||||
|
||||
/**
|
||||
* AppDetailWithSite
|
||||
*/
|
||||
@ -2092,6 +2068,30 @@ export const zAppDetailWithSite = z.object({
|
||||
workflow: zWorkflowPartial.nullish(),
|
||||
})
|
||||
|
||||
/**
|
||||
* AppDetail
|
||||
*/
|
||||
export const zAppDetail = z.object({
|
||||
access_mode: z.string().nullish(),
|
||||
app_model_config: zModelConfig.nullish(),
|
||||
created_at: z.int().nullish(),
|
||||
created_by: z.string().nullish(),
|
||||
description: z.string().nullish(),
|
||||
enable_api: z.boolean(),
|
||||
enable_site: z.boolean(),
|
||||
icon: z.string().nullish(),
|
||||
icon_background: z.string().nullish(),
|
||||
id: z.string(),
|
||||
mode_compatible_with_agent: z.string(),
|
||||
name: z.string(),
|
||||
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(),
|
||||
})
|
||||
|
||||
/**
|
||||
* ConversationDetail
|
||||
*/
|
||||
@ -3638,7 +3638,7 @@ export const zPostAppsBody = zCreateAppPayload
|
||||
/**
|
||||
* App created successfully
|
||||
*/
|
||||
export const zPostAppsResponse = zAppDetail
|
||||
export const zPostAppsResponse = zAppDetailWithSite
|
||||
|
||||
export const zPostAppsImportsBody = zAppImportPayload
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user