mirror of
https://github.com/langgenius/dify.git
synced 2026-06-07 16:13:59 +08:00
fix(api): return agent timestamps as epoch seconds (#37057)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
parent
f0fd7ddb60
commit
f9320b2c91
@ -37,7 +37,7 @@ class AgentConfigSnapshotSummaryResponse(ResponseModel):
|
||||
summary: str | None = None
|
||||
version_note: str | None = None
|
||||
created_by: str | None = None
|
||||
created_at: str | None = None
|
||||
created_at: int | None = None
|
||||
|
||||
|
||||
class AgentRosterResponse(ResponseModel):
|
||||
@ -59,9 +59,9 @@ class AgentRosterResponse(ResponseModel):
|
||||
created_by: str | None = None
|
||||
updated_by: str | None = None
|
||||
archived_by: str | None = None
|
||||
archived_at: str | None = None
|
||||
created_at: str | None = None
|
||||
updated_at: str | None = None
|
||||
archived_at: int | None = None
|
||||
created_at: int | None = None
|
||||
updated_at: int | None = None
|
||||
|
||||
|
||||
class AgentInviteOptionResponse(AgentRosterResponse):
|
||||
@ -95,7 +95,7 @@ class AgentConfigRevisionResponse(ResponseModel):
|
||||
summary: str | None = None
|
||||
version_note: str | None = None
|
||||
created_by: str | None = None
|
||||
created_at: str | None = None
|
||||
created_at: int | None = None
|
||||
|
||||
|
||||
class AgentConfigSnapshotDetailResponse(AgentConfigSnapshotSummaryResponse):
|
||||
|
||||
@ -11058,7 +11058,7 @@ Audit operation recorded for Agent Soul version/revision changes.
|
||||
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| created_at | string | | No |
|
||||
| created_at | integer | | No |
|
||||
| created_by | string | | No |
|
||||
| current_snapshot_id | string | | Yes |
|
||||
| id | string | | Yes |
|
||||
@ -11074,7 +11074,7 @@ Audit operation recorded for Agent Soul version/revision changes.
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| agent_id | string | | No |
|
||||
| config_snapshot | [AgentSoulConfig](#agentsoulconfig) | | Yes |
|
||||
| created_at | string | | No |
|
||||
| created_at | integer | | No |
|
||||
| created_by | string | | No |
|
||||
| id | string | | Yes |
|
||||
| revisions | [ [AgentConfigRevisionResponse](#agentconfigrevisionresponse) ] | | No |
|
||||
@ -11093,7 +11093,7 @@ Audit operation recorded for Agent Soul version/revision changes.
|
||||
| Name | Type | Description | Required |
|
||||
| ---- | ---- | ----------- | -------- |
|
||||
| agent_id | string | | No |
|
||||
| created_at | string | | No |
|
||||
| created_at | integer | | No |
|
||||
| created_by | string | | No |
|
||||
| id | string | | Yes |
|
||||
| summary | string | | No |
|
||||
@ -11165,9 +11165,9 @@ Supported icon storage formats for Agent roster entries.
|
||||
| active_config_snapshot_id | string | | No |
|
||||
| agent_kind | [AgentKind](#agentkind) | | Yes |
|
||||
| app_id | string | | No |
|
||||
| archived_at | string | | No |
|
||||
| archived_at | integer | | No |
|
||||
| archived_by | string | | No |
|
||||
| created_at | string | | No |
|
||||
| created_at | integer | | No |
|
||||
| created_by | string | | No |
|
||||
| description | string | | Yes |
|
||||
| existing_node_ids | [ string ] | | No |
|
||||
@ -11181,7 +11181,7 @@ Supported icon storage formats for Agent roster entries.
|
||||
| scope | [AgentScope](#agentscope) | | Yes |
|
||||
| source | [AgentSource](#agentsource) | | Yes |
|
||||
| status | [AgentStatus](#agentstatus) | | Yes |
|
||||
| updated_at | string | | No |
|
||||
| updated_at | integer | | No |
|
||||
| updated_by | string | | No |
|
||||
| workflow_id | string | | No |
|
||||
| workflow_node_id | string | | No |
|
||||
@ -11311,9 +11311,9 @@ the current roster/workflow APIs scoped to Dify Agent.
|
||||
| active_config_snapshot_id | string | | No |
|
||||
| agent_kind | [AgentKind](#agentkind) | | Yes |
|
||||
| app_id | string | | No |
|
||||
| archived_at | string | | No |
|
||||
| archived_at | integer | | No |
|
||||
| archived_by | string | | No |
|
||||
| created_at | string | | No |
|
||||
| created_at | integer | | No |
|
||||
| created_by | string | | No |
|
||||
| description | string | | Yes |
|
||||
| icon | string | | No |
|
||||
@ -11324,7 +11324,7 @@ the current roster/workflow APIs scoped to Dify Agent.
|
||||
| scope | [AgentScope](#agentscope) | | Yes |
|
||||
| source | [AgentSource](#agentsource) | | Yes |
|
||||
| status | [AgentStatus](#agentstatus) | | Yes |
|
||||
| updated_at | string | | No |
|
||||
| updated_at | integer | | No |
|
||||
| updated_by | string | | No |
|
||||
| workflow_id | string | | No |
|
||||
| workflow_node_id | string | | No |
|
||||
|
||||
@ -4,6 +4,7 @@ from sqlalchemy import func, select
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from extensions.ext_database import db
|
||||
from libs.helper import to_timestamp
|
||||
from models.agent import (
|
||||
Agent,
|
||||
AgentConfigRevision,
|
||||
@ -802,7 +803,7 @@ class AgentComposerService:
|
||||
"version": version.version,
|
||||
"version_note": version.version_note,
|
||||
"created_by": version.created_by,
|
||||
"created_at": version.created_at.isoformat() if version.created_at else None,
|
||||
"created_at": to_timestamp(version.created_at),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
|
||||
@ -4,6 +4,7 @@ from sqlalchemy import func, select
|
||||
from sqlalchemy.exc import IntegrityError
|
||||
|
||||
from libs.datetime_utils import naive_utc_now
|
||||
from libs.helper import to_timestamp
|
||||
from models.agent import (
|
||||
Agent,
|
||||
AgentConfigRevision,
|
||||
@ -64,9 +65,9 @@ class AgentRosterService:
|
||||
"created_by": agent.created_by,
|
||||
"updated_by": agent.updated_by,
|
||||
"archived_by": agent.archived_by,
|
||||
"archived_at": agent.archived_at.isoformat() if agent.archived_at else None,
|
||||
"created_at": agent.created_at.isoformat() if agent.created_at else None,
|
||||
"updated_at": agent.updated_at.isoformat() if agent.updated_at else None,
|
||||
"archived_at": to_timestamp(agent.archived_at),
|
||||
"created_at": to_timestamp(agent.created_at),
|
||||
"updated_at": to_timestamp(agent.updated_at),
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
@ -80,7 +81,7 @@ class AgentRosterService:
|
||||
"summary": version.summary,
|
||||
"version_note": version.version_note,
|
||||
"created_by": version.created_by,
|
||||
"created_at": version.created_at.isoformat() if version.created_at else None,
|
||||
"created_at": to_timestamp(version.created_at),
|
||||
}
|
||||
|
||||
def list_roster_agents(
|
||||
@ -418,7 +419,7 @@ class AgentRosterService:
|
||||
"summary": revision.summary,
|
||||
"version_note": revision.version_note,
|
||||
"created_by": revision.created_by,
|
||||
"created_at": revision.created_at.isoformat() if revision.created_at else None,
|
||||
"created_at": to_timestamp(revision.created_at),
|
||||
}
|
||||
for revision in revisions
|
||||
]
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
from datetime import UTC, datetime
|
||||
from types import SimpleNamespace
|
||||
|
||||
import pytest
|
||||
@ -495,6 +496,9 @@ def test_composer_current_version_and_error_paths(monkeypatch):
|
||||
|
||||
|
||||
def test_roster_list_and_invite_options(monkeypatch):
|
||||
created_at = datetime(2026, 1, 2, 3, 4, 5, tzinfo=UTC)
|
||||
updated_at = datetime(2026, 1, 3, 3, 4, 5, tzinfo=UTC)
|
||||
version_created_at = datetime(2026, 1, 4, 3, 4, 5, tzinfo=UTC)
|
||||
agent = Agent(
|
||||
id="agent-1",
|
||||
tenant_id="tenant-1",
|
||||
@ -505,7 +509,10 @@ def test_roster_list_and_invite_options(monkeypatch):
|
||||
source=AgentSource.AGENT_APP,
|
||||
status=AgentStatus.ACTIVE,
|
||||
)
|
||||
agent.created_at = created_at
|
||||
agent.updated_at = updated_at
|
||||
version = AgentConfigSnapshot(id="version-1", agent_id="agent-1", version=1)
|
||||
version.created_at = version_created_at
|
||||
agent.active_config_snapshot_id = "version-1"
|
||||
fake_session = FakeSession(
|
||||
scalar=[1, 1, SimpleNamespace(id="workflow-1")],
|
||||
@ -518,13 +525,30 @@ def test_roster_list_and_invite_options(monkeypatch):
|
||||
invited = service.list_invite_options(tenant_id="tenant-1", page=1, limit=20, app_id="app-1")
|
||||
|
||||
assert listed["data"][0]["active_config_snapshot"]["id"] == "version-1"
|
||||
assert listed["data"][0]["created_at"] == int(created_at.timestamp())
|
||||
assert listed["data"][0]["updated_at"] == int(updated_at.timestamp())
|
||||
assert listed["data"][0]["active_config_snapshot"]["created_at"] == int(version_created_at.timestamp())
|
||||
assert invited["data"][0]["is_in_current_workflow"] is True
|
||||
assert invited["data"][0]["existing_node_ids"] == ["node-1"]
|
||||
|
||||
|
||||
def test_roster_update_archive_versions_and_detail(monkeypatch):
|
||||
listed_version = AgentConfigSnapshot(id="version-2", agent_id="agent-1", version=2)
|
||||
fake_session = FakeSession(scalars=[[listed_version]])
|
||||
listed_version_created_at = datetime(2026, 1, 5, 3, 4, 5, tzinfo=UTC)
|
||||
listed_version.created_at = listed_version_created_at
|
||||
revision_created_at = datetime(2026, 1, 6, 3, 4, 5, tzinfo=UTC)
|
||||
revision = SimpleNamespace(
|
||||
id="revision-1",
|
||||
previous_snapshot_id=None,
|
||||
current_snapshot_id="version-1",
|
||||
revision=1,
|
||||
operation=AgentConfigRevisionOperation.CREATE_VERSION,
|
||||
summary=None,
|
||||
version_note=None,
|
||||
created_by="account-1",
|
||||
created_at=revision_created_at,
|
||||
)
|
||||
fake_session = FakeSession(scalars=[[listed_version], [revision]])
|
||||
agent = Agent(
|
||||
id="agent-1",
|
||||
tenant_id="tenant-1",
|
||||
@ -536,6 +560,7 @@ def test_roster_update_archive_versions_and_detail(monkeypatch):
|
||||
status=AgentStatus.ACTIVE,
|
||||
)
|
||||
version = AgentConfigSnapshot(id="version-1", agent_id="agent-1", version=1, config_snapshot='{"prompt":{}}')
|
||||
version.created_at = datetime(2026, 1, 4, 3, 4, 5, tzinfo=UTC)
|
||||
|
||||
service = AgentRosterService(fake_session)
|
||||
monkeypatch.setattr(service, "_get_agent", lambda **kwargs: agent)
|
||||
@ -559,7 +584,10 @@ def test_roster_update_archive_versions_and_detail(monkeypatch):
|
||||
assert updated["description"] == "new"
|
||||
assert agent.status == AgentStatus.ARCHIVED
|
||||
assert versions[0]["id"] == "version-2"
|
||||
assert versions[0]["created_at"] == int(listed_version_created_at.timestamp())
|
||||
assert detail["config_snapshot"] == {"prompt": {}}
|
||||
assert detail["created_at"] == int(version.created_at.timestamp())
|
||||
assert detail["revisions"][0]["created_at"] == int(revision_created_at.timestamp())
|
||||
|
||||
|
||||
def test_roster_create_detail_and_lookup_helpers(monkeypatch):
|
||||
|
||||
@ -27,9 +27,9 @@ export type AgentRosterResponse = {
|
||||
active_config_snapshot_id?: string | null
|
||||
agent_kind: AgentKind
|
||||
app_id?: string | null
|
||||
archived_at?: string | null
|
||||
archived_at?: number | null
|
||||
archived_by?: string | null
|
||||
created_at?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
description: string
|
||||
icon?: string | null
|
||||
@ -40,7 +40,7 @@ export type AgentRosterResponse = {
|
||||
scope: AgentScope
|
||||
source: AgentSource
|
||||
status: AgentStatus
|
||||
updated_at?: string | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
workflow_id?: string | null
|
||||
workflow_node_id?: string | null
|
||||
@ -69,7 +69,7 @@ export type AgentConfigSnapshotListResponse = {
|
||||
export type AgentConfigSnapshotDetailResponse = {
|
||||
agent_id?: string | null
|
||||
config_snapshot: AgentSoulConfig
|
||||
created_at?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
id: string
|
||||
revisions?: Array<AgentConfigRevisionResponse>
|
||||
@ -98,7 +98,7 @@ export type AgentIconType = 'emoji' | 'image' | 'link'
|
||||
|
||||
export type AgentConfigSnapshotSummaryResponse = {
|
||||
agent_id?: string | null
|
||||
created_at?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
id: string
|
||||
summary?: string | null
|
||||
@ -119,9 +119,9 @@ export type AgentInviteOptionResponse = {
|
||||
active_config_snapshot_id?: string | null
|
||||
agent_kind: AgentKind
|
||||
app_id?: string | null
|
||||
archived_at?: string | null
|
||||
archived_at?: number | null
|
||||
archived_by?: string | null
|
||||
created_at?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
description: string
|
||||
existing_node_ids?: Array<string>
|
||||
@ -135,14 +135,14 @@ export type AgentInviteOptionResponse = {
|
||||
scope: AgentScope
|
||||
source: AgentSource
|
||||
status: AgentStatus
|
||||
updated_at?: string | null
|
||||
updated_at?: number | null
|
||||
updated_by?: string | null
|
||||
workflow_id?: string | null
|
||||
workflow_node_id?: string | null
|
||||
}
|
||||
|
||||
export type AgentConfigRevisionResponse = {
|
||||
created_at?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
current_snapshot_id: string
|
||||
id: string
|
||||
|
||||
@ -25,7 +25,7 @@ export const zRosterAgentUpdatePayload = z.object({
|
||||
*/
|
||||
export const zAgentConfigSnapshotSummaryResponse = z.object({
|
||||
agent_id: z.string().nullish(),
|
||||
created_at: z.string().nullish(),
|
||||
created_at: z.int().nullish(),
|
||||
created_by: z.string().nullish(),
|
||||
id: z.string(),
|
||||
summary: z.string().nullish(),
|
||||
@ -79,9 +79,9 @@ export const zAgentRosterResponse = z.object({
|
||||
active_config_snapshot_id: z.string().nullish(),
|
||||
agent_kind: zAgentKind,
|
||||
app_id: z.string().nullish(),
|
||||
archived_at: z.string().nullish(),
|
||||
archived_at: z.int().nullish(),
|
||||
archived_by: z.string().nullish(),
|
||||
created_at: z.string().nullish(),
|
||||
created_at: z.int().nullish(),
|
||||
created_by: z.string().nullish(),
|
||||
description: z.string(),
|
||||
icon: z.string().nullish(),
|
||||
@ -92,7 +92,7 @@ export const zAgentRosterResponse = z.object({
|
||||
scope: zAgentScope,
|
||||
source: zAgentSource,
|
||||
status: zAgentStatus,
|
||||
updated_at: z.string().nullish(),
|
||||
updated_at: z.int().nullish(),
|
||||
updated_by: z.string().nullish(),
|
||||
workflow_id: z.string().nullish(),
|
||||
workflow_node_id: z.string().nullish(),
|
||||
@ -117,9 +117,9 @@ export const zAgentInviteOptionResponse = z.object({
|
||||
active_config_snapshot_id: z.string().nullish(),
|
||||
agent_kind: zAgentKind,
|
||||
app_id: z.string().nullish(),
|
||||
archived_at: z.string().nullish(),
|
||||
archived_at: z.int().nullish(),
|
||||
archived_by: z.string().nullish(),
|
||||
created_at: z.string().nullish(),
|
||||
created_at: z.int().nullish(),
|
||||
created_by: z.string().nullish(),
|
||||
description: z.string(),
|
||||
existing_node_ids: z.array(z.string()).optional(),
|
||||
@ -133,7 +133,7 @@ export const zAgentInviteOptionResponse = z.object({
|
||||
scope: zAgentScope,
|
||||
source: zAgentSource,
|
||||
status: zAgentStatus,
|
||||
updated_at: z.string().nullish(),
|
||||
updated_at: z.int().nullish(),
|
||||
updated_by: z.string().nullish(),
|
||||
workflow_id: z.string().nullish(),
|
||||
workflow_node_id: z.string().nullish(),
|
||||
@ -184,7 +184,7 @@ export const zAgentConfigRevisionOperation = z.enum([
|
||||
* AgentConfigRevisionResponse
|
||||
*/
|
||||
export const zAgentConfigRevisionResponse = z.object({
|
||||
created_at: z.string().nullish(),
|
||||
created_at: z.int().nullish(),
|
||||
created_by: z.string().nullish(),
|
||||
current_snapshot_id: z.string(),
|
||||
id: z.string(),
|
||||
@ -591,7 +591,7 @@ export const zRosterAgentCreatePayload = z.object({
|
||||
export const zAgentConfigSnapshotDetailResponse = z.object({
|
||||
agent_id: z.string().nullish(),
|
||||
config_snapshot: zAgentSoulConfig,
|
||||
created_at: z.string().nullish(),
|
||||
created_at: z.int().nullish(),
|
||||
created_by: z.string().nullish(),
|
||||
id: z.string(),
|
||||
revisions: z.array(zAgentConfigRevisionResponse).optional(),
|
||||
|
||||
@ -1034,7 +1034,7 @@ export type AdvancedChatWorkflowRunForListResponse = {
|
||||
|
||||
export type AgentConfigSnapshotSummaryResponse = {
|
||||
agent_id?: string | null
|
||||
created_at?: string | null
|
||||
created_at?: number | null
|
||||
created_by?: string | null
|
||||
id: string
|
||||
summary?: string | null
|
||||
|
||||
@ -753,7 +753,7 @@ export const zSite = z.object({
|
||||
*/
|
||||
export const zAgentConfigSnapshotSummaryResponse = z.object({
|
||||
agent_id: z.string().nullish(),
|
||||
created_at: z.string().nullish(),
|
||||
created_at: z.int().nullish(),
|
||||
created_by: z.string().nullish(),
|
||||
id: z.string(),
|
||||
summary: z.string().nullish(),
|
||||
|
||||
Loading…
Reference in New Issue
Block a user