fix(cron): accept nested GET-response shape in POST /api/cron/jobs (fixes iOfficeAI/AionUi#4042) - #858
Open
cdxiaodong wants to merge 1 commit into
Open
Conversation
The create endpoint rejected every JSON body with 400 "Invalid JSON
request body." because CreateCronJobRequest used #[serde(deny_unknown_fields)]
over a legacy flat schema (top-level message/conversation_id/created_by),
while agents and the CLI build create bodies by mirroring the nested shape
returned by GET /api/cron/jobs (target.payload.text, target.execution_mode,
enabled). The unknown fields tripped deny_unknown_fields and serde rejected
the body before any field validation, so even {} failed. PUT /{id} was
unaffected because UpdateCronJobRequest has no deny_unknown_fields and
all-optional fields.
Make the create DTO accept both shapes:
- add optional target (reusing CronJobTargetDto) and enabled fields
- make conversation_id/created_by optional (created_by defaults to "agent"
in the service layer; conversation_id is still required at the service
layer for existing execution mode)
- drop deny_unknown_fields so a body valid for PUT also deserializes for
create
The service layer normalizes target.payload.text -> message and
target.execution_mode -> execution_mode, with flat fields taking precedence,
and honors the enabled flag instead of hardcoding true.
Fixes iOfficeAI/AionUi#4042
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
问题
POST /api/cron/jobs(创建定时任务)对任何 JSON 请求体都无差别返回400 Invalid JSON request body,包括语法合法的最简 body{}。GET /api/cron/jobs与PUT /api/cron/jobs/{id}均正常,仅 create 失败。这导致所有 agent-facing CLI 创建 cron 任务的通道(aioncore config cron current create/aioncore config cron jobs create)全部不可用。上游 issue:iOfficeAI/AionUi#4042(已在该 issue 评论中附完整复现证据与截图)。
根因
CreateCronJobRequest使用#[serde(deny_unknown_fields)],且仍是旧的扁平 schema(顶层message/ 必填conversation_id/ 必填created_by)。而 agent / CLI 是按
GET /api/cron/jobs返回的嵌套结构反向构造 create body 的:{ "name": ..., "enabled": ..., "schedule": {...}, "target": { "payload": {"kind":"message","text":...}, "execution_mode": "new_conversation" } }其中的
enabled、target等字段在CreateCronJobRequest里不存在 → 触发deny_unknown_fields→ serde 在反序列化第一步即拒绝(后端日志latency_ms=0可证),根本走不到字段校验。PUT /{id}正常,正是因为UpdateCronJobRequest没有deny_unknown_fields且字段全为Option。修复
让 create DTO 同时兼容两种结构(向后兼容,旧扁平调用方不受影响):
CreateCronJobRequest新增可选target(复用现有CronJobTargetDto)与enabled字段conversation_id/created_by改为可选:created_by在 service 层默认"agent";conversation_id在existing执行模式下仍由 service 层强制校验(行为不变)deny_unknown_fields:未知字段忽略而非 400,使对 PUT 合法的 body 也能用于 createtarget.payload.text→message、target.execution_mode→execution_mode(扁平字段优先);enabled默认值true保持原有行为,不再硬编码测试
create_request_nested_response_shape(嵌套结构可反序列化)、create_request_ignores_unknown_fields(未知字段不拒绝)missing_conversation_id/missing_created_by/legacy_agent_type)以匹配新行为cargo test -p aionui-api-types --lib cron:22 passedcargo test -p aionui-cron:280 passed, 0 failedcargo clippy/cargo fmt --check:无警告兼容性
完全向后兼容:原有扁平 body(含
conversation_id/created_by/ 顶层message)照常工作;新增嵌套 body 现在也能正确创建任务,与 GET 响应及 PUT 行为对齐。