merge: fix/q-inline-handling
Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_01Cxwgnn2pbzQ7rXv3rq7fei # Conflicts: # apps/server/src/modules/sources-identity/service/episode-resolution.ts
This commit is contained in:
commit
c465b533fd
80 files changed
+2766
-1016
No files matched your search
@@ -8,6 +8,7 @@ triggers:
|
||||
- 识别(错|不出)|认错|没识别|对不上作品
|
||||
- 为什么.{0,20}(没|不|还没)
|
||||
capabilities:
|
||||
- catalog.lookup
|
||||
- inventory.query
|
||||
- download.list
|
||||
- download.inspect
|
||||
@@ -18,6 +19,7 @@ capabilities:
|
||||
- organize.execute
|
||||
- metadata.enrich
|
||||
- metadata.resolve_organize
|
||||
- organize.assign_identity
|
||||
sessions: [chat, investigate, child]
|
||||
---
|
||||
|
||||
@@ -33,14 +35,15 @@ sessions: [chat, investigate, child]
|
||||
- 还在下载 / 无进展 → 汇报进度和最近进展时间;
|
||||
- 已完成待整理 / 整理中 → 看关联的核验入库任务(task.inspect 看错误);
|
||||
- 入库失败 → 读整理记录和错误,一句话说原因;
|
||||
- 有「没识别出作品」的待处理事项 → decision.list 确认,说明要用户指定作品。
|
||||
4. 身份问题:资源还没对上作品时可以用 identity.resolve 提出映射;TMDB 查不到的作品,网页搜索开启时用 metadata.enrich 出建议。整理要用的资源连常规识别也对不上作品时,用 metadata.resolve_organize 补全译名重查 TMDB,仍没有合适条目才建立带来源证据的本地作品。
|
||||
- 整理记录「没识别出作品」→ decision.list 确认事项,按下面第 4 步认作品;认出来用 organize.assign_identity 指定(会重新整理),认不出说明要用户在整理记录里指定作品。
|
||||
4. 身份问题:资源还没对上作品时可以用 identity.resolve 提出映射;TMDB 查不到的作品,网页搜索开启时用 metadata.enrich 出建议。整理要用的资源连常规识别也对不上作品时,用 metadata.resolve_organize 补全译名重查 TMDB,仍没有合适条目才建立带来源证据的本地作品。整理时「没识别出作品」的记录(接管任务、文件名认不出):catalog.lookup / inventory.query 核对标题、年份、类型和季集都对得上后,organize.assign_identity 写一次(带依据),系统按该作品重新整理;拿不准不要指定。
|
||||
5. 需要重新整理时:organize.plan 生成计划(不动文件),再 organize.execute。
|
||||
|
||||
## 需要批准
|
||||
|
||||
- organize.execute(执行整理)、identity.resolve(身份映射)需要授权;没有授权时写一句「没做:重新整理,需要你批准」。
|
||||
- organize.plan、查询类不需要批准。
|
||||
- organize.assign_identity(指定整理作品)不需要持续授权:用户对话里可直接用,后台识别会话只能处理它自己那条记录。
|
||||
|
||||
## 汇报模板
|
||||
|
||||
|
||||
@@ -130,6 +130,7 @@ export const INTENT_ROUTES: readonly IntentRoute[] = [
|
||||
{ cap: "web.fetch", note: "读其中一条结果的正文" },
|
||||
{ cap: "metadata.enrich", note: "TMDB 查不到的作品出元数据建议" },
|
||||
{ cap: "metadata.resolve_organize", note: "整理用的资源对不上作品时兜底识别或建本地作品" },
|
||||
{ cap: "organize.assign_identity", note: "整理时没识别出作品:查到作品后指定,随即重新整理" },
|
||||
],
|
||||
},
|
||||
];
|
||||
|
||||
@@ -359,6 +359,23 @@ export type AgentRunChoiceInput = z.infer<typeof AgentRunChoiceInput>;
|
||||
export const AgentRunAbortInput = z.object({ reason: z.string().max(500).optional() });
|
||||
export type AgentRunAbortInput = z.infer<typeof AgentRunAbortInput>;
|
||||
|
||||
/**
|
||||
* 智能体用量(2026-10-06 起不设硬性预算上限,花费改为可见):按会话类型统计次数、token 与费用。
|
||||
* chat = 用户对话;patrol = 智能体巡检;investigate = 待处理事项的后台调查 / 授权内恢复;
|
||||
* organize_identify = 整理没识别出作品时的智能体识别;subagent = 子会话
|
||||
*/
|
||||
export const AgentSpendKind = z.enum(["chat", "patrol", "investigate", "organize_identify", "subagent"]);
|
||||
export type AgentSpendKind = z.infer<typeof AgentSpendKind>;
|
||||
export const AgentSpendBucket = z.object({
|
||||
runs: NonNegInt,
|
||||
tokens: NonNegInt,
|
||||
costUsd: z.number().min(0),
|
||||
byKind: z.array(z.object({ kind: AgentSpendKind, runs: NonNegInt, tokens: NonNegInt, costUsd: z.number().min(0) })),
|
||||
});
|
||||
export type AgentSpendBucket = z.infer<typeof AgentSpendBucket>;
|
||||
export const AgentSpend = z.object({ today: AgentSpendBucket, last7d: AgentSpendBucket });
|
||||
export type AgentSpend = z.infer<typeof AgentSpend>;
|
||||
|
||||
export const AgentRunListQuery = z.object({
|
||||
cursor: z.string().min(1).optional(),
|
||||
limit: z.coerce.number().int().min(1).max(200).default(50),
|
||||
|
||||
@@ -149,6 +149,15 @@ export const libraryApi = {
|
||||
response: organization.Dashboard,
|
||||
}),
|
||||
},
|
||||
attention: {
|
||||
summary: ep({
|
||||
method: "get",
|
||||
path: "/attention",
|
||||
scope: "read",
|
||||
summary: "需要关注的汇总:整理记录需要处理的条数、等你批准的智能体操作、系统健康问题",
|
||||
response: organization.AttentionSummary,
|
||||
}),
|
||||
},
|
||||
downloadCache: {
|
||||
cleanup: ep({
|
||||
method: "post",
|
||||
|
||||
@@ -49,6 +49,22 @@ export const organizeApi = {
|
||||
body: organization.OrganizationDeleteRequest,
|
||||
response: organization.OrganizationDeleteResult,
|
||||
}),
|
||||
dismissAttention: ep({
|
||||
method: "post",
|
||||
path: "/organization-records/{id}/dismiss-attention",
|
||||
scope: "organize.execute",
|
||||
summary: "忽略这条整理记录的问题:不再算需要处理,关联的未关闭事项一并关闭",
|
||||
params: IdParam,
|
||||
response: organization.PublicOrganizationRecord,
|
||||
}),
|
||||
agentIdentify: ep({
|
||||
method: "post",
|
||||
path: "/organization-records/{id}/agent-identify",
|
||||
scope: "organize.execute",
|
||||
summary: "让智能体识别这条整理记录的作品(没识别出作品的记录),认出来自动重新整理",
|
||||
params: IdParam,
|
||||
response: organization.OrganizationAgentIdentifyResult,
|
||||
}),
|
||||
create: ep({
|
||||
method: "post",
|
||||
path: "/organization-records",
|
||||
|
||||
@@ -77,6 +77,13 @@ export const reviewApi = {
|
||||
),
|
||||
/** Agent 会话(W2-D):建 run 只入队持久任务 runAgent;增量经全局 SSE(agent.*),断线按 runSeq 用 afterSeq 补读 */
|
||||
agentRuns: {
|
||||
usage: ep({
|
||||
method: "get",
|
||||
path: "/agent/usage",
|
||||
scope: "read",
|
||||
summary: "智能体用量:今天与最近 7 天按会话类型的次数、token 与费用",
|
||||
response: agent.AgentSpend,
|
||||
}),
|
||||
list: ep({
|
||||
method: "get",
|
||||
path: "/agent/runs",
|
||||
|
||||
@@ -1088,6 +1088,34 @@ export const EpisodeMappingApplyRuleOutput = z.object({
|
||||
decisionStatus: DecisionStatus,
|
||||
});
|
||||
|
||||
/** organize.assign_identity:给「没识别出作品」的整理事项指定作品并重新整理 */
|
||||
/** mediaEntityId 与 tmdb 二选一(都给时用 mediaEntityId,都没给由处理器拒绝) */
|
||||
export const OrganizeAssignIdentityInput = z.object({
|
||||
/** 「没识别出作品」事项 ID(调查目标里给出) */
|
||||
decisionId: Id,
|
||||
mediaEntityId: Id.optional(),
|
||||
tmdb: z
|
||||
.object({
|
||||
type: z.enum(["movie", "tv"]),
|
||||
id: z
|
||||
.string()
|
||||
.trim()
|
||||
.regex(/^\d{1,10}$/),
|
||||
})
|
||||
.optional(),
|
||||
/** 为什么是这个作品(依据),至少一条 */
|
||||
reasons: z.array(z.string().trim().min(1).max(300)).min(1).max(10),
|
||||
});
|
||||
export const OrganizeAssignIdentityOutput = z.object({
|
||||
mediaEntityId: Id,
|
||||
/** 重新整理的记录与状态 */
|
||||
recordId: Id.nullable(),
|
||||
status: z.string(),
|
||||
decisionStatus: DecisionStatus,
|
||||
});
|
||||
export type OrganizeAssignIdentityInput = z.infer<typeof OrganizeAssignIdentityInput>;
|
||||
export type OrganizeAssignIdentityOutput = z.infer<typeof OrganizeAssignIdentityOutput>;
|
||||
|
||||
/** 能力 ID → 输入/输出 schema(server 注册处理器、agent 生成工具定义时共用) */
|
||||
// ── schedule.draft_check:按自然语言需求起草巡检(建成未启用,用户在计划页检查后启用) ──
|
||||
|
||||
@@ -1167,6 +1195,7 @@ export const CAPABILITY_IO = {
|
||||
"episode_mapping.inspect": { input: EpisodeMappingInspectInput, output: EpisodeMappingInspectOutput },
|
||||
"episode_mapping.simulate": { input: EpisodeMappingSimulateInput, output: EpisodeMappingSimulateOutput },
|
||||
"episode_mapping.apply_rule": { input: EpisodeMappingApplyRuleInput, output: EpisodeMappingApplyRuleOutput },
|
||||
"organize.assign_identity": { input: OrganizeAssignIdentityInput, output: OrganizeAssignIdentityOutput },
|
||||
} as const satisfies Record<KnownCapabilityId, { input: z.ZodType; output: z.ZodType }>;
|
||||
|
||||
type CapabilityIo = typeof CAPABILITY_IO;
|
||||
|
||||
@@ -100,6 +100,7 @@ export const CAPABILITY_IDS = [
|
||||
"episode_mapping.inspect",
|
||||
"episode_mapping.simulate",
|
||||
"episode_mapping.apply_rule",
|
||||
"organize.assign_identity",
|
||||
] as const;
|
||||
export const KnownCapabilityId = z.enum(CAPABILITY_IDS);
|
||||
export type KnownCapabilityId = z.infer<typeof KnownCapabilityId>;
|
||||
@@ -668,6 +669,19 @@ export const CAPABILITY_CATALOG: Record<KnownCapabilityId, CapabilityDescriptor>
|
||||
false,
|
||||
true,
|
||||
),
|
||||
// 整理时没识别出作品(organize_identity 事项):智能体查到作品后指定,随即按该作品重新整理
|
||||
"organize.assign_identity": d(
|
||||
"organize.assign_identity",
|
||||
"指定整理作品",
|
||||
"给没识别出作品的整理记录指定作品(本地作品 ID 或 TMDB 类型 + ID),随即按这个作品重新整理。只用于「没识别出作品」事项;先用 catalog.lookup / inventory.query 核对标题、年份、季集,拿不准就不要指定",
|
||||
"execute",
|
||||
"OrganizeAssignIdentity",
|
||||
"organize.execute",
|
||||
"medium",
|
||||
false,
|
||||
false,
|
||||
"never",
|
||||
),
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -733,6 +747,7 @@ export const CAPABILITY_ACTIVITY: Record<KnownCapabilityId, CapabilityActivity>
|
||||
"episode_mapping.inspect": act("查", "集数映射"),
|
||||
"episode_mapping.simulate": act("模拟", "映射规则", "次"),
|
||||
"episode_mapping.apply_rule": act("写入", "映射规则", "条"),
|
||||
"organize.assign_identity": act("指定", "整理作品", "个"),
|
||||
};
|
||||
|
||||
function d(
|
||||
|
||||
@@ -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>;
|
||||
@@ -1,4 +1,4 @@
|
||||
// 内部原因码 → 一句人话 + 下一步(DEAI-2)。整理记录、待处理、下载时间线、任务都用这张表;
|
||||
// 内部原因码 → 一句人话 + 下一步(DEAI-2)。整理记录、下载时间线、任务都用这张表;
|
||||
// 原码只放在界面的「技术信息」里,不直接给人看。不认识的码返回 null,由调用方决定兜底文字。
|
||||
|
||||
export type ReasonText = {
|
||||
@@ -19,9 +19,9 @@ const REASONS: Record<string, ReasonText> = {
|
||||
identity_unresolved: { text: "没识别出作品", action: "指定作品" },
|
||||
episode_mapping: { text: "集数对不上作品的季集", action: "确认集数映射" },
|
||||
episode_unresolved: { text: "集数对不上作品的季集", action: "确认集数映射" },
|
||||
target_exists: { text: "媒体库里已有同名文件", action: "在待处理里选择替换或跳过" },
|
||||
target_exists: { text: "媒体库里已有同名文件", action: "在整理记录里选择替换、保留两者或跳过" },
|
||||
duplicate_target: { text: "改名后与其他文件同名", action: "改命名模板或排除其中一个" },
|
||||
replace_requires_grant: { text: "替换已有文件需要你批准", action: "在待处理里批准" },
|
||||
replace_requires_grant: { text: "替换已有文件需要你批准", action: "在整理记录里选择是否替换" },
|
||||
hnr_unsatisfied: { text: "做种时间还不够,不能移动", action: "改用复制,或等做种完成" },
|
||||
hnr_unknown: { text: "不确定做种要求是否满足", action: "改用复制,或确认站点规则" },
|
||||
orphan_sidecar: { text: "字幕等附属文件找不到对应视频" },
|
||||
@@ -51,7 +51,7 @@ const REASONS: Record<string, ReasonText> = {
|
||||
downloader_unavailable: { text: "下载器连不上", action: "在设置 → 下载器里测试连接" },
|
||||
downloader_error: { text: "下载器报错", action: "查看下载器日志" },
|
||||
// DL-2b:下载面板整理状态、下载计划里出现的码
|
||||
blocked: { text: "有冲突要先处理", action: "去待处理" },
|
||||
blocked: { text: "有冲突要先处理", action: "在整理记录里处理" },
|
||||
blocked_by_conflict: { text: "有冲突,暂不整理" },
|
||||
transfer_failed: { text: "文件没有整理成功", action: "在整理记录里查看失败的文件" },
|
||||
main_failed: { text: "主文件整理失败,附属文件一起跳过" },
|
||||
|
||||
@@ -208,10 +208,12 @@ export const AgentRuntimeSettings = z.object({
|
||||
.int()
|
||||
.min(10)
|
||||
.max(24 * 3600),
|
||||
/** 单次运行:token 上限(null = 不限) */
|
||||
maxTokensPerRun: z.number().int().positive().nullable(),
|
||||
/** 单次运行:费用上限(美元,null = 不限) */
|
||||
maxCostUsdPerRun: z.number().positive().nullable(),
|
||||
/** 已弃用(2026-10-06 起不限 token,旧值兼容读取、不生效) */
|
||||
maxTokensPerRun: z.number().int().positive().nullable().optional(),
|
||||
/** 已弃用(2026-10-06 起不限单次费用,旧值兼容读取、不生效) */
|
||||
maxCostUsdPerRun: z.number().positive().nullable().optional(),
|
||||
/** 整理时没识别出作品:自动派智能体识别一次,认出来就按该作品重新整理(不需要持续授权) */
|
||||
autoIdentifyOrganize: z.boolean(),
|
||||
/** 后台自动调查的工具调用上限(比用户委托更小) */
|
||||
investigateMaxToolCalls: z.number().int().min(1).max(100),
|
||||
/** 等待目标关联的下载/入库结束时的轮询间隔(秒) */
|
||||
@@ -432,8 +434,10 @@ export const BudgetSettings = z.object({
|
||||
maxNewTitlesPerDay: z.number().int().min(0),
|
||||
maxDownloadBytesPerDay: z.number().int().min(0),
|
||||
maxConcurrentDownloads: z.number().int().min(1).max(100),
|
||||
agentMaxRunsPerDay: z.number().int().min(0),
|
||||
agentMaxCostUsdPerDay: z.number().min(0),
|
||||
/** 已弃用(2026-10-06 起智能体不设每日次数上限,旧值兼容读取、不生效) */
|
||||
agentMaxRunsPerDay: z.number().int().min(0).optional(),
|
||||
/** 已弃用(2026-10-06 起智能体不设每日费用上限,旧值兼容读取、不生效) */
|
||||
agentMaxCostUsdPerDay: z.number().min(0).optional(),
|
||||
});
|
||||
export type BudgetSettings = z.infer<typeof BudgetSettings>;
|
||||
|
||||
@@ -667,19 +671,16 @@ export const DEFAULT_SETTINGS: GlobalSettings = {
|
||||
maxNewTitlesPerDay: 20,
|
||||
maxDownloadBytesPerDay: 500 * 1024 ** 3,
|
||||
maxConcurrentDownloads: 5,
|
||||
agentMaxRunsPerDay: 50,
|
||||
agentMaxCostUsdPerDay: 5,
|
||||
},
|
||||
agent: {
|
||||
autoInvestigate: false,
|
||||
autoInvestigateMode: "investigate",
|
||||
investigateMaxAttempts: 2,
|
||||
recoverVerifySec: 600,
|
||||
maxToolCalls: 40,
|
||||
maxDurationSec: 900,
|
||||
maxTokensPerRun: null,
|
||||
maxCostUsdPerRun: null,
|
||||
investigateMaxToolCalls: 8,
|
||||
maxToolCalls: 120,
|
||||
maxDurationSec: 1800,
|
||||
autoIdentifyOrganize: true,
|
||||
investigateMaxToolCalls: 20,
|
||||
goalPollSec: 60,
|
||||
goalWaitHours: 72,
|
||||
optionsTimeoutSec: 1800,
|
||||
@@ -858,6 +859,11 @@ export const DEPRECATED_SETTINGS_FIELDS = [
|
||||
"cache.tmdbTtlHours",
|
||||
"cache.emptyResultTtlSec",
|
||||
"identity.poolArchiveDays",
|
||||
// 2026-10-06:智能体不设硬性预算上限,只保留单次工具调用次数与时长两个防跑飞限制
|
||||
"budget.agentMaxRunsPerDay",
|
||||
"budget.agentMaxCostUsdPerDay",
|
||||
"agent.maxTokensPerRun",
|
||||
"agent.maxCostUsdPerRun",
|
||||
] as const;
|
||||
|
||||
// ── 设置页分区(docs/design/console-ia.md §3.4) ──
|
||||
@@ -1027,12 +1033,12 @@ export const SETTINGS_SECTIONS: readonly SettingsSectionDef[] = [
|
||||
{
|
||||
id: "agent",
|
||||
label: "智能体",
|
||||
description: "模型服务、运行预算、自动调查、网页搜索",
|
||||
description: "模型服务、用量与限制、自动调查、网页搜索",
|
||||
legacyTabs: [{ tab: "pi" }],
|
||||
anchors: [
|
||||
{ id: "upstream", label: "模型服务" },
|
||||
{ id: "runtime", label: "上下文与子会话" },
|
||||
{ id: "budget", label: "预算" },
|
||||
{ id: "budget", label: "用量与限制" },
|
||||
{ id: "investigate", label: "自动调查" },
|
||||
{ id: "websearch", label: "网页搜索" },
|
||||
{ id: "advanced", label: "高级" },
|
||||
@@ -1045,16 +1051,13 @@ export const SETTINGS_SECTIONS: readonly SettingsSectionDef[] = [
|
||||
"pi.compaction",
|
||||
"pi.subagentsEnabled",
|
||||
"pi.subagents",
|
||||
"budget.agentMaxRunsPerDay",
|
||||
"budget.agentMaxCostUsdPerDay",
|
||||
"agent.autoInvestigate",
|
||||
"agent.autoIdentifyOrganize",
|
||||
"agent.autoInvestigateMode",
|
||||
"agent.investigateMaxAttempts",
|
||||
"agent.recoverVerifySec",
|
||||
"agent.maxToolCalls",
|
||||
"agent.maxDurationSec",
|
||||
"agent.maxTokensPerRun",
|
||||
"agent.maxCostUsdPerRun",
|
||||
"agent.investigateMaxToolCalls",
|
||||
"agent.goalPollSec",
|
||||
"agent.goalWaitHours",
|
||||
|
||||
@@ -12,7 +12,7 @@ describe("reasonText(DEAI-2 原因码人话化)", () => {
|
||||
|
||||
it("下载面板用到的码(DL-2b):整理失败、冲突、下载被删", () => {
|
||||
expect(reasonSentence("transfer_failed")).toBe("文件没有整理成功。在整理记录里查看失败的文件");
|
||||
expect(reasonSentence("blocked")).toBe("有冲突要先处理。去待处理");
|
||||
expect(reasonSentence("blocked")).toBe("有冲突要先处理。在整理记录里处理");
|
||||
expect(reasonText("download_removed")?.text).toBe("下载任务已从下载器删除");
|
||||
expect(reasonText("target_root_not_managed")?.text).toContain("本工具管理");
|
||||
for (const c of ["blocked_by_conflict", "main_failed", "not_imported_kind"]) expect(reasonText(c)).not.toBeNull();
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
import type { Kysely } from "kysely";
|
||||
import { execDdl } from "../src/migration-helpers.ts";
|
||||
|
||||
// 整理记录「需要处理」(2026-10-06,去掉待处理中心):失败 / 部分完成的记录在整理记录里就地处理;
|
||||
// 用户点「忽略」时记下时间,该记录不再算「需要处理」(关联的未关闭事项一并关闭)。
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: 迁移不依赖应用表类型
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await execDdl(db, `alter table organization_record add column attention_cleared_at timestamptz;`);
|
||||
}
|
||||
|
||||
// biome-ignore lint/suspicious/noExplicitAny: 同上
|
||||
export async function down(db: Kysely<any>): Promise<void> {
|
||||
await execDdl(db, `alter table organization_record drop column if exists attention_cleared_at;`);
|
||||
}
|
||||
@@ -1093,6 +1093,7 @@ export interface OrganizationRecordTable {
|
||||
updated_at: GeneratedTimestamptz;
|
||||
requeue_count: Generated<number>;
|
||||
requeued_at: Timestamptz | null;
|
||||
attention_cleared_at: Timestamptz | null;
|
||||
}
|
||||
|
||||
export interface OrganizeSourceSnapshotTable {
|
||||
|
||||
Reference in new issue
Block a user