feat(整理): 问题在整理记录就地处理,识别失败自动叫智能体识别

- 整理记录「需要处理」:列表 attention 筛选与统计同口径(没被后来的整理取代,且有未关闭事项或失败 / 部分完成未忽略),
  记录带 attention(原因类别、精简事项、能否让智能体识别);忽略端点记 attention_cleared_at(迁移 0078)并关闭关联事项
- 识别失败(organize_identity)按 agent.autoIdentifyOrganize 自动派一次识别会话;新能力 organize.assign_identity
  指定作品后复用人工指定的钩子路径自动重新整理,只放行本事项的识别会话与用户对话;整理记录里可手动「让智能体识别」
- GET /attention:整理需要处理条数、等你批准的智能体操作、系统健康问题(铃铛 / 首页 / 运行状态共用)
- 原因码文案不再指向待处理;命令面板「待处理」换成「需要处理的整理记录」

Co-Authored-By: Claude Opus 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei
This commit is contained in:
rootandClaude Opus 5.5 committed 2026-10-06 16:47:18 +08:00
1 parent 414ea7c890
commit 1c1a954703
25 files changed
+1037 -35

No files matched your search

+58 -1
View File
@@ -1,5 +1,5 @@
import { z } from "zod";
import { AgentRunStatus, DecisionKind } from "./agent.ts";
import { AgentRunStatus, Decision, DecisionKind } from "./agent.ts";
import { AssetLocation, MediaAsset, PathBinding } from "./assets.ts";
import { ActorType, EntityBase, Id, JsonObject, NonNegInt, Timestamp } from "./common.ts";
import { MediaEntity, MediaKind } from "./content.ts";
@@ -73,6 +73,8 @@ export const OrganizationRecord = EntityBase.extend({
startedAt: Timestamp.nullable(),
finishedAt: Timestamp.nullable(),
changeSeq: ChangeSeq,
/** 用户在整理记录里忽略了这条记录的问题(不再算需要处理) */
attentionClearedAt: Timestamp.nullable(),
});
export type OrganizationRecord = z.infer<typeof OrganizationRecord>;
export const OrganizationRecordCreate = OrganizationRecord.pick({
@@ -211,6 +213,32 @@ export const PublicOrganizationFile = z.object({
});
export type PublicOrganizationFile = z.infer<typeof PublicOrganizationFile>;
/** 整理记录关联的未关闭事项(在整理记录里就地处理;选项与「处理」端点同 /decisions/{id}/resolve) */
export const RecordAttentionDecision = Decision.pick({
id: true,
kind: true,
status: true,
title: true,
summary: true,
options: true,
agentRunId: true,
evidence: true,
});
export type RecordAttentionDecision = z.infer<typeof RecordAttentionDecision>;
/**
* 需要处理(2026-10-06 去掉待处理中心后,整理侧的问题在整理记录里就地处理):
* topic:identity = 没识别出作品(可指定作品 / 让智能体识别);conflict = 目标已存在 / 路径冲突(按选项替换、保留两者或跳过);
* other = 其余失败或部分完成(排除、非视频、卡住、执行失败…,重新整理或忽略)。
* agentIdentify:可以让智能体识别(没识别出作品且有关联下载任务)。
*/
export const RecordAttention = z.object({
topic: z.enum(["identity", "conflict", "other"]),
decision: RecordAttentionDecision.nullable(),
agentIdentify: z.boolean(),
});
export type RecordAttention = z.infer<typeof RecordAttention>;
export const PublicOrganizationRecord = z.object({
/** 稳定记录 ID */
id: Id,
@@ -261,6 +289,8 @@ export const PublicOrganizationRecord = z.object({
finishedAt: Timestamp.nullable(),
/** 该记录最近一次变更的游标值;客户端按 id 去重、以最大 changeSeq 续读 */
changeSeq: ChangeCursor,
/** 需要处理时给出原因与可做的动作;不需要为 null(旧客户端可忽略) */
attention: RecordAttention.nullable().optional(),
});
export type PublicOrganizationRecord = z.infer<typeof PublicOrganizationRecord>;
@@ -303,6 +333,13 @@ export const OrganizationListQuery = z.object({
since: Timestamp.optional(),
/** HIS-1:只看整理类记录(复制/移动/硬链接),不含文件管理的改名、删除、还原 */
organizeOnly: z.union([z.boolean(), z.enum(["true", "false"]).transform((v) => v === "true")]).optional(),
/**
* 只看需要处理的记录:有关联的未关闭事项,或失败 / 部分完成、没被同一下载任务后来的整理取代、也没被忽略的
* (口径见 docs/runbook/organize.md「需要处理」)
*/
attention: z
.union([z.boolean(), z.enum(["true", "false", "1", "0"]).transform((v) => v === "true" || v === "1")])
.optional(),
});
export type OrganizationListQuery = z.infer<typeof OrganizationListQuery>;
@@ -317,6 +354,8 @@ export const OrganizationStats = z.object({
/** 排队 + 执行中 */
running: NonNegInt,
cancelled: NonNegInt,
/** 需要处理(同列表 attention=true 的口径,不受状态筛选影响) */
attention: NonNegInt,
});
export type OrganizationStats = z.infer<typeof OrganizationStats>;
@@ -764,3 +803,21 @@ export const OrganizePlanArtifactContent = z.object({
.optional(),
});
export type OrganizePlanArtifactContent = z.infer<typeof OrganizePlanArtifactContent>;
/** 让智能体识别整理记录里的作品(没识别出作品的记录):入队一次识别会话 */
export const OrganizationAgentIdentifyResult = z.object({ decisionId: Id, queued: z.boolean() });
export type OrganizationAgentIdentifyResult = z.infer<typeof OrganizationAgentIdentifyResult>;
/**
* 需要用户关注的汇总(铃铛、首页、运行状态共用):
* - organize:整理记录里需要处理的条数(点进整理记录「需要处理」);
* - approvals:需要你批准的智能体操作(会话里的审批 / 方案选择、计划审批、原站页面等你接手);
* - health:系统健康问题(站点不可达、下载器离线、下载目录读不到容量、磁盘空间不足、媒体库目录离线),恢复后自动消失。
* 集数待确认、未识别资源等不在这里:前者在订阅详情与作品页集数映射里看原因,后者静默留在未识别里。
*/
export const AttentionSummary = z.object({
organize: NonNegInt,
approvals: z.object({ total: NonNegInt, items: z.array(Decision) }),
health: z.object({ total: NonNegInt, items: z.array(Decision) }),
});
export type AttentionSummary = z.infer<typeof AttentionSummary>;